diff --git a/.changeset/chubby-dots-kiss.md b/.changeset/chubby-dots-kiss.md new file mode 100644 index 0000000000..7a28467725 --- /dev/null +++ b/.changeset/chubby-dots-kiss.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Fixed an issue causing TechDocs to not properly handle initial redirect. diff --git a/.changeset/clear-bananas-end.md b/.changeset/clear-bananas-end.md new file mode 100644 index 0000000000..50e722544c --- /dev/null +++ b/.changeset/clear-bananas-end.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-graph': patch +--- + +Catalog graph plugin support i18n diff --git a/.changeset/create-app-1751370514.md b/.changeset/create-app-1751370514.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1751370514.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/curly-zoos-thank.md b/.changeset/curly-zoos-thank.md new file mode 100644 index 0000000000..ec55b2abb9 --- /dev/null +++ b/.changeset/curly-zoos-thank.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +We are consolidating all css files into a single styles.css in Canon. diff --git a/.changeset/cyan-islands-swim.md b/.changeset/cyan-islands-swim.md new file mode 100644 index 0000000000..396cc6fc68 --- /dev/null +++ b/.changeset/cyan-islands-swim.md @@ -0,0 +1,14 @@ +--- +'@backstage/plugin-catalog-backend': major +'@backstage/create-app': patch +--- + +**BREAKING:** The experimental `catalog.useUrlReadersSearch` configuration flag (introduced in v1.36) has been removed. + +The `UrlReaderProcessor` now always uses the `search` method of `UrlReaders`. Built-in `UrlReaderService` implementations have been updated accordingly. +If you use custom `UrlReaderService` implementations, you need to adapt their `search` method to correctly handle both specific URLs and potential +search patterns (see changes on built-in readers [in the original PR](https://github.com/backstage/backstage/pull/28379/files#diff-68b0452f173ee54bdd40f7b5e047a9cb8bb59200425622c212c217b76dac1d1b)). + +Previous behavior was to call the `search` method only if the parsed Git URL's filename contained a wildcard and use `readUrl` otherwise. Each `UrlReaderService` must implement this logic in the `search` method instead. + +This allows each `UrlReaderService` implementation to check whether it's a search URL (that contains a wildcard pattern) or not using logic that is specific to each provider. diff --git a/.changeset/dark-cougars-go.md b/.changeset/dark-cougars-go.md new file mode 100644 index 0000000000..f835dd2658 --- /dev/null +++ b/.changeset/dark-cougars-go.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Add new SearchField component in Canon diff --git a/.changeset/dry-hornets-stop.md b/.changeset/dry-hornets-stop.md new file mode 100644 index 0000000000..4979d463a8 --- /dev/null +++ b/.changeset/dry-hornets-stop.md @@ -0,0 +1,6 @@ +--- +'@backstage/config-loader': patch +'@backstage/config': patch +--- + +Loosen the requirements for a key to be considered valid config. diff --git a/.changeset/early-trains-relax.md b/.changeset/early-trains-relax.md new file mode 100644 index 0000000000..179e224681 --- /dev/null +++ b/.changeset/early-trains-relax.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Add new Header component to Canon. diff --git a/.changeset/eleven-pans-turn.md b/.changeset/eleven-pans-turn.md new file mode 100644 index 0000000000..a929928114 --- /dev/null +++ b/.changeset/eleven-pans-turn.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +'@backstage/plugin-search-backend-module-elasticsearch': patch +'@backstage/backend-dynamic-feature-service': patch +'@backstage/plugin-catalog-backend-module-puppetdb': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-catalog-backend-module-ldap': patch +'@backstage/frontend-app-api': patch +'@backstage/plugin-permission-common': patch +'@backstage/plugin-kubernetes-node': patch +'@backstage/plugin-permission-node': patch +'@backstage/catalog-model': patch +'@backstage/plugin-catalog-react': patch +'@backstage/config': patch +--- + +Just some more circular dep cleanup diff --git a/.changeset/empty-mugs-agree.md b/.changeset/empty-mugs-agree.md new file mode 100644 index 0000000000..80dd35b8cf --- /dev/null +++ b/.changeset/empty-mugs-agree.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Filter MultiEntityPicker options based on rendered option value diff --git a/.changeset/empty-poets-give.md b/.changeset/empty-poets-give.md new file mode 100644 index 0000000000..2eb63c2ed5 --- /dev/null +++ b/.changeset/empty-poets-give.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Add new `RadioGroup` + `Radio` component to Canon diff --git a/.changeset/fancy-nails-call.md b/.changeset/fancy-nails-call.md new file mode 100644 index 0000000000..556b358dfa --- /dev/null +++ b/.changeset/fancy-nails-call.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-incremental-ingestion': patch +--- + +Fixed bug in `IncrementalIngestionEngine` by adding `burstLength` check when a burst completes diff --git a/.changeset/fuzzy-cooks-dress.md b/.changeset/fuzzy-cooks-dress.md new file mode 100644 index 0000000000..77fab62647 --- /dev/null +++ b/.changeset/fuzzy-cooks-dress.md @@ -0,0 +1,5 @@ +--- +'yarn-plugin-backstage': patch +--- + +Fixed a bug that would prevent the yarn plugin from installing new dependencies with the `backstage:^` protocol. diff --git a/.changeset/gentle-llamas-press.md b/.changeset/gentle-llamas-press.md new file mode 100644 index 0000000000..9c922d396f --- /dev/null +++ b/.changeset/gentle-llamas-press.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-defaults': patch +'@backstage/backend-test-utils': minor +--- + +Add a standard `toString` on credentials objects diff --git a/.changeset/good-paths-act.md b/.changeset/good-paths-act.md deleted file mode 100644 index dc33b43766..0000000000 --- a/.changeset/good-paths-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': patch ---- - -Fix an issue where errors were not printed to console when running `backstage-repo-tools schema openapi generate` without the `--watch` flag. diff --git a/.changeset/mean-lemons-dream.md b/.changeset/mean-lemons-dream.md new file mode 100644 index 0000000000..fdf7f29017 --- /dev/null +++ b/.changeset/mean-lemons-dream.md @@ -0,0 +1,5 @@ +--- +'@backstage/repo-tools': minor +--- + +Clear output directory before running `package-docs` and skip all internal packages. diff --git a/.changeset/odd-clubs-teach.md b/.changeset/odd-clubs-teach.md new file mode 100644 index 0000000000..79b91ad2fb --- /dev/null +++ b/.changeset/odd-clubs-teach.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-dynamic-feature-service': patch +--- + +Fix wrong imports which lead to module initialization failures when enabling dynamic plugins. diff --git a/.changeset/petite-paths-remain.md b/.changeset/petite-paths-remain.md new file mode 100644 index 0000000000..a2bef50c80 --- /dev/null +++ b/.changeset/petite-paths-remain.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-scaffolder-node-test-utils': patch +'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder-node': patch +--- + +An internal refactor which adds additional types to experimental checkpoints diff --git a/.changeset/pre.json b/.changeset/pre.json index c09d56c9d4..8d5daefe90 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -2,204 +2,239 @@ "mode": "pre", "tag": "next", "initialVersions": { - "example-app": "0.2.109", - "@backstage/app-defaults": "1.6.2", - "example-app-next": "0.0.23", - "app-next-example-plugin": "0.0.23", - "example-backend": "0.0.38", - "@backstage/backend-app-api": "1.2.3", - "@backstage/backend-defaults": "0.10.0", + "example-app": "0.2.110", + "@backstage/app-defaults": "1.6.3", + "example-app-next": "0.0.24", + "app-next-example-plugin": "0.0.24", + "example-backend": "0.0.39", + "@backstage/backend-app-api": "1.2.4", + "@backstage/backend-defaults": "0.11.0", "@backstage/backend-dev-utils": "0.1.5", - "@backstage/backend-dynamic-feature-service": "0.7.0", - "@backstage/backend-openapi-utils": "0.5.3", - "@backstage/backend-plugin-api": "1.3.1", - "@backstage/backend-test-utils": "1.5.0", - "@backstage/canon": "0.4.0", - "@backstage/catalog-client": "1.10.0", + "@backstage/backend-dynamic-feature-service": "0.7.1", + "@backstage/backend-openapi-utils": "0.5.4", + "@backstage/backend-plugin-api": "1.4.0", + "@backstage/backend-test-utils": "1.6.0", + "@backstage/canon": "0.5.0", + "@backstage/catalog-client": "1.10.1", "@backstage/catalog-model": "1.7.4", - "@backstage/cli": "0.32.1", + "@backstage/cli": "0.33.0", "@backstage/cli-common": "0.1.15", "@backstage/cli-node": "0.2.13", "@backstage/codemods": "0.1.52", "@backstage/config": "1.3.2", "@backstage/config-loader": "1.10.1", - "@backstage/core-app-api": "1.17.0", - "@backstage/core-compat-api": "0.4.2", - "@backstage/core-components": "0.17.2", - "@backstage/core-plugin-api": "1.10.7", - "@backstage/create-app": "0.6.2", - "@backstage/dev-utils": "1.1.10", - "e2e-test": "0.2.28", + "@backstage/core-app-api": "1.17.1", + "@backstage/core-compat-api": "0.4.3", + "@backstage/core-components": "0.17.3", + "@backstage/core-plugin-api": "1.10.8", + "@backstage/create-app": "0.7.0", + "@backstage/dev-utils": "1.1.11", + "e2e-test": "0.2.29", "@backstage/e2e-test-utils": "0.1.1", "@backstage/errors": "1.2.7", - "@backstage/eslint-plugin": "0.1.10", - "@backstage/frontend-app-api": "0.11.2", - "@backstage/frontend-defaults": "0.2.2", - "@backstage/frontend-dynamic-feature-loader": "0.1.1", - "@internal/frontend": "0.0.9", - "@backstage/frontend-plugin-api": "0.10.2", - "@backstage/frontend-test-utils": "0.3.2", + "@backstage/eslint-plugin": "0.1.11", + "@backstage/frontend-app-api": "0.11.3", + "@backstage/frontend-defaults": "0.2.3", + "@backstage/frontend-dynamic-feature-loader": "0.1.2", + "@internal/frontend": "0.0.10", + "@backstage/frontend-plugin-api": "0.10.3", + "@backstage/frontend-test-utils": "0.3.3", "@backstage/integration": "1.17.0", "@backstage/integration-aws-node": "0.1.16", - "@backstage/integration-react": "1.2.7", + "@backstage/integration-react": "1.2.8", "@internal/opaque": "0.0.1", "@backstage/release-manifests": "0.0.13", - "@backstage/repo-tools": "0.13.3", - "@internal/scaffolder": "0.0.9", - "@techdocs/cli": "1.9.3", - "techdocs-cli-embedded-app": "0.2.108", - "@backstage/test-utils": "1.7.8", + "@backstage/repo-tools": "0.14.0", + "@internal/scaffolder": "0.0.10", + "@techdocs/cli": "1.9.4", + "techdocs-cli-embedded-app": "0.2.109", + "@backstage/test-utils": "1.7.9", "@backstage/theme": "0.6.6", "@backstage/types": "1.2.1", "@backstage/version-bridge": "1.0.11", - "yarn-plugin-backstage": "0.0.5", - "@backstage/plugin-api-docs": "0.12.7", + "yarn-plugin-backstage": "0.0.6", + "@backstage/plugin-api-docs": "0.12.8", "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.10", - "@backstage/plugin-app": "0.1.9", - "@backstage/plugin-app-backend": "0.5.2", - "@backstage/plugin-app-node": "0.1.33", - "@backstage/plugin-app-visualizer": "0.1.19", - "@backstage/plugin-auth-backend": "0.25.0", - "@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.3", - "@backstage/plugin-auth-backend-module-auth0-provider": "0.2.3", - "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.3", - "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.8", - "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.3", - "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.3", - "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.3", - "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.3", - "@backstage/plugin-auth-backend-module-github-provider": "0.3.3", - "@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.3", - "@backstage/plugin-auth-backend-module-google-provider": "0.3.3", - "@backstage/plugin-auth-backend-module-guest-provider": "0.2.8", - "@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.3", - "@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.3", - "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.8", - "@backstage/plugin-auth-backend-module-oidc-provider": "0.4.3", - "@backstage/plugin-auth-backend-module-okta-provider": "0.2.3", - "@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.3", - "@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.3", - "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.3", - "@backstage/plugin-auth-node": "0.6.3", - "@backstage/plugin-auth-react": "0.1.15", + "@backstage/plugin-app": "0.1.10", + "@backstage/plugin-app-backend": "0.5.3", + "@backstage/plugin-app-node": "0.1.34", + "@backstage/plugin-app-visualizer": "0.1.20", + "@backstage/plugin-auth-backend": "0.25.1", + "@backstage/plugin-auth-backend-module-atlassian-provider": "0.4.4", + "@backstage/plugin-auth-backend-module-auth0-provider": "0.2.4", + "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.4.4", + "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.2.9", + "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.3.4", + "@backstage/plugin-auth-backend-module-bitbucket-server-provider": "0.2.4", + "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.4.4", + "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.4.4", + "@backstage/plugin-auth-backend-module-github-provider": "0.3.4", + "@backstage/plugin-auth-backend-module-gitlab-provider": "0.3.4", + "@backstage/plugin-auth-backend-module-google-provider": "0.3.4", + "@backstage/plugin-auth-backend-module-guest-provider": "0.2.9", + "@backstage/plugin-auth-backend-module-microsoft-provider": "0.3.4", + "@backstage/plugin-auth-backend-module-oauth2-provider": "0.4.4", + "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.2.9", + "@backstage/plugin-auth-backend-module-oidc-provider": "0.4.4", + "@backstage/plugin-auth-backend-module-okta-provider": "0.2.4", + "@backstage/plugin-auth-backend-module-onelogin-provider": "0.3.4", + "@backstage/plugin-auth-backend-module-pinniped-provider": "0.3.4", + "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.5.4", + "@backstage/plugin-auth-node": "0.6.4", + "@backstage/plugin-auth-react": "0.1.16", "@backstage/plugin-bitbucket-cloud-common": "0.3.0", - "@backstage/plugin-catalog": "1.30.0", - "@backstage/plugin-catalog-backend": "2.0.0", - "@backstage/plugin-catalog-backend-module-aws": "0.4.11", - "@backstage/plugin-catalog-backend-module-azure": "0.3.5", - "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.2", - "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.4.8", - "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.4.1", - "@backstage/plugin-catalog-backend-module-gcp": "0.3.8", - "@backstage/plugin-catalog-backend-module-gerrit": "0.3.2", - "@backstage/plugin-catalog-backend-module-gitea": "0.1.0", - "@backstage/plugin-catalog-backend-module-github": "0.9.0", - "@backstage/plugin-catalog-backend-module-github-org": "0.3.10", - "@backstage/plugin-catalog-backend-module-gitlab": "0.6.6", - "@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.9", - "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.7.0", - "@backstage/plugin-catalog-backend-module-ldap": "0.11.5", - "@backstage/plugin-catalog-backend-module-logs": "0.1.10", - "@backstage/plugin-catalog-backend-module-msgraph": "0.7.0", - "@backstage/plugin-catalog-backend-module-openapi": "0.2.10", - "@backstage/plugin-catalog-backend-module-puppetdb": "0.2.10", - "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.8", - "@backstage/plugin-catalog-backend-module-unprocessed": "0.6.0", + "@backstage/plugin-catalog": "1.31.0", + "@backstage/plugin-catalog-backend": "2.1.0", + "@backstage/plugin-catalog-backend-module-aws": "0.4.12", + "@backstage/plugin-catalog-backend-module-azure": "0.3.6", + "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.5.3", + "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.5.0", + "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.5.0", + "@backstage/plugin-catalog-backend-module-gcp": "0.3.9", + "@backstage/plugin-catalog-backend-module-gerrit": "0.3.3", + "@backstage/plugin-catalog-backend-module-gitea": "0.1.1", + "@backstage/plugin-catalog-backend-module-github": "0.10.0", + "@backstage/plugin-catalog-backend-module-github-org": "0.3.11", + "@backstage/plugin-catalog-backend-module-gitlab": "0.7.0", + "@backstage/plugin-catalog-backend-module-gitlab-org": "0.2.10", + "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.7.1", + "@backstage/plugin-catalog-backend-module-ldap": "0.11.6", + "@backstage/plugin-catalog-backend-module-logs": "0.1.11", + "@backstage/plugin-catalog-backend-module-msgraph": "0.7.1", + "@backstage/plugin-catalog-backend-module-openapi": "0.2.11", + "@backstage/plugin-catalog-backend-module-puppetdb": "0.2.11", + "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.2.9", + "@backstage/plugin-catalog-backend-module-unprocessed": "0.6.1", "@backstage/plugin-catalog-common": "1.1.4", - "@backstage/plugin-catalog-graph": "0.4.19", - "@backstage/plugin-catalog-import": "0.13.0", - "@backstage/plugin-catalog-node": "1.17.0", - "@backstage/plugin-catalog-react": "1.18.0", - "@backstage/plugin-catalog-unprocessed-entities": "0.2.17", + "@backstage/plugin-catalog-graph": "0.4.20", + "@backstage/plugin-catalog-import": "0.13.1", + "@backstage/plugin-catalog-node": "1.17.1", + "@backstage/plugin-catalog-react": "1.19.0", + "@backstage/plugin-catalog-unprocessed-entities": "0.2.18", "@backstage/plugin-catalog-unprocessed-entities-common": "0.0.8", - "@backstage/plugin-config-schema": "0.1.68", - "@backstage/plugin-devtools": "0.1.27", - "@backstage/plugin-devtools-backend": "0.5.5", + "@backstage/plugin-config-schema": "0.1.69", + "@backstage/plugin-devtools": "0.1.28", + "@backstage/plugin-devtools-backend": "0.5.6", "@backstage/plugin-devtools-common": "0.1.16", - "@backstage/plugin-events-backend": "0.5.2", - "@backstage/plugin-events-backend-module-aws-sqs": "0.4.11", - "@backstage/plugin-events-backend-module-azure": "0.2.20", - "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.20", - "@backstage/plugin-events-backend-module-bitbucket-server": "0.1.1", - "@backstage/plugin-events-backend-module-gerrit": "0.2.20", - "@backstage/plugin-events-backend-module-github": "0.4.0", - "@backstage/plugin-events-backend-module-gitlab": "0.3.1", - "@backstage/plugin-events-backend-module-google-pubsub": "0.1.0", - "@backstage/plugin-events-backend-test-utils": "0.1.44", - "@backstage/plugin-events-node": "0.4.11", - "@internal/plugin-todo-list": "1.0.39", - "@internal/plugin-todo-list-backend": "1.0.39", + "@backstage/plugin-events-backend": "0.5.3", + "@backstage/plugin-events-backend-module-aws-sqs": "0.4.12", + "@backstage/plugin-events-backend-module-azure": "0.2.21", + "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.21", + "@backstage/plugin-events-backend-module-bitbucket-server": "0.1.2", + "@backstage/plugin-events-backend-module-gerrit": "0.2.21", + "@backstage/plugin-events-backend-module-github": "0.4.1", + "@backstage/plugin-events-backend-module-gitlab": "0.3.2", + "@backstage/plugin-events-backend-module-google-pubsub": "0.1.1", + "@backstage/plugin-events-backend-module-kafka": "0.1.0", + "@backstage/plugin-events-backend-test-utils": "0.1.45", + "@backstage/plugin-events-node": "0.4.12", + "@internal/plugin-todo-list": "1.0.40", + "@internal/plugin-todo-list-backend": "1.0.40", "@internal/plugin-todo-list-common": "1.0.25", - "@backstage/plugin-gateway-backend": "1.0.1", - "@backstage/plugin-home": "0.8.8", - "@backstage/plugin-home-react": "0.1.26", - "@backstage/plugin-kubernetes": "0.12.7", - "@backstage/plugin-kubernetes-backend": "0.19.6", - "@backstage/plugin-kubernetes-cluster": "0.0.25", + "@backstage/plugin-gateway-backend": "1.0.2", + "@backstage/plugin-home": "0.8.9", + "@backstage/plugin-home-react": "0.1.27", + "@backstage/plugin-kubernetes": "0.12.8", + "@backstage/plugin-kubernetes-backend": "0.19.7", + "@backstage/plugin-kubernetes-cluster": "0.0.26", "@backstage/plugin-kubernetes-common": "0.9.5", - "@backstage/plugin-kubernetes-node": "0.3.0", - "@backstage/plugin-kubernetes-react": "0.5.7", - "@backstage/plugin-notifications": "0.5.5", - "@backstage/plugin-notifications-backend": "0.5.6", - "@backstage/plugin-notifications-backend-module-email": "0.3.9", - "@backstage/plugin-notifications-backend-module-slack": "0.1.1", - "@backstage/plugin-notifications-common": "0.0.8", - "@backstage/plugin-notifications-node": "0.2.15", - "@backstage/plugin-org": "0.6.39", - "@backstage/plugin-org-react": "0.1.38", - "@backstage/plugin-permission-backend": "0.7.0", - "@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.8", + "@backstage/plugin-kubernetes-node": "0.3.1", + "@backstage/plugin-kubernetes-react": "0.5.8", + "@backstage/plugin-mcp-actions-backend": "0.1.0", + "@backstage/plugin-notifications": "0.5.6", + "@backstage/plugin-notifications-backend": "0.5.7", + "@backstage/plugin-notifications-backend-module-email": "0.3.10", + "@backstage/plugin-notifications-backend-module-slack": "0.1.2", + "@backstage/plugin-notifications-common": "0.0.9", + "@backstage/plugin-notifications-node": "0.2.16", + "@backstage/plugin-org": "0.6.40", + "@backstage/plugin-org-react": "0.1.39", + "@backstage/plugin-permission-backend": "0.7.1", + "@backstage/plugin-permission-backend-module-allow-all-policy": "0.2.9", "@backstage/plugin-permission-common": "0.9.0", - "@backstage/plugin-permission-node": "0.10.0", - "@backstage/plugin-permission-react": "0.4.34", - "@backstage/plugin-proxy-backend": "0.6.2", - "@backstage/plugin-proxy-node": "0.1.4", - "@backstage/plugin-scaffolder": "1.31.0", - "@backstage/plugin-scaffolder-backend": "1.33.0", - "@backstage/plugin-scaffolder-backend-module-azure": "0.2.9", - "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.10", - "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.9", - "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.9", - "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.9", - "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.10", - "@backstage/plugin-scaffolder-backend-module-gcp": "0.2.9", - "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.9", - "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.9", - "@backstage/plugin-scaffolder-backend-module-github": "0.7.1", - "@backstage/plugin-scaffolder-backend-module-gitlab": "0.9.1", - "@backstage/plugin-scaffolder-backend-module-notifications": "0.1.10", - "@backstage/plugin-scaffolder-backend-module-rails": "0.5.9", - "@backstage/plugin-scaffolder-backend-module-sentry": "0.2.9", - "@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.10", + "@backstage/plugin-permission-node": "0.10.1", + "@backstage/plugin-permission-react": "0.4.35", + "@backstage/plugin-proxy-backend": "0.6.3", + "@backstage/plugin-proxy-node": "0.1.5", + "@backstage/plugin-scaffolder": "1.32.0", + "@backstage/plugin-scaffolder-backend": "2.0.0", + "@backstage/plugin-scaffolder-backend-module-azure": "0.2.10", + "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.3.11", + "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.2.10", + "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.2.10", + "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.3.10", + "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.3.11", + "@backstage/plugin-scaffolder-backend-module-gcp": "0.2.10", + "@backstage/plugin-scaffolder-backend-module-gerrit": "0.2.10", + "@backstage/plugin-scaffolder-backend-module-gitea": "0.2.10", + "@backstage/plugin-scaffolder-backend-module-github": "0.8.0", + "@backstage/plugin-scaffolder-backend-module-gitlab": "0.9.2", + "@backstage/plugin-scaffolder-backend-module-notifications": "0.1.11", + "@backstage/plugin-scaffolder-backend-module-rails": "0.5.10", + "@backstage/plugin-scaffolder-backend-module-sentry": "0.2.10", + "@backstage/plugin-scaffolder-backend-module-yeoman": "0.4.11", "@backstage/plugin-scaffolder-common": "1.5.11", - "@backstage/plugin-scaffolder-node": "0.8.2", - "@backstage/plugin-scaffolder-node-test-utils": "0.2.2", - "@backstage/plugin-scaffolder-react": "1.16.0", - "@backstage/plugin-search": "1.4.26", - "@backstage/plugin-search-backend": "2.0.2", - "@backstage/plugin-search-backend-module-catalog": "0.3.4", - "@backstage/plugin-search-backend-module-elasticsearch": "1.7.2", - "@backstage/plugin-search-backend-module-explore": "0.3.2", - "@backstage/plugin-search-backend-module-pg": "0.5.44", - "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.9", - "@backstage/plugin-search-backend-module-techdocs": "0.4.2", - "@backstage/plugin-search-backend-node": "1.3.11", + "@backstage/plugin-scaffolder-node": "0.9.0", + "@backstage/plugin-scaffolder-node-test-utils": "0.3.0", + "@backstage/plugin-scaffolder-react": "1.17.0", + "@backstage/plugin-search": "1.4.27", + "@backstage/plugin-search-backend": "2.0.3", + "@backstage/plugin-search-backend-module-catalog": "0.3.5", + "@backstage/plugin-search-backend-module-elasticsearch": "1.7.3", + "@backstage/plugin-search-backend-module-explore": "0.3.3", + "@backstage/plugin-search-backend-module-pg": "0.5.45", + "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.3.10", + "@backstage/plugin-search-backend-module-techdocs": "0.4.3", + "@backstage/plugin-search-backend-node": "1.3.12", "@backstage/plugin-search-common": "1.2.18", - "@backstage/plugin-search-react": "1.9.0", - "@backstage/plugin-signals": "0.0.19", - "@backstage/plugin-signals-backend": "0.3.4", - "@backstage/plugin-signals-node": "0.1.20", - "@backstage/plugin-signals-react": "0.0.13", - "@backstage/plugin-techdocs": "1.12.6", - "@backstage/plugin-techdocs-addons-test-utils": "1.0.48", - "@backstage/plugin-techdocs-backend": "2.0.2", - "@backstage/plugin-techdocs-common": "0.1.0", - "@backstage/plugin-techdocs-module-addons-contrib": "1.1.24", - "@backstage/plugin-techdocs-node": "1.13.3", - "@backstage/plugin-techdocs-react": "1.2.17", - "@backstage/plugin-user-settings": "0.8.22", - "@backstage/plugin-user-settings-backend": "0.3.2", + "@backstage/plugin-search-react": "1.9.1", + "@backstage/plugin-signals": "0.0.20", + "@backstage/plugin-signals-backend": "0.3.5", + "@backstage/plugin-signals-node": "0.1.21", + "@backstage/plugin-signals-react": "0.0.14", + "@backstage/plugin-techdocs": "1.13.0", + "@backstage/plugin-techdocs-addons-test-utils": "1.0.49", + "@backstage/plugin-techdocs-backend": "2.0.3", + "@backstage/plugin-techdocs-common": "0.1.1", + "@backstage/plugin-techdocs-module-addons-contrib": "1.1.25", + "@backstage/plugin-techdocs-node": "1.13.4", + "@backstage/plugin-techdocs-react": "1.3.0", + "@backstage/plugin-user-settings": "0.8.23", + "@backstage/plugin-user-settings-backend": "0.3.3", "@backstage/plugin-user-settings-common": "0.0.1" }, - "changesets": [] + "changesets": [ + "chubby-dots-kiss", + "clear-bananas-end", + "create-app-1751370514", + "curly-zoos-thank", + "cyan-islands-swim", + "dark-cougars-go", + "dry-hornets-stop", + "eleven-pans-turn", + "empty-mugs-agree", + "empty-poets-give", + "fancy-nails-call", + "fuzzy-cooks-dress", + "gentle-llamas-press", + "mean-lemons-dream", + "odd-clubs-teach", + "petite-paths-remain", + "public-nails-melt", + "red-trams-join", + "rich-eagles-rule", + "shaggy-cobras-rhyme", + "shaky-parents-enter", + "sharp-stars-report", + "silent-vans-tie", + "six-dots-agree", + "sixty-ties-matter", + "social-insects-cheat", + "stupid-donuts-sit", + "three-shoes-behave", + "tired-bats-attend", + "wicked-socks-share", + "wise-frogs-talk", + "yummy-pugs-battle" + ] } diff --git a/.changeset/public-nails-melt.md b/.changeset/public-nails-melt.md new file mode 100644 index 0000000000..1529ee94d0 --- /dev/null +++ b/.changeset/public-nails-melt.md @@ -0,0 +1,13 @@ +--- +'@backstage/canon': minor +--- + +**BREAKING CHANGES** + +We’re updating our Button component to provide better support for button links. + +- We’re introducing a new `ButtonLink` component, which replaces the previous render prop pattern. +- To maintain naming consistency across components, `IconButton` is being renamed to `ButtonIcon`. +- Additionally, the render prop will be removed from all button-related components. + +These changes aim to simplify usage and improve clarity in our component API. diff --git a/.changeset/red-trams-join.md b/.changeset/red-trams-join.md new file mode 100644 index 0000000000..3ee245e2a8 --- /dev/null +++ b/.changeset/red-trams-join.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-notifications-backend': patch +--- + +Fix `addTopic` migration when `user_settings` present diff --git a/.changeset/rich-eagles-rule.md b/.changeset/rich-eagles-rule.md new file mode 100644 index 0000000000..100ccafb77 --- /dev/null +++ b/.changeset/rich-eagles-rule.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-mcp-actions-backend': patch +--- + +Fixed the example in the README for generating a static token by adding a subject field diff --git a/.changeset/salty-worlds-float.md b/.changeset/salty-worlds-float.md deleted file mode 100644 index a21d0b2e7c..0000000000 --- a/.changeset/salty-worlds-float.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/create-app': minor ---- - -Add .cache directory to shipped gitignore. diff --git a/.changeset/seven-sloths-kick.md b/.changeset/seven-sloths-kick.md new file mode 100644 index 0000000000..a33924efc7 --- /dev/null +++ b/.changeset/seven-sloths-kick.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Update return types for Heading & Text components for React 19. diff --git a/.changeset/shaggy-cobras-rhyme.md b/.changeset/shaggy-cobras-rhyme.md new file mode 100644 index 0000000000..d8adefd112 --- /dev/null +++ b/.changeset/shaggy-cobras-rhyme.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +We are transforming how we structure our class names and data attributes definitions for all components. They are now all set in the same place. diff --git a/.changeset/shaky-parents-enter.md b/.changeset/shaky-parents-enter.md new file mode 100644 index 0000000000..5e81402bed --- /dev/null +++ b/.changeset/shaky-parents-enter.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': patch +--- + +allow arrays in the InMemoryCatalogClient to filter entities diff --git a/.changeset/sharp-stars-report.md b/.changeset/sharp-stars-report.md new file mode 100644 index 0000000000..c37e0e39ea --- /dev/null +++ b/.changeset/sharp-stars-report.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Replaced deprecated uses of `@backstage/backend-common` with the equivalents in `@backstage/backend-defaults` and `@backstage/backend-plugin-api`. diff --git a/.changeset/silent-vans-tie.md b/.changeset/silent-vans-tie.md new file mode 100644 index 0000000000..b81564be7e --- /dev/null +++ b/.changeset/silent-vans-tie.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Added placeholder prop to TextField component. diff --git a/.changeset/six-dots-agree.md b/.changeset/six-dots-agree.md new file mode 100644 index 0000000000..97f9b3017f --- /dev/null +++ b/.changeset/six-dots-agree.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-defaults': patch +'@backstage/integration': patch +--- + +UrlReader: Fix handling of access tokens for GitLab readURL requests diff --git a/.changeset/six-mangos-yell.md b/.changeset/six-mangos-yell.md deleted file mode 100644 index 65ddae86f8..0000000000 --- a/.changeset/six-mangos-yell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/repo-tools': minor ---- - -Add support for caching the per-package output from the `package-docs` command. diff --git a/.changeset/sixty-ties-matter.md b/.changeset/sixty-ties-matter.md new file mode 100644 index 0000000000..3be0bb08a8 --- /dev/null +++ b/.changeset/sixty-ties-matter.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-cookiecutter': patch +--- + +Fixing the typescript issue with using `z.unknown()` diff --git a/.changeset/social-insects-cheat.md b/.changeset/social-insects-cheat.md new file mode 100644 index 0000000000..494cba15e7 --- /dev/null +++ b/.changeset/social-insects-cheat.md @@ -0,0 +1,21 @@ +--- +'@backstage/plugin-scaffolder-backend-module-github': patch +--- + +Added support for file deletion to `publish:github:pull-request` action. + +Example usage: + +```diff + - action: publish:github:pull-request + id: clean-up-pr + input: + description: This is the description ++ filesToDelete: ++ - outdated/changelog.md ++ - sample-file.txt + owner: owner + repo: repo + title: Title Goes Here + +``` diff --git a/.changeset/stupid-donuts-sit.md b/.changeset/stupid-donuts-sit.md new file mode 100644 index 0000000000..e829d49843 --- /dev/null +++ b/.changeset/stupid-donuts-sit.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +Fixed bug with error message since ResponseError is now thrown from CatalogClient diff --git a/.changeset/three-shoes-behave.md b/.changeset/three-shoes-behave.md new file mode 100644 index 0000000000..51205ffa21 --- /dev/null +++ b/.changeset/three-shoes-behave.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +adding export for ButtonLink so it's importable diff --git a/.changeset/tired-bats-attend.md b/.changeset/tired-bats-attend.md new file mode 100644 index 0000000000..cfe01f14fe --- /dev/null +++ b/.changeset/tired-bats-attend.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration-react': patch +--- + +Separated gitlab `write_repository` and `api` scope to pass checks in `RefreshingAuthSessionManager` diff --git a/.changeset/warm-taxes-show.md b/.changeset/warm-taxes-show.md deleted file mode 100644 index edebd0048e..0000000000 --- a/.changeset/warm-taxes-show.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/canon': minor ---- - -Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using instead of just . diff --git a/.changeset/wicked-socks-share.md b/.changeset/wicked-socks-share.md new file mode 100644 index 0000000000..d3e1275732 --- /dev/null +++ b/.changeset/wicked-socks-share.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-search-backend': patch +--- + +Error messages should not contain backend SQL query strings in the API response, this change will ensure that messages are logged and empty response is returned to the user diff --git a/.changeset/wise-frogs-talk.md b/.changeset/wise-frogs-talk.md new file mode 100644 index 0000000000..6a25abc246 --- /dev/null +++ b/.changeset/wise-frogs-talk.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-defaults': patch +'@backstage/integration': patch +--- + +Fixed bug where the GitLab user token and GitLab integration token were being merged together diff --git a/.changeset/yummy-donuts-peel.md b/.changeset/yummy-donuts-peel.md deleted file mode 100644 index 6c66573025..0000000000 --- a/.changeset/yummy-donuts-peel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/canon': patch ---- - -Remove leftover console.log from Container component. diff --git a/.changeset/yummy-pugs-battle.md b/.changeset/yummy-pugs-battle.md new file mode 100644 index 0000000000..a17b934deb --- /dev/null +++ b/.changeset/yummy-pugs-battle.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': patch +--- + +Update uncomfortably bright color in recently visited and top visited home page cards diff --git a/.eslintrc.js b/.eslintrc.js index 409b820783..54f9e69576 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,8 +18,26 @@ var path = require('path'); module.exports = { root: true, - plugins: ['@spotify', 'notice', 'react', 'testing-library'], + plugins: ['@spotify', 'notice', 'react', 'testing-library', '@backstage'], rules: { + '@backstage/no-mixed-plugin-imports': [ + 'error', + { + // TODO: Fix these either by right role or by moving things to new packages + excludedTargetPackages: [ + '@backstage/plugin-catalog', + '@backstage/plugin-techdocs', + '@backstage/plugin-app', + '@backstage/plugin-catalog-backend', + '@backstage/test-utils', + '@backstage/plugin-auth-backend', + '@backstage/plugin-permission-backend', + '@backstage/plugin-kubernetes-backend', + '@backstage/config-loader', + '@backstage/plugin-app-backend' + ], + } + ], 'react/react-in-jsx-scope': 'off', 'notice/notice': [ 'error', diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 77faa9354f..4716f1363f 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -35,6 +35,11 @@ rangeStrategy: 'replace', matchSourceUrls: ['https://github.com/gregberge/svgr{/,}**'], }, + { + groupName: 'Module-federation monorepo packages', + rangeStrategy: 'replace', + matchSourceUrls: ['https://github.com/module-federation/core{/,}**'], + }, // We update yarn packages manually as it's gzip'd and we don't want to pollute the repository too much. { matchSourceUrls: ['https://github.com/yarnpkg/berry'], diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index 36f9335b1f..b3ef80c45f 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -43,6 +43,7 @@ bugfixes builtins bundler bundlers +bursty callout CDNs Chai @@ -433,6 +434,7 @@ statefulsets stdout storable storages +Streamable stringified stringify subcommand diff --git a/.github/workflows/deploy_docker-image.yml b/.github/workflows/deploy_docker-image.yml index e1547801ef..9c97c62d16 100644 --- a/.github/workflows/deploy_docker-image.yml +++ b/.github/workflows/deploy_docker-image.yml @@ -52,17 +52,17 @@ jobs: working-directory: ./example-app - name: Login to GitHub Container Registry - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 + uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1 - name: Build and push - uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0 with: context: './example-app' file: ./example-app/packages/backend/Dockerfile diff --git a/.github/workflows/deploy_microsite.yml b/.github/workflows/deploy_microsite.yml index 67fcc5d709..a5e89d6103 100644 --- a/.github/workflows/deploy_microsite.yml +++ b/.github/workflows/deploy_microsite.yml @@ -321,12 +321,12 @@ jobs: name: storybook path: microsite/build/storybook - - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: stable-reference-beta path: microsite/build/api/stable/ - - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + - uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: next-reference-beta path: microsite/build/api/next/ diff --git a/.github/workflows/sync_code-formatting.yml b/.github/workflows/sync_code-formatting.yml index ee97f3fef3..18ec62c7bf 100644 --- a/.github/workflows/sync_code-formatting.yml +++ b/.github/workflows/sync_code-formatting.yml @@ -30,7 +30,7 @@ jobs: cache-prefix: ${{ runner.os }}-v${{ matrix.node-version }} - name: Run Prettier on ADOPTERS.md - uses: creyD/prettier_action@31355f8eef017f8aeba2e0bc09d8502b13dbbad1 # v4.3 + uses: creyD/prettier_action@8c18391fdc98ed0d884c6345f03975edac71b8f0 # v4.6 with: # Modifies commit only if prettier autofixed the ADOPTERS.md prettier_options: --config docs/prettier.config.js --write ADOPTERS.md diff --git a/.github/workflows/verify_microsite.yml b/.github/workflows/verify_microsite.yml index df68cff2cf..38900074d6 100644 --- a/.github/workflows/verify_microsite.yml +++ b/.github/workflows/verify_microsite.yml @@ -325,13 +325,13 @@ jobs: working-directory: microsite - name: download stable reference (beta) - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: stable-reference-beta path: api/stable/ - name: download next reference (beta) - uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: name: next-reference-beta path: api/next/ diff --git a/.github/workflows/verify_storybook.yml b/.github/workflows/verify_storybook.yml index 3cc846a706..6c1ceb4c52 100644 --- a/.github/workflows/verify_storybook.yml +++ b/.github/workflows/verify_storybook.yml @@ -54,7 +54,7 @@ jobs: - run: yarn --cwd packages/canon build-storybook - - uses: chromaui/action@e8cc4c31775280b175a3c440076c00d19a9014d7 # v11 + - uses: chromaui/action@1cfa065cbdab28f6ca3afaeb3d761383076a35aa # v11 with: token: ${{ secrets.GITHUB_TOKEN }} # projectToken intentionally shared to allow collaborators to run Chromatic on forks diff --git a/ADOPTERS.md b/ADOPTERS.md index e97c213adf..d20fd4a8b2 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -284,3 +284,4 @@ _You can do this by using the [Adopter form](https://info.backstage.spotify.com/ | [Scalepoint](https://scalepoint.com) | [Yuriy Ostapenko](https://github.com/yuriyostapenko), [Dmytro Pasko](https://github.com/dimapasko), [Yuri Sedykh ](https://github.com/yuiri-sedykh), [Bartosz Wisniewski](https://github.com/Epgor) | Internal Developer Portal: Software Catalog with infrastructure resources and dependencies, Software Templates, TechDocs, Tech Radar, Kubernetes and Observability, as well as custom CI/CD components | | [VR](https://www.vr.com.br) | [Felipe Gomes](https://www.linkedin.com/in/felipe-gomes-da-silva), [Tiago Garcia](https://www.linkedin.com/in/tiago-garcia-6301a925) | Internal portal for development squads, service catalog, documentation hub, and application mapping for the entire company ecosystem, simplifying cloud infrastructure construction through templates. | | [Plata](https://platacard.mx/en) | [Shamil Ganiev](https://github.com/ganievs) | Internal Developer Portal for the whole engineering team | +| [Syngenta Digital](https://www.syngentadigital.com) | [Bitan Mallick](https://www.linkedin.com/in/bitanmallick) | Internal developer portal, designed to empower developers and streamline workflows. We use software catalog, tech-radar, software templates, tech-docs and various custom plugins to ensure an efficient and collaborative development experience. | diff --git a/LABELS.md b/LABELS.md index 7f8804f75a..32d5c7f095 100644 --- a/LABELS.md +++ b/LABELS.md @@ -26,6 +26,7 @@ These labels indicate what is needed to move an issue forward before it can be a - `needs:bep` - The issue is an advanced addition that needs a [Backstage Enhancement Proposal](./beps/README.md). - `needs:direction` - The issue needs direction from the owners of the area. +- `needs:discussion` - The way forward for this issue is unclear and it needs further discussion with the author and other participants. - `needs:more-info` - The issue needs more information from the author. - `needs:motivation` - It is not clear why this change is needed. The author should provide motivation for the change, for instance by giving examples of concrete use cases or scenarios. - `needs:repro` - The issue cannot be reproduced by the owners of the area. The author should provide more information to help them reproduce the issue, if possible with a minimal reproduction repository. @@ -81,11 +82,17 @@ These labels indicate that an issue is related to specific domains of expertise. - `domain:tooling` - Tooling and automation in Node.js and GitHub Actions. - `domain:web` - Frontend development using TypeScript and React. +## Workflow Labels + +These labels indicate a workflow status for the owners. + +- `workflow:do-not-merge` - The Pull Request should not be merged. +- `workflow:before-release` - Should be handled before the next main-line release. +- `workflow:after-release` - Should be handled after the next main-line release. +- `workflow:after-vacations` - To be handled once the owners return from vacation. + ## General Labels -- `after vacations` - To be handled once the owners return from vacation. -- `do not merge` - The pull request should not be merged. -- `fix before release` - Should be handled before the next release. - `good first issue` - Good for new contributors. - `stale` - The issue or pull request has not seen any activity for a while and will be closed if no further activity is seen. - `no stale` - The issue or pull request should not be closed due to inactivity. diff --git a/OWNERS.md b/OWNERS.md index 85ffadae42..d4ee3c6400 100644 --- a/OWNERS.md +++ b/OWNERS.md @@ -56,6 +56,18 @@ Scope: The Backstage design system, component library, as well as surrounding to | Charles de Dreuille | Spotify | | [cdedreuille](https://github.com/cdedreuille) | `cdedreuille` | | Patrik Oldsberg | Spotify | Cubic Belugas | [Rugvip](https://github.com/Rugvip) | `Rugvip` | +### Documentation + +Team: @backstage/documentation-maintainers + +Scope: The Backstage Documentation and Microsite, excluding the plugins listing + +| Name | Organization | GitHub | Discord | +| --------------- | ------------- | ----------------------------------------------------- | ------------- | +| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` | +| Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` | +| Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` | + ### Framework Team: @backstage/framework-maintainers @@ -77,11 +89,11 @@ Team: @backstage/helm-chart-maintainers Scope: The Backstage [Helm Chart(s)](https://github.com/backstage/charts). -| Name | Organization | Team | GitHub | Discord | -| -------------------- | ------------ | ---- | ---------------------------------------- | -------------- | -| Andrew Block | Red Hat | | [sabre1041](http://github.com/sabre1041) | sabre1041#2622 | -| Tom Coufal | Red Hat | | [tumido](http://github.com/tumido) | Tumi#4346 | -| Vincenzo Scamporlino | Spotify | | [vinzscam](http://github.com/vinzscam) | vinzscam#6944 | +| Name | Organization | Team | GitHub | Discord | +| -------------------- | ------------ | ---- | ---------------------------------------- | ---------------- | +| Andrew Block | Red Hat | | [sabre1041](http://github.com/sabre1041) | `sabre1041#2622` | +| Tom Coufal | Red Hat | | [tumido](http://github.com/tumido) | `Tumi#4346` | +| Vincenzo Scamporlino | Spotify | | [vinzscam](http://github.com/vinzscam) | `vinzscam#6944` | ### Home @@ -89,12 +101,14 @@ Team: @backstage/home-maintainers Scope: The Backstage home page and information architecture -| Name | Organization | Team | GitHub | Discord | -| ------------------------ | ------------ | -------------- | ---------------------------------------- | ----------------- | -| Avantika Iyer | Spotify | Infinite Buck$ | [tikabom](http://github.com/tikabom) | - | -| Emma Indal | Spotify | Infinite Buck$ | [emmaindal](http://github.com/emmaindal) | emmaindal#7503 | -| Djamaile Rahamat | Spotify | Infinite Buck$ | [djamaile](http://github.com/djamaile) | dyoqi | -| Raghunandan Balachandran | Spotify | Infinite Buck$ | [soapraj](http://github.com/soapraj) | raghunandanb#1114 | +| Name | Organization | Team | GitHub | Discord | +| ------------------ | ------------ | --------------- | ----------------------------------------- | ------- | +| Ainhoa Larumbe | Spotify | Imaginary Goats | [ainhoaL](http://github.com/ainhoaL) | - | +| Avantika Iyer | Spotify | Imaginary Goats | [tikabom](http://github.com/tikabom) | - | +| Daniel Jelčić | Spotify | Imaginary Goats | [djelcic](http://github.com/danieljelcic) | - | +| Eric Peterson | Spotify | Imaginary Goats | [iamEAP](http://github.com/iamEAP) | - | +| Musaab Elfaqih | Spotify | Imaginary Goats | [TheSabby](http://github.com/TheSabby) | - | +| Landry Zinda-Snead | Spotify | Imaginary Goats | [landryzs](http://github.com/landryzs) | - | ### Kubernetes @@ -206,18 +220,6 @@ Scope: Tooling and Community Repo Maintainers for the Backstage [Community Plugi | Vincenzo Scamporlino | Spotify | [vinzscam](https://github.com/vinzscam) | `vinzscam` | | Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` | -### Documentation - -Team: @backstage/documentation-maintainers - -Scope: The Backstage Documentation and Microsite, excluding the plugins listing - -| Name | Organization | GitHub | Discord | -| --------------- | ------------- | ----------------------------------------------------- | ------------- | -| Andre Wanlin | Spotify | [awanlin](https://github.com/awanlin) | `ahhhndre` | -| Aramis Sennyey | DoorDash | [aramissennyeydd](https://github.com/aramissennyeydd) | `Aramis#7984` | -| Peter Macdonald | VodafoneZiggo | [Parsifal-M](https://github.com/Parsifal-M) | `parsifal` | - ### Events Team: @backstage/events-maintainers diff --git a/app-config.yaml b/app-config.yaml index 89e417fad3..910a3e4f99 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -36,6 +36,12 @@ backend: # keys: # - secret: ${BACKEND_SECRET} + # Used for testing rate limiting locally + # rateLimit: + # windowMs: 1m + # incomingRequestLimit: 1 + # ipAllowList: [] + auth: # TODO: once plugins have been migrated we can remove this, but right now it # is require for the backend-next to work in this repo @@ -64,83 +70,11 @@ backend: # See README.md in the proxy-backend plugin for information on the configuration format proxy: endpoints: - '/circleci/api': - target: https://circleci.com/api/v1.1 - headers: - Circle-Token: ${CIRCLECI_AUTH_TOKEN} - - '/jenkins/api': - target: http://localhost:8080 - headers: - Authorization: ${JENKINS_BASIC_AUTH_HEADER} - - '/travisci/api': - target: https://api.travis-ci.com - changeOrigin: true - headers: - Authorization: ${TRAVISCI_AUTH_TOKEN} - travis-api-version: '3' - - '/newrelic/apm/api': - target: https://api.newrelic.com/v2 - headers: - X-Api-Key: ${NEW_RELIC_REST_API_KEY} - allowedHeaders: - - link - - '/newrelic/api': - target: https://api.newrelic.com - headers: - X-Api-Key: ${NEW_RELIC_USER_KEY} - '/pagerduty': target: https://api.pagerduty.com headers: Authorization: Token token=${PAGERDUTY_TOKEN} - '/buildkite/api': - target: https://api.buildkite.com/v2/ - headers: - Authorization: ${BUILDKITE_TOKEN} - - '/sentry/api': - target: https://sentry.io/api/ - allowedMethods: ['GET'] - headers: - Authorization: ${SENTRY_TOKEN} - - '/ilert': - target: https://api.ilert.com - allowedMethods: ['GET', 'POST', 'PUT'] - allowedHeaders: ['Authorization'] - headers: - Authorization: ${ILERT_AUTH_HEADER} - - '/airflow': - target: https://your.airflow.instance.com/api/v1 - headers: - Authorization: ${AIRFLOW_BASIC_AUTH_HEADER} - - '/gocd': - target: https://your.gocd.instance.com/go/api - allowedMethods: ['GET'] - allowedHeaders: ['Authorization'] - headers: - Authorization: Basic ${GOCD_AUTH_CREDENTIALS} - - '/dynatrace': - target: https://your.dynatrace.instance.com/api/v2 - headers: - Authorization: 'Api-Token ${DYNATRACE_ACCESS_TOKEN}' - - '/stackstorm': - target: https://your.stackstorm.instance.com/api - headers: - St2-Api-Key: ${ST2_API_KEY} - - '/puppetdb': - target: https://your.puppetdb.instance.com - organization: name: My Company @@ -157,46 +91,6 @@ techdocs: publisher: type: 'local' # Alternatives - 'googleGcs' or 'awsS3' or 'azureBlobStorage' or 'openStackSwift'. Read documentation for using alternatives. -dynatrace: - baseUrl: https://your.dynatrace.instance.com - -nomad: - addr: 0.0.0.0 - -# Score-cards sample configuration. -scorecards: - jsonDataUrl: https://raw.githubusercontent.com/Oriflame/backstage-plugins/main/plugins/score-card/sample-data/ - wikiLinkTemplate: https://link-to-wiki/{id} - -sentry: - organization: my-company - -rollbar: - organization: my-company - # NOTE: The rollbar-backend & accountToken key may be deprecated in the future (replaced by a proxy config) - accountToken: my-rollbar-account-token - -lighthouse: - baseUrl: http://localhost:3003 - -kubernetes: - serviceLocatorMethod: - type: 'multiTenant' - clusterLocatorMethods: - - type: 'config' - clusters: [] - -kafka: - clientId: backstage - clusters: - - name: cluster - dashboardUrl: https://akhq.io/ - brokers: - - localhost:9092 - -allure: - baseUrl: http://localhost:5050/allure-docker-service - integrations: github: - host: github.com @@ -244,7 +138,6 @@ integrations: secretAccessKey: ${AWS_SECRET_ACCESS_KEY} catalog: - useUrlReadersSearch: true import: entityFilename: catalog-info.yaml pullRequestBranchName: backstage-integration @@ -269,26 +162,6 @@ catalog: plugins: - catalog - search - - processors: - ldapOrg: - ### Example for how to add your enterprise LDAP server - # providers: - # - target: ldaps://ds.example.net - # bind: - # dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net - # secret: ${LDAP_SECRET} - # users: - # dn: ou=people,ou=example,dc=example,dc=net - # options: - # filter: (uid=*) - # map: - # description: l - # groups: - # dn: ou=access,ou=groups,ou=example,dc=example,dc=net - # options: - # filter: (&(objectClass=some-group-class)(!(groupType=email))) - locations: # Add a location here to ingest it, for example from a URL: # @@ -325,13 +198,14 @@ catalog: target: ../../plugins/scaffolder-backend/sample-templates/all-templates.yaml rules: - allow: [Template] + scaffolder: # Use to customize default commit author info used when new components are created - # defaultAuthor: - # name: Scaffolder - # email: scaffolder@backstage.io + defaultAuthor: + name: Scaffolder + email: scaffolder@backstage.io # Use to customize the default commit message when new components are created - # defaultCommitMessage: 'Initial commit' + defaultCommitMessage: 'Initial commit' auth: ### Add auth.keyStore.provider to more granularly control how to store JWK data when running @@ -422,80 +296,5 @@ auth: myproxy: {} guest: {} -costInsights: - engineerCost: 200000 - engineerThreshold: 0.5 - products: - computeEngine: - name: Compute Engine - icon: compute - cloudDataflow: - name: Cloud Dataflow - icon: data - cloudStorage: - name: Cloud Storage - icon: storage - bigQuery: - name: BigQuery - icon: search - events: - name: Events - icon: data - metrics: - DAU: - name: Daily Active Users - default: true - MSC: - name: Monthly Subscribers - currencies: - engineers: - label: 'Engineers 🛠' - unit: 'engineer' - usd: - label: 'US Dollars 💵' - kind: 'USD' - unit: 'dollar' - prefix: '$' - rate: 1 - carbonOffsetTons: - label: 'Carbon Offset Tons ♻️⚖️s' - kind: 'CARBON_OFFSET_TONS' - unit: 'carbon offset ton' - rate: 3.5 - beers: - label: 'Beers 🍺' - kind: 'BEERS' - unit: 'beer' - rate: 4.5 - pintsIceCream: - label: 'Pints of Ice Cream 🍦' - kind: 'PINTS_OF_ICE_CREAM' - unit: 'ice cream pint' - rate: 5.5 - -pagerDuty: - eventsBaseUrl: 'https://events.pagerduty.com/v2' - -jenkins: - instances: - - name: default - baseUrl: https://jenkins.example.com - username: backstage-bot - apiKey: 123456789abcdef0123456789abcedf012 - -azureDevOps: - host: dev.azure.com - token: my-token - organization: my-company - -apacheAirflow: - baseUrl: https://your.airflow.instance.com - -gocd: - baseUrl: https://your.gocd.instance.com - -stackstorm: - webUrl: https://your.stackstorm.webui.instance.com - permission: enabled: true diff --git a/canon-docs/next.config.mjs b/canon-docs/next.config.mjs index ca221d9a8c..8e6ed8fdc0 100644 --- a/canon-docs/next.config.mjs +++ b/canon-docs/next.config.mjs @@ -8,6 +8,11 @@ const nextConfig = { images: { unoptimized: true, }, + typescript: { + // Ignore TypeScript errors during build - safe for React 18/19 compatibility issues + // These are type-level conflicts that don't affect runtime behavior + ignoreBuildErrors: true, + }, }; const withMDX = createMDX({}); diff --git a/canon-docs/package.json b/canon-docs/package.json index 5a4affc45b..b6faca63ae 100644 --- a/canon-docs/package.json +++ b/canon-docs/package.json @@ -3,24 +3,35 @@ "version": "0.1.0", "private": true, "scripts": { - "build": "npm run build:css && next build", - "build:css": "node scripts/build-css.js", + "prebuild": "yarn sync:css", + "build": "next build", "lint": "next lint", - "start": "npm run build:css && next dev" + "prestart": "yarn sync:css", + "start": "concurrently \"yarn sync:css:watch\" \"next dev\"", + "sync:css": "node scripts/sync-css.js", + "sync:css:watch": "node scripts/sync-css.js --watch" + }, + "resolutions": { + "@types/react": "19.1.8", + "@types/react-dom": "19.1.6" }, "dependencies": { "@codemirror/lang-sass": "^6.0.2", + "@codemirror/view": "^6.34.4", "@lezer/highlight": "^1.2.1", "@mdx-js/loader": "^3.1.0", "@mdx-js/react": "^3.1.0", - "@next/mdx": "^15.1.4", + "@next/mdx": "15.3.4", "@storybook/react": "^8.6.8", "@uiw/codemirror-themes": "^4.23.7", "@uiw/react-codemirror": "^4.23.7", + "html-react-parser": "^5.2.5", "motion": "^12.4.1", - "next": "14.2.26", - "react": "^18.0.2", - "react-dom": "^18.0.2", + "next": "15.3.4", + "next-mdx-remote-client": "^2.1.2", + "prop-types": "^15.8.1", + "react": "19.1.0", + "react-dom": "19.1.0", "react-frame-component": "^5.2.7", "shiki": "^1.26.1", "storybook": "^8.6.8" @@ -28,10 +39,12 @@ "devDependencies": { "@types/mdx": "^2.0.13", "@types/node": "^20", - "@types/react": "^18.0.0", - "@types/react-dom": "^18.0.0", + "@types/react": "19.1.8", + "@types/react-dom": "19.1.6", + "chokidar": "^3.6.0", + "concurrently": "^8.2.2", "eslint": "^8", - "eslint-config-next": "14.2.23", + "eslint-config-next": "15.3.4", "lightningcss": "^1.28.2", "typescript": "^5" } diff --git a/canon-docs/public/header.png b/canon-docs/public/header.png index 507bd05ca7..8d11151a3e 100644 Binary files a/canon-docs/public/header.png and b/canon-docs/public/header.png differ diff --git a/canon-docs/public/theme-backstage.css b/canon-docs/public/theme-backstage.css new file mode 100644 index 0000000000..a9b535da3c --- /dev/null +++ b/canon-docs/public/theme-backstage.css @@ -0,0 +1,2 @@ +/*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ +@layer base{*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:100%;tab-size:4;font-family:system-ui,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;line-height:1.15}body{margin:0}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{border-color:currentColor}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:100%;line-height:1.15}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}legend{padding:0}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}}.cu-p{padding:var(--p)}.cu-p-0\.5{padding:var(--canon-space-0_5)}.cu-p-1{padding:var(--canon-space-1)}.cu-p-1\.5{padding:var(--canon-space-1_5)}.cu-p-2{padding:var(--canon-space-2)}.cu-p-3{padding:var(--canon-space-3)}.cu-p-4{padding:var(--canon-space-4)}.cu-p-5{padding:var(--canon-space-5)}.cu-p-6{padding:var(--canon-space-6)}.cu-p-7{padding:var(--canon-space-7)}.cu-p-8{padding:var(--canon-space-8)}.cu-p-9{padding:var(--canon-space-9)}.cu-p-10{padding:var(--canon-space-10)}.cu-p-11{padding:var(--canon-space-11)}.cu-p-12{padding:var(--canon-space-12)}.cu-p-13{padding:var(--canon-space-13)}.cu-p-14{padding:var(--canon-space-14)}@media (width>=640px){.xs\:cu-p{padding:var(--p-xs)}.xs\:cu-p-0\.5{padding:var(--canon-space-0_5)}.xs\:cu-p-1{padding:var(--canon-space-1)}.xs\:cu-p-1\.5{padding:var(--canon-space-1_5)}.xs\:cu-p-2{padding:var(--canon-space-2)}.xs\:cu-p-3{padding:var(--canon-space-3)}.xs\:cu-p-4{padding:var(--canon-space-4)}.xs\:cu-p-5{padding:var(--canon-space-5)}.xs\:cu-p-6{padding:var(--canon-space-6)}.xs\:cu-p-7{padding:var(--canon-space-7)}.xs\:cu-p-8{padding:var(--canon-space-8)}.xs\:cu-p-9{padding:var(--canon-space-9)}.xs\:cu-p-10{padding:var(--canon-space-10)}.xs\:cu-p-11{padding:var(--canon-space-11)}.xs\:cu-p-12{padding:var(--canon-space-12)}.xs\:cu-p-13{padding:var(--canon-space-13)}.xs\:cu-p-14{padding:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-p{padding:var(--p-sm)}.sm\:cu-p-0\.5{padding:var(--canon-space-0_5)}.sm\:cu-p-1{padding:var(--canon-space-1)}.sm\:cu-p-1\.5{padding:var(--canon-space-1_5)}.sm\:cu-p-2{padding:var(--canon-space-2)}.sm\:cu-p-3{padding:var(--canon-space-3)}.sm\:cu-p-4{padding:var(--canon-space-4)}.sm\:cu-p-5{padding:var(--canon-space-5)}.sm\:cu-p-6{padding:var(--canon-space-6)}.sm\:cu-p-7{padding:var(--canon-space-7)}.sm\:cu-p-8{padding:var(--canon-space-8)}.sm\:cu-p-9{padding:var(--canon-space-9)}.sm\:cu-p-10{padding:var(--canon-space-10)}.sm\:cu-p-11{padding:var(--canon-space-11)}.sm\:cu-p-12{padding:var(--canon-space-12)}.sm\:cu-p-13{padding:var(--canon-space-13)}.sm\:cu-p-14{padding:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-p{padding:var(--p-md)}.md\:cu-p-0\.5{padding:var(--canon-space-0_5)}.md\:cu-p-1{padding:var(--canon-space-1)}.md\:cu-p-1\.5{padding:var(--canon-space-1_5)}.md\:cu-p-2{padding:var(--canon-space-2)}.md\:cu-p-3{padding:var(--canon-space-3)}.md\:cu-p-4{padding:var(--canon-space-4)}.md\:cu-p-5{padding:var(--canon-space-5)}.md\:cu-p-6{padding:var(--canon-space-6)}.md\:cu-p-7{padding:var(--canon-space-7)}.md\:cu-p-8{padding:var(--canon-space-8)}.md\:cu-p-9{padding:var(--canon-space-9)}.md\:cu-p-10{padding:var(--canon-space-10)}.md\:cu-p-11{padding:var(--canon-space-11)}.md\:cu-p-12{padding:var(--canon-space-12)}.md\:cu-p-13{padding:var(--canon-space-13)}.md\:cu-p-14{padding:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-p{padding:var(--p-lg)}.lg\:cu-p-0\.5{padding:var(--canon-space-0_5)}.lg\:cu-p-1{padding:var(--canon-space-1)}.lg\:cu-p-1\.5{padding:var(--canon-space-1_5)}.lg\:cu-p-2{padding:var(--canon-space-2)}.lg\:cu-p-3{padding:var(--canon-space-3)}.lg\:cu-p-4{padding:var(--canon-space-4)}.lg\:cu-p-5{padding:var(--canon-space-5)}.lg\:cu-p-6{padding:var(--canon-space-6)}.lg\:cu-p-7{padding:var(--canon-space-7)}.lg\:cu-p-8{padding:var(--canon-space-8)}.lg\:cu-p-9{padding:var(--canon-space-9)}.lg\:cu-p-10{padding:var(--canon-space-10)}.lg\:cu-p-11{padding:var(--canon-space-11)}.lg\:cu-p-12{padding:var(--canon-space-12)}.lg\:cu-p-13{padding:var(--canon-space-13)}.lg\:cu-p-14{padding:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-p{padding:var(--p-xl)}.xl\:cu-p-0\.5{padding:var(--canon-space-0_5)}.xl\:cu-p-1{padding:var(--canon-space-1)}.xl\:cu-p-1\.5{padding:var(--canon-space-1_5)}.xl\:cu-p-2{padding:var(--canon-space-2)}.xl\:cu-p-3{padding:var(--canon-space-3)}.xl\:cu-p-4{padding:var(--canon-space-4)}.xl\:cu-p-5{padding:var(--canon-space-5)}.xl\:cu-p-6{padding:var(--canon-space-6)}.xl\:cu-p-7{padding:var(--canon-space-7)}.xl\:cu-p-8{padding:var(--canon-space-8)}.xl\:cu-p-9{padding:var(--canon-space-9)}.xl\:cu-p-10{padding:var(--canon-space-10)}.xl\:cu-p-11{padding:var(--canon-space-11)}.xl\:cu-p-12{padding:var(--canon-space-12)}.xl\:cu-p-13{padding:var(--canon-space-13)}.xl\:cu-p-14{padding:var(--canon-space-14)}}.cu-pl{padding-left:var(--pl)}.cu-pl-0\.5{padding-left:var(--canon-space-0_5)}.cu-pl-1{padding-left:var(--canon-space-1)}.cu-pl-1\.5{padding-left:var(--canon-space-1_5)}.cu-pl-2{padding-left:var(--canon-space-2)}.cu-pl-3{padding-left:var(--canon-space-3)}.cu-pl-4{padding-left:var(--canon-space-4)}.cu-pl-5{padding-left:var(--canon-space-5)}.cu-pl-6{padding-left:var(--canon-space-6)}.cu-pl-7{padding-left:var(--canon-space-7)}.cu-pl-8{padding-left:var(--canon-space-8)}.cu-pl-9{padding-left:var(--canon-space-9)}.cu-pl-10{padding-left:var(--canon-space-10)}.cu-pl-11{padding-left:var(--canon-space-11)}.cu-pl-12{padding-left:var(--canon-space-12)}.cu-pl-13{padding-left:var(--canon-space-13)}.cu-pl-14{padding-left:var(--canon-space-14)}@media (width>=640px){.xs\:cu-pl{padding-left:var(--pl-xs)}.xs\:cu-pl-0\.5{padding-left:var(--canon-space-0_5)}.xs\:cu-pl-1{padding-left:var(--canon-space-1)}.xs\:cu-pl-1\.5{padding-left:var(--canon-space-1_5)}.xs\:cu-pl-2{padding-left:var(--canon-space-2)}.xs\:cu-pl-3{padding-left:var(--canon-space-3)}.xs\:cu-pl-4{padding-left:var(--canon-space-4)}.xs\:cu-pl-5{padding-left:var(--canon-space-5)}.xs\:cu-pl-6{padding-left:var(--canon-space-6)}.xs\:cu-pl-7{padding-left:var(--canon-space-7)}.xs\:cu-pl-8{padding-left:var(--canon-space-8)}.xs\:cu-pl-9{padding-left:var(--canon-space-9)}.xs\:cu-pl-10{padding-left:var(--canon-space-10)}.xs\:cu-pl-11{padding-left:var(--canon-space-11)}.xs\:cu-pl-12{padding-left:var(--canon-space-12)}.xs\:cu-pl-13{padding-left:var(--canon-space-13)}.xs\:cu-pl-14{padding-left:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-pl{padding-left:var(--pl-sm)}.sm\:cu-pl-0\.5{padding-left:var(--canon-space-0_5)}.sm\:cu-pl-1{padding-left:var(--canon-space-1)}.sm\:cu-pl-1\.5{padding-left:var(--canon-space-1_5)}.sm\:cu-pl-2{padding-left:var(--canon-space-2)}.sm\:cu-pl-3{padding-left:var(--canon-space-3)}.sm\:cu-pl-4{padding-left:var(--canon-space-4)}.sm\:cu-pl-5{padding-left:var(--canon-space-5)}.sm\:cu-pl-6{padding-left:var(--canon-space-6)}.sm\:cu-pl-7{padding-left:var(--canon-space-7)}.sm\:cu-pl-8{padding-left:var(--canon-space-8)}.sm\:cu-pl-9{padding-left:var(--canon-space-9)}.sm\:cu-pl-10{padding-left:var(--canon-space-10)}.sm\:cu-pl-11{padding-left:var(--canon-space-11)}.sm\:cu-pl-12{padding-left:var(--canon-space-12)}.sm\:cu-pl-13{padding-left:var(--canon-space-13)}.sm\:cu-pl-14{padding-left:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-pl{padding-left:var(--pl-md)}.md\:cu-pl-0\.5{padding-left:var(--canon-space-0_5)}.md\:cu-pl-1{padding-left:var(--canon-space-1)}.md\:cu-pl-1\.5{padding-left:var(--canon-space-1_5)}.md\:cu-pl-2{padding-left:var(--canon-space-2)}.md\:cu-pl-3{padding-left:var(--canon-space-3)}.md\:cu-pl-4{padding-left:var(--canon-space-4)}.md\:cu-pl-5{padding-left:var(--canon-space-5)}.md\:cu-pl-6{padding-left:var(--canon-space-6)}.md\:cu-pl-7{padding-left:var(--canon-space-7)}.md\:cu-pl-8{padding-left:var(--canon-space-8)}.md\:cu-pl-9{padding-left:var(--canon-space-9)}.md\:cu-pl-10{padding-left:var(--canon-space-10)}.md\:cu-pl-11{padding-left:var(--canon-space-11)}.md\:cu-pl-12{padding-left:var(--canon-space-12)}.md\:cu-pl-13{padding-left:var(--canon-space-13)}.md\:cu-pl-14{padding-left:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-pl{padding-left:var(--pl-lg)}.lg\:cu-pl-0\.5{padding-left:var(--canon-space-0_5)}.lg\:cu-pl-1{padding-left:var(--canon-space-1)}.lg\:cu-pl-1\.5{padding-left:var(--canon-space-1_5)}.lg\:cu-pl-2{padding-left:var(--canon-space-2)}.lg\:cu-pl-3{padding-left:var(--canon-space-3)}.lg\:cu-pl-4{padding-left:var(--canon-space-4)}.lg\:cu-pl-5{padding-left:var(--canon-space-5)}.lg\:cu-pl-6{padding-left:var(--canon-space-6)}.lg\:cu-pl-7{padding-left:var(--canon-space-7)}.lg\:cu-pl-8{padding-left:var(--canon-space-8)}.lg\:cu-pl-9{padding-left:var(--canon-space-9)}.lg\:cu-pl-10{padding-left:var(--canon-space-10)}.lg\:cu-pl-11{padding-left:var(--canon-space-11)}.lg\:cu-pl-12{padding-left:var(--canon-space-12)}.lg\:cu-pl-13{padding-left:var(--canon-space-13)}.lg\:cu-pl-14{padding-left:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-pl{padding-left:var(--pl-xl)}.xl\:cu-pl-0\.5{padding-left:var(--canon-space-0_5)}.xl\:cu-pl-1{padding-left:var(--canon-space-1)}.xl\:cu-pl-1\.5{padding-left:var(--canon-space-1_5)}.xl\:cu-pl-2{padding-left:var(--canon-space-2)}.xl\:cu-pl-3{padding-left:var(--canon-space-3)}.xl\:cu-pl-4{padding-left:var(--canon-space-4)}.xl\:cu-pl-5{padding-left:var(--canon-space-5)}.xl\:cu-pl-6{padding-left:var(--canon-space-6)}.xl\:cu-pl-7{padding-left:var(--canon-space-7)}.xl\:cu-pl-8{padding-left:var(--canon-space-8)}.xl\:cu-pl-9{padding-left:var(--canon-space-9)}.xl\:cu-pl-10{padding-left:var(--canon-space-10)}.xl\:cu-pl-11{padding-left:var(--canon-space-11)}.xl\:cu-pl-12{padding-left:var(--canon-space-12)}.xl\:cu-pl-13{padding-left:var(--canon-space-13)}.xl\:cu-pl-14{padding-left:var(--canon-space-14)}}.cu-pr{padding-right:var(--pr)}.cu-pr-0\.5{padding-right:var(--canon-space-0_5)}.cu-pr-1{padding-right:var(--canon-space-1)}.cu-pr-1\.5{padding-right:var(--canon-space-1_5)}.cu-pr-2{padding-right:var(--canon-space-2)}.cu-pr-3{padding-right:var(--canon-space-3)}.cu-pr-4{padding-right:var(--canon-space-4)}.cu-pr-5{padding-right:var(--canon-space-5)}.cu-pr-6{padding-right:var(--canon-space-6)}.cu-pr-7{padding-right:var(--canon-space-7)}.cu-pr-8{padding-right:var(--canon-space-8)}.cu-pr-9{padding-right:var(--canon-space-9)}.cu-pr-10{padding-right:var(--canon-space-10)}.cu-pr-11{padding-right:var(--canon-space-11)}.cu-pr-12{padding-right:var(--canon-space-12)}.cu-pr-13{padding-right:var(--canon-space-13)}.cu-pr-14{padding-right:var(--canon-space-14)}@media (width>=640px){.xs\:cu-pr{padding-right:var(--pr-xs)}.xs\:cu-pr-0\.5{padding-right:var(--canon-space-0_5)}.xs\:cu-pr-1{padding-right:var(--canon-space-1)}.xs\:cu-pr-1\.5{padding-right:var(--canon-space-1_5)}.xs\:cu-pr-2{padding-right:var(--canon-space-2)}.xs\:cu-pr-3{padding-right:var(--canon-space-3)}.xs\:cu-pr-4{padding-right:var(--canon-space-4)}.xs\:cu-pr-5{padding-right:var(--canon-space-5)}.xs\:cu-pr-6{padding-right:var(--canon-space-6)}.xs\:cu-pr-7{padding-right:var(--canon-space-7)}.xs\:cu-pr-8{padding-right:var(--canon-space-8)}.xs\:cu-pr-9{padding-right:var(--canon-space-9)}.xs\:cu-pr-10{padding-right:var(--canon-space-10)}.xs\:cu-pr-11{padding-right:var(--canon-space-11)}.xs\:cu-pr-12{padding-right:var(--canon-space-12)}.xs\:cu-pr-13{padding-right:var(--canon-space-13)}.xs\:cu-pr-14{padding-right:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-pr{padding-right:var(--pr-sm)}.sm\:cu-pr-0\.5{padding-right:var(--canon-space-0_5)}.sm\:cu-pr-1{padding-right:var(--canon-space-1)}.sm\:cu-pr-1\.5{padding-right:var(--canon-space-1_5)}.sm\:cu-pr-2{padding-right:var(--canon-space-2)}.sm\:cu-pr-3{padding-right:var(--canon-space-3)}.sm\:cu-pr-4{padding-right:var(--canon-space-4)}.sm\:cu-pr-5{padding-right:var(--canon-space-5)}.sm\:cu-pr-6{padding-right:var(--canon-space-6)}.sm\:cu-pr-7{padding-right:var(--canon-space-7)}.sm\:cu-pr-8{padding-right:var(--canon-space-8)}.sm\:cu-pr-9{padding-right:var(--canon-space-9)}.sm\:cu-pr-10{padding-right:var(--canon-space-10)}.sm\:cu-pr-11{padding-right:var(--canon-space-11)}.sm\:cu-pr-12{padding-right:var(--canon-space-12)}.sm\:cu-pr-13{padding-right:var(--canon-space-13)}.sm\:cu-pr-14{padding-right:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-pr{padding-right:var(--pr-md)}.md\:cu-pr-0\.5{padding-right:var(--canon-space-0_5)}.md\:cu-pr-1{padding-right:var(--canon-space-1)}.md\:cu-pr-1\.5{padding-right:var(--canon-space-1_5)}.md\:cu-pr-2{padding-right:var(--canon-space-2)}.md\:cu-pr-3{padding-right:var(--canon-space-3)}.md\:cu-pr-4{padding-right:var(--canon-space-4)}.md\:cu-pr-5{padding-right:var(--canon-space-5)}.md\:cu-pr-6{padding-right:var(--canon-space-6)}.md\:cu-pr-7{padding-right:var(--canon-space-7)}.md\:cu-pr-8{padding-right:var(--canon-space-8)}.md\:cu-pr-9{padding-right:var(--canon-space-9)}.md\:cu-pr-10{padding-right:var(--canon-space-10)}.md\:cu-pr-11{padding-right:var(--canon-space-11)}.md\:cu-pr-12{padding-right:var(--canon-space-12)}.md\:cu-pr-13{padding-right:var(--canon-space-13)}.md\:cu-pr-14{padding-right:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-pr{padding-right:var(--pr-lg)}.lg\:cu-pr-0\.5{padding-right:var(--canon-space-0_5)}.lg\:cu-pr-1{padding-right:var(--canon-space-1)}.lg\:cu-pr-1\.5{padding-right:var(--canon-space-1_5)}.lg\:cu-pr-2{padding-right:var(--canon-space-2)}.lg\:cu-pr-3{padding-right:var(--canon-space-3)}.lg\:cu-pr-4{padding-right:var(--canon-space-4)}.lg\:cu-pr-5{padding-right:var(--canon-space-5)}.lg\:cu-pr-6{padding-right:var(--canon-space-6)}.lg\:cu-pr-7{padding-right:var(--canon-space-7)}.lg\:cu-pr-8{padding-right:var(--canon-space-8)}.lg\:cu-pr-9{padding-right:var(--canon-space-9)}.lg\:cu-pr-10{padding-right:var(--canon-space-10)}.lg\:cu-pr-11{padding-right:var(--canon-space-11)}.lg\:cu-pr-12{padding-right:var(--canon-space-12)}.lg\:cu-pr-13{padding-right:var(--canon-space-13)}.lg\:cu-pr-14{padding-right:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-pr{padding-right:var(--pr-xl)}.xl\:cu-pr-0\.5{padding-right:var(--canon-space-0_5)}.xl\:cu-pr-1{padding-right:var(--canon-space-1)}.xl\:cu-pr-1\.5{padding-right:var(--canon-space-1_5)}.xl\:cu-pr-2{padding-right:var(--canon-space-2)}.xl\:cu-pr-3{padding-right:var(--canon-space-3)}.xl\:cu-pr-4{padding-right:var(--canon-space-4)}.xl\:cu-pr-5{padding-right:var(--canon-space-5)}.xl\:cu-pr-6{padding-right:var(--canon-space-6)}.xl\:cu-pr-7{padding-right:var(--canon-space-7)}.xl\:cu-pr-8{padding-right:var(--canon-space-8)}.xl\:cu-pr-9{padding-right:var(--canon-space-9)}.xl\:cu-pr-10{padding-right:var(--canon-space-10)}.xl\:cu-pr-11{padding-right:var(--canon-space-11)}.xl\:cu-pr-12{padding-right:var(--canon-space-12)}.xl\:cu-pr-13{padding-right:var(--canon-space-13)}.xl\:cu-pr-14{padding-right:var(--canon-space-14)}}.cu-pt{padding-top:var(--pt)}.cu-pt-0\.5{padding-top:var(--canon-space-0_5)}.cu-pt-1{padding-top:var(--canon-space-1)}.cu-pt-1\.5{padding-top:var(--canon-space-1_5)}.cu-pt-2{padding-top:var(--canon-space-2)}.cu-pt-3{padding-top:var(--canon-space-3)}.cu-pt-4{padding-top:var(--canon-space-4)}.cu-pt-5{padding-top:var(--canon-space-5)}.cu-pt-6{padding-top:var(--canon-space-6)}.cu-pt-7{padding-top:var(--canon-space-7)}.cu-pt-8{padding-top:var(--canon-space-8)}.cu-pt-9{padding-top:var(--canon-space-9)}.cu-pt-10{padding-top:var(--canon-space-10)}.cu-pt-11{padding-top:var(--canon-space-11)}.cu-pt-12{padding-top:var(--canon-space-12)}.cu-pt-13{padding-top:var(--canon-space-13)}.cu-pt-14{padding-top:var(--canon-space-14)}@media (width>=640px){.xs\:cu-pt{padding-top:var(--pt-xs)}.xs\:cu-pt-0\.5{padding-top:var(--canon-space-0_5)}.xs\:cu-pt-1{padding-top:var(--canon-space-1)}.xs\:cu-pt-1\.5{padding-top:var(--canon-space-1_5)}.xs\:cu-pt-2{padding-top:var(--canon-space-2)}.xs\:cu-pt-3{padding-top:var(--canon-space-3)}.xs\:cu-pt-4{padding-top:var(--canon-space-4)}.xs\:cu-pt-5{padding-top:var(--canon-space-5)}.xs\:cu-pt-6{padding-top:var(--canon-space-6)}.xs\:cu-pt-7{padding-top:var(--canon-space-7)}.xs\:cu-pt-8{padding-top:var(--canon-space-8)}.xs\:cu-pt-9{padding-top:var(--canon-space-9)}.xs\:cu-pt-10{padding-top:var(--canon-space-10)}.xs\:cu-pt-11{padding-top:var(--canon-space-11)}.xs\:cu-pt-12{padding-top:var(--canon-space-12)}.xs\:cu-pt-13{padding-top:var(--canon-space-13)}.xs\:cu-pt-14{padding-top:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-pt{padding-top:var(--pt-sm)}.sm\:cu-pt-0\.5{padding-top:var(--canon-space-0_5)}.sm\:cu-pt-1{padding-top:var(--canon-space-1)}.sm\:cu-pt-1\.5{padding-top:var(--canon-space-1_5)}.sm\:cu-pt-2{padding-top:var(--canon-space-2)}.sm\:cu-pt-3{padding-top:var(--canon-space-3)}.sm\:cu-pt-4{padding-top:var(--canon-space-4)}.sm\:cu-pt-5{padding-top:var(--canon-space-5)}.sm\:cu-pt-6{padding-top:var(--canon-space-6)}.sm\:cu-pt-7{padding-top:var(--canon-space-7)}.sm\:cu-pt-8{padding-top:var(--canon-space-8)}.sm\:cu-pt-9{padding-top:var(--canon-space-9)}.sm\:cu-pt-10{padding-top:var(--canon-space-10)}.sm\:cu-pt-11{padding-top:var(--canon-space-11)}.sm\:cu-pt-12{padding-top:var(--canon-space-12)}.sm\:cu-pt-13{padding-top:var(--canon-space-13)}.sm\:cu-pt-14{padding-top:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-pt{padding-top:var(--pt-md)}.md\:cu-pt-0\.5{padding-top:var(--canon-space-0_5)}.md\:cu-pt-1{padding-top:var(--canon-space-1)}.md\:cu-pt-1\.5{padding-top:var(--canon-space-1_5)}.md\:cu-pt-2{padding-top:var(--canon-space-2)}.md\:cu-pt-3{padding-top:var(--canon-space-3)}.md\:cu-pt-4{padding-top:var(--canon-space-4)}.md\:cu-pt-5{padding-top:var(--canon-space-5)}.md\:cu-pt-6{padding-top:var(--canon-space-6)}.md\:cu-pt-7{padding-top:var(--canon-space-7)}.md\:cu-pt-8{padding-top:var(--canon-space-8)}.md\:cu-pt-9{padding-top:var(--canon-space-9)}.md\:cu-pt-10{padding-top:var(--canon-space-10)}.md\:cu-pt-11{padding-top:var(--canon-space-11)}.md\:cu-pt-12{padding-top:var(--canon-space-12)}.md\:cu-pt-13{padding-top:var(--canon-space-13)}.md\:cu-pt-14{padding-top:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-pt{padding-top:var(--pt-lg)}.lg\:cu-pt-0\.5{padding-top:var(--canon-space-0_5)}.lg\:cu-pt-1{padding-top:var(--canon-space-1)}.lg\:cu-pt-1\.5{padding-top:var(--canon-space-1_5)}.lg\:cu-pt-2{padding-top:var(--canon-space-2)}.lg\:cu-pt-3{padding-top:var(--canon-space-3)}.lg\:cu-pt-4{padding-top:var(--canon-space-4)}.lg\:cu-pt-5{padding-top:var(--canon-space-5)}.lg\:cu-pt-6{padding-top:var(--canon-space-6)}.lg\:cu-pt-7{padding-top:var(--canon-space-7)}.lg\:cu-pt-8{padding-top:var(--canon-space-8)}.lg\:cu-pt-9{padding-top:var(--canon-space-9)}.lg\:cu-pt-10{padding-top:var(--canon-space-10)}.lg\:cu-pt-11{padding-top:var(--canon-space-11)}.lg\:cu-pt-12{padding-top:var(--canon-space-12)}.lg\:cu-pt-13{padding-top:var(--canon-space-13)}.lg\:cu-pt-14{padding-top:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-pt{padding-top:var(--pt-xl)}.xl\:cu-pt-0\.5{padding-top:var(--canon-space-0_5)}.xl\:cu-pt-1{padding-top:var(--canon-space-1)}.xl\:cu-pt-1\.5{padding-top:var(--canon-space-1_5)}.xl\:cu-pt-2{padding-top:var(--canon-space-2)}.xl\:cu-pt-3{padding-top:var(--canon-space-3)}.xl\:cu-pt-4{padding-top:var(--canon-space-4)}.xl\:cu-pt-5{padding-top:var(--canon-space-5)}.xl\:cu-pt-6{padding-top:var(--canon-space-6)}.xl\:cu-pt-7{padding-top:var(--canon-space-7)}.xl\:cu-pt-8{padding-top:var(--canon-space-8)}.xl\:cu-pt-9{padding-top:var(--canon-space-9)}.xl\:cu-pt-10{padding-top:var(--canon-space-10)}.xl\:cu-pt-11{padding-top:var(--canon-space-11)}.xl\:cu-pt-12{padding-top:var(--canon-space-12)}.xl\:cu-pt-13{padding-top:var(--canon-space-13)}.xl\:cu-pt-14{padding-top:var(--canon-space-14)}}.cu-pb{padding-bottom:var(--pb)}.cu-pb-0\.5{padding-bottom:var(--canon-space-0_5)}.cu-pb-1{padding-bottom:var(--canon-space-1)}.cu-pb-1\.5{padding-bottom:var(--canon-space-1_5)}.cu-pb-2{padding-bottom:var(--canon-space-2)}.cu-pb-3{padding-bottom:var(--canon-space-3)}.cu-pb-4{padding-bottom:var(--canon-space-4)}.cu-pb-5{padding-bottom:var(--canon-space-5)}.cu-pb-6{padding-bottom:var(--canon-space-6)}.cu-pb-7{padding-bottom:var(--canon-space-7)}.cu-pb-8{padding-bottom:var(--canon-space-8)}.cu-pb-9{padding-bottom:var(--canon-space-9)}.cu-pb-10{padding-bottom:var(--canon-space-10)}.cu-pb-11{padding-bottom:var(--canon-space-11)}.cu-pb-12{padding-bottom:var(--canon-space-12)}.cu-pb-13{padding-bottom:var(--canon-space-13)}.cu-pb-14{padding-bottom:var(--canon-space-14)}@media (width>=640px){.xs\:cu-pb{padding-bottom:var(--pb-xs)}.xs\:cu-pb-0\.5{padding-bottom:var(--canon-space-0_5)}.xs\:cu-pb-1{padding-bottom:var(--canon-space-1)}.xs\:cu-pb-1\.5{padding-bottom:var(--canon-space-1_5)}.xs\:cu-pb-2{padding-bottom:var(--canon-space-2)}.xs\:cu-pb-3{padding-bottom:var(--canon-space-3)}.xs\:cu-pb-4{padding-bottom:var(--canon-space-4)}.xs\:cu-pb-5{padding-bottom:var(--canon-space-5)}.xs\:cu-pb-6{padding-bottom:var(--canon-space-6)}.xs\:cu-pb-7{padding-bottom:var(--canon-space-7)}.xs\:cu-pb-8{padding-bottom:var(--canon-space-8)}.xs\:cu-pb-9{padding-bottom:var(--canon-space-9)}.xs\:cu-pb-10{padding-bottom:var(--canon-space-10)}.xs\:cu-pb-11{padding-bottom:var(--canon-space-11)}.xs\:cu-pb-12{padding-bottom:var(--canon-space-12)}.xs\:cu-pb-13{padding-bottom:var(--canon-space-13)}.xs\:cu-pb-14{padding-bottom:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-pb{padding-bottom:var(--pb-sm)}.sm\:cu-pb-0\.5{padding-bottom:var(--canon-space-0_5)}.sm\:cu-pb-1{padding-bottom:var(--canon-space-1)}.sm\:cu-pb-1\.5{padding-bottom:var(--canon-space-1_5)}.sm\:cu-pb-2{padding-bottom:var(--canon-space-2)}.sm\:cu-pb-3{padding-bottom:var(--canon-space-3)}.sm\:cu-pb-4{padding-bottom:var(--canon-space-4)}.sm\:cu-pb-5{padding-bottom:var(--canon-space-5)}.sm\:cu-pb-6{padding-bottom:var(--canon-space-6)}.sm\:cu-pb-7{padding-bottom:var(--canon-space-7)}.sm\:cu-pb-8{padding-bottom:var(--canon-space-8)}.sm\:cu-pb-9{padding-bottom:var(--canon-space-9)}.sm\:cu-pb-10{padding-bottom:var(--canon-space-10)}.sm\:cu-pb-11{padding-bottom:var(--canon-space-11)}.sm\:cu-pb-12{padding-bottom:var(--canon-space-12)}.sm\:cu-pb-13{padding-bottom:var(--canon-space-13)}.sm\:cu-pb-14{padding-bottom:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-pb{padding-bottom:var(--pb-md)}.md\:cu-pb-0\.5{padding-bottom:var(--canon-space-0_5)}.md\:cu-pb-1{padding-bottom:var(--canon-space-1)}.md\:cu-pb-1\.5{padding-bottom:var(--canon-space-1_5)}.md\:cu-pb-2{padding-bottom:var(--canon-space-2)}.md\:cu-pb-3{padding-bottom:var(--canon-space-3)}.md\:cu-pb-4{padding-bottom:var(--canon-space-4)}.md\:cu-pb-5{padding-bottom:var(--canon-space-5)}.md\:cu-pb-6{padding-bottom:var(--canon-space-6)}.md\:cu-pb-7{padding-bottom:var(--canon-space-7)}.md\:cu-pb-8{padding-bottom:var(--canon-space-8)}.md\:cu-pb-9{padding-bottom:var(--canon-space-9)}.md\:cu-pb-10{padding-bottom:var(--canon-space-10)}.md\:cu-pb-11{padding-bottom:var(--canon-space-11)}.md\:cu-pb-12{padding-bottom:var(--canon-space-12)}.md\:cu-pb-13{padding-bottom:var(--canon-space-13)}.md\:cu-pb-14{padding-bottom:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-pb{padding-bottom:var(--pb-lg)}.lg\:cu-pb-0\.5{padding-bottom:var(--canon-space-0_5)}.lg\:cu-pb-1{padding-bottom:var(--canon-space-1)}.lg\:cu-pb-1\.5{padding-bottom:var(--canon-space-1_5)}.lg\:cu-pb-2{padding-bottom:var(--canon-space-2)}.lg\:cu-pb-3{padding-bottom:var(--canon-space-3)}.lg\:cu-pb-4{padding-bottom:var(--canon-space-4)}.lg\:cu-pb-5{padding-bottom:var(--canon-space-5)}.lg\:cu-pb-6{padding-bottom:var(--canon-space-6)}.lg\:cu-pb-7{padding-bottom:var(--canon-space-7)}.lg\:cu-pb-8{padding-bottom:var(--canon-space-8)}.lg\:cu-pb-9{padding-bottom:var(--canon-space-9)}.lg\:cu-pb-10{padding-bottom:var(--canon-space-10)}.lg\:cu-pb-11{padding-bottom:var(--canon-space-11)}.lg\:cu-pb-12{padding-bottom:var(--canon-space-12)}.lg\:cu-pb-13{padding-bottom:var(--canon-space-13)}.lg\:cu-pb-14{padding-bottom:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-pb{padding-bottom:var(--pb-xl)}.xl\:cu-pb-0\.5{padding-bottom:var(--canon-space-0_5)}.xl\:cu-pb-1{padding-bottom:var(--canon-space-1)}.xl\:cu-pb-1\.5{padding-bottom:var(--canon-space-1_5)}.xl\:cu-pb-2{padding-bottom:var(--canon-space-2)}.xl\:cu-pb-3{padding-bottom:var(--canon-space-3)}.xl\:cu-pb-4{padding-bottom:var(--canon-space-4)}.xl\:cu-pb-5{padding-bottom:var(--canon-space-5)}.xl\:cu-pb-6{padding-bottom:var(--canon-space-6)}.xl\:cu-pb-7{padding-bottom:var(--canon-space-7)}.xl\:cu-pb-8{padding-bottom:var(--canon-space-8)}.xl\:cu-pb-9{padding-bottom:var(--canon-space-9)}.xl\:cu-pb-10{padding-bottom:var(--canon-space-10)}.xl\:cu-pb-11{padding-bottom:var(--canon-space-11)}.xl\:cu-pb-12{padding-bottom:var(--canon-space-12)}.xl\:cu-pb-13{padding-bottom:var(--canon-space-13)}.xl\:cu-pb-14{padding-bottom:var(--canon-space-14)}}.cu-py{padding-top:var(--py);padding-bottom:var(--py)}.cu-py-0\.5{padding-top:var(--canon-space-0_5);padding-bottom:var(--canon-space-0_5)}.cu-py-1{padding-top:var(--canon-space-1);padding-bottom:var(--canon-space-1)}.cu-py-1\.5{padding-top:var(--canon-space-1_5);padding-bottom:var(--canon-space-1_5)}.cu-py-2{padding-top:var(--canon-space-2);padding-bottom:var(--canon-space-2)}.cu-py-3{padding-top:var(--canon-space-3);padding-bottom:var(--canon-space-3)}.cu-py-4{padding-top:var(--canon-space-4);padding-bottom:var(--canon-space-4)}.cu-py-5{padding-top:var(--canon-space-5);padding-bottom:var(--canon-space-5)}.cu-py-6{padding-top:var(--canon-space-6);padding-bottom:var(--canon-space-6)}.cu-py-7{padding-top:var(--canon-space-7);padding-bottom:var(--canon-space-7)}.cu-py-8{padding-top:var(--canon-space-8);padding-bottom:var(--canon-space-8)}.cu-py-9{padding-top:var(--canon-space-9);padding-bottom:var(--canon-space-9)}.cu-py-10{padding-top:var(--canon-space-10);padding-bottom:var(--canon-space-10)}.cu-py-11{padding-top:var(--canon-space-11);padding-bottom:var(--canon-space-11)}.cu-py-12{padding-top:var(--canon-space-12);padding-bottom:var(--canon-space-12)}.cu-py-13{padding-top:var(--canon-space-13);padding-bottom:var(--canon-space-13)}.cu-py-14{padding-top:var(--canon-space-14);padding-bottom:var(--canon-space-14)}@media (width>=640px){.xs\:cu-py{padding-top:var(--py-xs);padding-bottom:var(--py-xs)}.xs\:cu-py-0\.5{padding-top:var(--canon-space-0_5);padding-bottom:var(--canon-space-0_5)}.xs\:cu-py-1{padding-top:var(--canon-space-1);padding-bottom:var(--canon-space-1)}.xs\:cu-py-1\.5{padding-top:var(--canon-space-1_5);padding-bottom:var(--canon-space-1_5)}.xs\:cu-py-2{padding-top:var(--canon-space-2);padding-bottom:var(--canon-space-2)}.xs\:cu-py-3{padding-top:var(--canon-space-3);padding-bottom:var(--canon-space-3)}.xs\:cu-py-4{padding-top:var(--canon-space-4);padding-bottom:var(--canon-space-4)}.xs\:cu-py-5{padding-top:var(--canon-space-5);padding-bottom:var(--canon-space-5)}.xs\:cu-py-6{padding-top:var(--canon-space-6);padding-bottom:var(--canon-space-6)}.xs\:cu-py-7{padding-top:var(--canon-space-7);padding-bottom:var(--canon-space-7)}.xs\:cu-py-8{padding-top:var(--canon-space-8);padding-bottom:var(--canon-space-8)}.xs\:cu-py-9{padding-top:var(--canon-space-9);padding-bottom:var(--canon-space-9)}.xs\:cu-py-10{padding-top:var(--canon-space-10);padding-bottom:var(--canon-space-10)}.xs\:cu-py-11{padding-top:var(--canon-space-11);padding-bottom:var(--canon-space-11)}.xs\:cu-py-12{padding-top:var(--canon-space-12);padding-bottom:var(--canon-space-12)}.xs\:cu-py-13{padding-top:var(--canon-space-13);padding-bottom:var(--canon-space-13)}.xs\:cu-py-14{padding-top:var(--canon-space-14);padding-bottom:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-py{padding-top:var(--py-sm);padding-bottom:var(--py-sm)}.sm\:cu-py-0\.5{padding-top:var(--canon-space-0_5);padding-bottom:var(--canon-space-0_5)}.sm\:cu-py-1{padding-top:var(--canon-space-1);padding-bottom:var(--canon-space-1)}.sm\:cu-py-1\.5{padding-top:var(--canon-space-1_5);padding-bottom:var(--canon-space-1_5)}.sm\:cu-py-2{padding-top:var(--canon-space-2);padding-bottom:var(--canon-space-2)}.sm\:cu-py-3{padding-top:var(--canon-space-3);padding-bottom:var(--canon-space-3)}.sm\:cu-py-4{padding-top:var(--canon-space-4);padding-bottom:var(--canon-space-4)}.sm\:cu-py-5{padding-top:var(--canon-space-5);padding-bottom:var(--canon-space-5)}.sm\:cu-py-6{padding-top:var(--canon-space-6);padding-bottom:var(--canon-space-6)}.sm\:cu-py-7{padding-top:var(--canon-space-7);padding-bottom:var(--canon-space-7)}.sm\:cu-py-8{padding-top:var(--canon-space-8);padding-bottom:var(--canon-space-8)}.sm\:cu-py-9{padding-top:var(--canon-space-9);padding-bottom:var(--canon-space-9)}.sm\:cu-py-10{padding-top:var(--canon-space-10);padding-bottom:var(--canon-space-10)}.sm\:cu-py-11{padding-top:var(--canon-space-11);padding-bottom:var(--canon-space-11)}.sm\:cu-py-12{padding-top:var(--canon-space-12);padding-bottom:var(--canon-space-12)}.sm\:cu-py-13{padding-top:var(--canon-space-13);padding-bottom:var(--canon-space-13)}.sm\:cu-py-14{padding-top:var(--canon-space-14);padding-bottom:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-py{padding-top:var(--py-md);padding-bottom:var(--py-md)}.md\:cu-py-0\.5{padding-top:var(--canon-space-0_5);padding-bottom:var(--canon-space-0_5)}.md\:cu-py-1{padding-top:var(--canon-space-1);padding-bottom:var(--canon-space-1)}.md\:cu-py-1\.5{padding-top:var(--canon-space-1_5);padding-bottom:var(--canon-space-1_5)}.md\:cu-py-2{padding-top:var(--canon-space-2);padding-bottom:var(--canon-space-2)}.md\:cu-py-3{padding-top:var(--canon-space-3);padding-bottom:var(--canon-space-3)}.md\:cu-py-4{padding-top:var(--canon-space-4);padding-bottom:var(--canon-space-4)}.md\:cu-py-5{padding-top:var(--canon-space-5);padding-bottom:var(--canon-space-5)}.md\:cu-py-6{padding-top:var(--canon-space-6);padding-bottom:var(--canon-space-6)}.md\:cu-py-7{padding-top:var(--canon-space-7);padding-bottom:var(--canon-space-7)}.md\:cu-py-8{padding-top:var(--canon-space-8);padding-bottom:var(--canon-space-8)}.md\:cu-py-9{padding-top:var(--canon-space-9);padding-bottom:var(--canon-space-9)}.md\:cu-py-10{padding-top:var(--canon-space-10);padding-bottom:var(--canon-space-10)}.md\:cu-py-11{padding-top:var(--canon-space-11);padding-bottom:var(--canon-space-11)}.md\:cu-py-12{padding-top:var(--canon-space-12);padding-bottom:var(--canon-space-12)}.md\:cu-py-13{padding-top:var(--canon-space-13);padding-bottom:var(--canon-space-13)}.md\:cu-py-14{padding-top:var(--canon-space-14);padding-bottom:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-py{padding-top:var(--py-lg);padding-bottom:var(--py-lg)}.lg\:cu-py-0\.5{padding-top:var(--canon-space-0_5);padding-bottom:var(--canon-space-0_5)}.lg\:cu-py-1{padding-top:var(--canon-space-1);padding-bottom:var(--canon-space-1)}.lg\:cu-py-1\.5{padding-top:var(--canon-space-1_5);padding-bottom:var(--canon-space-1_5)}.lg\:cu-py-2{padding-top:var(--canon-space-2);padding-bottom:var(--canon-space-2)}.lg\:cu-py-3{padding-top:var(--canon-space-3);padding-bottom:var(--canon-space-3)}.lg\:cu-py-4{padding-top:var(--canon-space-4);padding-bottom:var(--canon-space-4)}.lg\:cu-py-5{padding-top:var(--canon-space-5);padding-bottom:var(--canon-space-5)}.lg\:cu-py-6{padding-top:var(--canon-space-6);padding-bottom:var(--canon-space-6)}.lg\:cu-py-7{padding-top:var(--canon-space-7);padding-bottom:var(--canon-space-7)}.lg\:cu-py-8{padding-top:var(--canon-space-8);padding-bottom:var(--canon-space-8)}.lg\:cu-py-9{padding-top:var(--canon-space-9);padding-bottom:var(--canon-space-9)}.lg\:cu-py-10{padding-top:var(--canon-space-10);padding-bottom:var(--canon-space-10)}.lg\:cu-py-11{padding-top:var(--canon-space-11);padding-bottom:var(--canon-space-11)}.lg\:cu-py-12{padding-top:var(--canon-space-12);padding-bottom:var(--canon-space-12)}.lg\:cu-py-13{padding-top:var(--canon-space-13);padding-bottom:var(--canon-space-13)}.lg\:cu-py-14{padding-top:var(--canon-space-14);padding-bottom:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-py{padding-top:var(--py-xl);padding-bottom:var(--py-xl)}.xl\:cu-py-0\.5{padding-top:var(--canon-space-0_5);padding-bottom:var(--canon-space-0_5)}.xl\:cu-py-1{padding-top:var(--canon-space-1);padding-bottom:var(--canon-space-1)}.xl\:cu-py-1\.5{padding-top:var(--canon-space-1_5);padding-bottom:var(--canon-space-1_5)}.xl\:cu-py-2{padding-top:var(--canon-space-2);padding-bottom:var(--canon-space-2)}.xl\:cu-py-3{padding-top:var(--canon-space-3);padding-bottom:var(--canon-space-3)}.xl\:cu-py-4{padding-top:var(--canon-space-4);padding-bottom:var(--canon-space-4)}.xl\:cu-py-5{padding-top:var(--canon-space-5);padding-bottom:var(--canon-space-5)}.xl\:cu-py-6{padding-top:var(--canon-space-6);padding-bottom:var(--canon-space-6)}.xl\:cu-py-7{padding-top:var(--canon-space-7);padding-bottom:var(--canon-space-7)}.xl\:cu-py-8{padding-top:var(--canon-space-8);padding-bottom:var(--canon-space-8)}.xl\:cu-py-9{padding-top:var(--canon-space-9);padding-bottom:var(--canon-space-9)}.xl\:cu-py-10{padding-top:var(--canon-space-10);padding-bottom:var(--canon-space-10)}.xl\:cu-py-11{padding-top:var(--canon-space-11);padding-bottom:var(--canon-space-11)}.xl\:cu-py-12{padding-top:var(--canon-space-12);padding-bottom:var(--canon-space-12)}.xl\:cu-py-13{padding-top:var(--canon-space-13);padding-bottom:var(--canon-space-13)}.xl\:cu-py-14{padding-top:var(--canon-space-14);padding-bottom:var(--canon-space-14)}}.cu-px{padding-left:var(--px);padding-right:var(--px)}.cu-px-0\.5{padding-left:var(--canon-space-0_5);padding-right:var(--canon-space-0_5)}.cu-px-1{padding-left:var(--canon-space-1);padding-right:var(--canon-space-1)}.cu-px-1\.5{padding-left:var(--canon-space-1_5);padding-right:var(--canon-space-1_5)}.cu-px-2{padding-left:var(--canon-space-2);padding-right:var(--canon-space-2)}.cu-px-3{padding-left:var(--canon-space-3);padding-right:var(--canon-space-3)}.cu-px-4{padding-left:var(--canon-space-4);padding-right:var(--canon-space-4)}.cu-px-5{padding-left:var(--canon-space-5);padding-right:var(--canon-space-5)}.cu-px-6{padding-left:var(--canon-space-6);padding-right:var(--canon-space-6)}.cu-px-7{padding-left:var(--canon-space-7);padding-right:var(--canon-space-7)}.cu-px-8{padding-left:var(--canon-space-8);padding-right:var(--canon-space-8)}.cu-px-9{padding-left:var(--canon-space-9);padding-right:var(--canon-space-9)}.cu-px-10{padding-left:var(--canon-space-10);padding-right:var(--canon-space-10)}.cu-px-11{padding-left:var(--canon-space-11);padding-right:var(--canon-space-11)}.cu-px-12{padding-left:var(--canon-space-12);padding-right:var(--canon-space-12)}.cu-px-13{padding-left:var(--canon-space-13);padding-right:var(--canon-space-13)}.cu-px-14{padding-left:var(--canon-space-14);padding-right:var(--canon-space-14)}@media (width>=640px){.xs\:cu-px{padding-left:var(--px-xs);padding-right:var(--px-xs)}.xs\:cu-px-0\.5{padding-left:var(--canon-space-0_5);padding-right:var(--canon-space-0_5)}.xs\:cu-px-1{padding-left:var(--canon-space-1);padding-right:var(--canon-space-1)}.xs\:cu-px-1\.5{padding-left:var(--canon-space-1_5);padding-right:var(--canon-space-1_5)}.xs\:cu-px-2{padding-left:var(--canon-space-2);padding-right:var(--canon-space-2)}.xs\:cu-px-3{padding-left:var(--canon-space-3);padding-right:var(--canon-space-3)}.xs\:cu-px-4{padding-left:var(--canon-space-4);padding-right:var(--canon-space-4)}.xs\:cu-px-5{padding-left:var(--canon-space-5);padding-right:var(--canon-space-5)}.xs\:cu-px-6{padding-left:var(--canon-space-6);padding-right:var(--canon-space-6)}.xs\:cu-px-7{padding-left:var(--canon-space-7);padding-right:var(--canon-space-7)}.xs\:cu-px-8{padding-left:var(--canon-space-8);padding-right:var(--canon-space-8)}.xs\:cu-px-9{padding-left:var(--canon-space-9);padding-right:var(--canon-space-9)}.xs\:cu-px-10{padding-left:var(--canon-space-10);padding-right:var(--canon-space-10)}.xs\:cu-px-11{padding-left:var(--canon-space-11);padding-right:var(--canon-space-11)}.xs\:cu-px-12{padding-left:var(--canon-space-12);padding-right:var(--canon-space-12)}.xs\:cu-px-13{padding-left:var(--canon-space-13);padding-right:var(--canon-space-13)}.xs\:cu-px-14{padding-left:var(--canon-space-14);padding-right:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-px{padding-left:var(--px-sm);padding-right:var(--px-sm)}.sm\:cu-px-0\.5{padding-left:var(--canon-space-0_5);padding-right:var(--canon-space-0_5)}.sm\:cu-px-1{padding-left:var(--canon-space-1);padding-right:var(--canon-space-1)}.sm\:cu-px-1\.5{padding-left:var(--canon-space-1_5);padding-right:var(--canon-space-1_5)}.sm\:cu-px-2{padding-left:var(--canon-space-2);padding-right:var(--canon-space-2)}.sm\:cu-px-3{padding-left:var(--canon-space-3);padding-right:var(--canon-space-3)}.sm\:cu-px-4{padding-left:var(--canon-space-4);padding-right:var(--canon-space-4)}.sm\:cu-px-5{padding-left:var(--canon-space-5);padding-right:var(--canon-space-5)}.sm\:cu-px-6{padding-left:var(--canon-space-6);padding-right:var(--canon-space-6)}.sm\:cu-px-7{padding-left:var(--canon-space-7);padding-right:var(--canon-space-7)}.sm\:cu-px-8{padding-left:var(--canon-space-8);padding-right:var(--canon-space-8)}.sm\:cu-px-9{padding-left:var(--canon-space-9);padding-right:var(--canon-space-9)}.sm\:cu-px-10{padding-left:var(--canon-space-10);padding-right:var(--canon-space-10)}.sm\:cu-px-11{padding-left:var(--canon-space-11);padding-right:var(--canon-space-11)}.sm\:cu-px-12{padding-left:var(--canon-space-12);padding-right:var(--canon-space-12)}.sm\:cu-px-13{padding-left:var(--canon-space-13);padding-right:var(--canon-space-13)}.sm\:cu-px-14{padding-left:var(--canon-space-14);padding-right:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-px{padding-left:var(--px-md);padding-right:var(--px-md)}.md\:cu-px-0\.5{padding-left:var(--canon-space-0_5);padding-right:var(--canon-space-0_5)}.md\:cu-px-1{padding-left:var(--canon-space-1);padding-right:var(--canon-space-1)}.md\:cu-px-1\.5{padding-left:var(--canon-space-1_5);padding-right:var(--canon-space-1_5)}.md\:cu-px-2{padding-left:var(--canon-space-2);padding-right:var(--canon-space-2)}.md\:cu-px-3{padding-left:var(--canon-space-3);padding-right:var(--canon-space-3)}.md\:cu-px-4{padding-left:var(--canon-space-4);padding-right:var(--canon-space-4)}.md\:cu-px-5{padding-left:var(--canon-space-5);padding-right:var(--canon-space-5)}.md\:cu-px-6{padding-left:var(--canon-space-6);padding-right:var(--canon-space-6)}.md\:cu-px-7{padding-left:var(--canon-space-7);padding-right:var(--canon-space-7)}.md\:cu-px-8{padding-left:var(--canon-space-8);padding-right:var(--canon-space-8)}.md\:cu-px-9{padding-left:var(--canon-space-9);padding-right:var(--canon-space-9)}.md\:cu-px-10{padding-left:var(--canon-space-10);padding-right:var(--canon-space-10)}.md\:cu-px-11{padding-left:var(--canon-space-11);padding-right:var(--canon-space-11)}.md\:cu-px-12{padding-left:var(--canon-space-12);padding-right:var(--canon-space-12)}.md\:cu-px-13{padding-left:var(--canon-space-13);padding-right:var(--canon-space-13)}.md\:cu-px-14{padding-left:var(--canon-space-14);padding-right:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-px{padding-left:var(--px-lg);padding-right:var(--px-lg)}.lg\:cu-px-0\.5{padding-left:var(--canon-space-0_5);padding-right:var(--canon-space-0_5)}.lg\:cu-px-1{padding-left:var(--canon-space-1);padding-right:var(--canon-space-1)}.lg\:cu-px-1\.5{padding-left:var(--canon-space-1_5);padding-right:var(--canon-space-1_5)}.lg\:cu-px-2{padding-left:var(--canon-space-2);padding-right:var(--canon-space-2)}.lg\:cu-px-3{padding-left:var(--canon-space-3);padding-right:var(--canon-space-3)}.lg\:cu-px-4{padding-left:var(--canon-space-4);padding-right:var(--canon-space-4)}.lg\:cu-px-5{padding-left:var(--canon-space-5);padding-right:var(--canon-space-5)}.lg\:cu-px-6{padding-left:var(--canon-space-6);padding-right:var(--canon-space-6)}.lg\:cu-px-7{padding-left:var(--canon-space-7);padding-right:var(--canon-space-7)}.lg\:cu-px-8{padding-left:var(--canon-space-8);padding-right:var(--canon-space-8)}.lg\:cu-px-9{padding-left:var(--canon-space-9);padding-right:var(--canon-space-9)}.lg\:cu-px-10{padding-left:var(--canon-space-10);padding-right:var(--canon-space-10)}.lg\:cu-px-11{padding-left:var(--canon-space-11);padding-right:var(--canon-space-11)}.lg\:cu-px-12{padding-left:var(--canon-space-12);padding-right:var(--canon-space-12)}.lg\:cu-px-13{padding-left:var(--canon-space-13);padding-right:var(--canon-space-13)}.lg\:cu-px-14{padding-left:var(--canon-space-14);padding-right:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-px{padding-left:var(--px-xl);padding-right:var(--px-xl)}.xl\:cu-px-0\.5{padding-left:var(--canon-space-0_5);padding-right:var(--canon-space-0_5)}.xl\:cu-px-1{padding-left:var(--canon-space-1);padding-right:var(--canon-space-1)}.xl\:cu-px-1\.5{padding-left:var(--canon-space-1_5);padding-right:var(--canon-space-1_5)}.xl\:cu-px-2{padding-left:var(--canon-space-2);padding-right:var(--canon-space-2)}.xl\:cu-px-3{padding-left:var(--canon-space-3);padding-right:var(--canon-space-3)}.xl\:cu-px-4{padding-left:var(--canon-space-4);padding-right:var(--canon-space-4)}.xl\:cu-px-5{padding-left:var(--canon-space-5);padding-right:var(--canon-space-5)}.xl\:cu-px-6{padding-left:var(--canon-space-6);padding-right:var(--canon-space-6)}.xl\:cu-px-7{padding-left:var(--canon-space-7);padding-right:var(--canon-space-7)}.xl\:cu-px-8{padding-left:var(--canon-space-8);padding-right:var(--canon-space-8)}.xl\:cu-px-9{padding-left:var(--canon-space-9);padding-right:var(--canon-space-9)}.xl\:cu-px-10{padding-left:var(--canon-space-10);padding-right:var(--canon-space-10)}.xl\:cu-px-11{padding-left:var(--canon-space-11);padding-right:var(--canon-space-11)}.xl\:cu-px-12{padding-left:var(--canon-space-12);padding-right:var(--canon-space-12)}.xl\:cu-px-13{padding-left:var(--canon-space-13);padding-right:var(--canon-space-13)}.xl\:cu-px-14{padding-left:var(--canon-space-14);padding-right:var(--canon-space-14)}}.cu-m{margin:var(--m)}.cu-m-0\.5{margin:var(--canon-space-0_5)}.cu-m-1{margin:var(--canon-space-1)}.cu-m-1\.5{margin:var(--canon-space-1_5)}.cu-m-2{margin:var(--canon-space-2)}.cu-m-3{margin:var(--canon-space-3)}.cu-m-4{margin:var(--canon-space-4)}.cu-m-5{margin:var(--canon-space-5)}.cu-m-6{margin:var(--canon-space-6)}.cu-m-7{margin:var(--canon-space-7)}.cu-m-8{margin:var(--canon-space-8)}.cu-m-9{margin:var(--canon-space-9)}.cu-m-10{margin:var(--canon-space-10)}.cu-m-11{margin:var(--canon-space-11)}.cu-m-12{margin:var(--canon-space-12)}.cu-m-13{margin:var(--canon-space-13)}.cu-m-14{margin:var(--canon-space-14)}@media (width>=640px){.xs\:cu-m{margin:var(--p-xs)}.xs\:cu-m-0\.5{margin:var(--canon-space-0_5)}.xs\:cu-m-1{margin:var(--canon-space-1)}.xs\:cu-m-1\.5{margin:var(--canon-space-1_5)}.xs\:cu-m-2{margin:var(--canon-space-2)}.xs\:cu-m-3{margin:var(--canon-space-3)}.xs\:cu-m-4{margin:var(--canon-space-4)}.xs\:cu-m-5{margin:var(--canon-space-5)}.xs\:cu-m-6{margin:var(--canon-space-6)}.xs\:cu-m-7{margin:var(--canon-space-7)}.xs\:cu-m-8{margin:var(--canon-space-8)}.xs\:cu-m-9{margin:var(--canon-space-9)}.xs\:cu-m-10{margin:var(--canon-space-10)}.xs\:cu-m-11{margin:var(--canon-space-11)}.xs\:cu-m-12{margin:var(--canon-space-12)}.xs\:cu-m-13{margin:var(--canon-space-13)}.xs\:cu-m-14{margin:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-m{margin:var(--p-sm)}.sm\:cu-m-0\.5{margin:var(--canon-space-0_5)}.sm\:cu-m-1{margin:var(--canon-space-1)}.sm\:cu-m-1\.5{margin:var(--canon-space-1_5)}.sm\:cu-m-2{margin:var(--canon-space-2)}.sm\:cu-m-3{margin:var(--canon-space-3)}.sm\:cu-m-4{margin:var(--canon-space-4)}.sm\:cu-m-5{margin:var(--canon-space-5)}.sm\:cu-m-6{margin:var(--canon-space-6)}.sm\:cu-m-7{margin:var(--canon-space-7)}.sm\:cu-m-8{margin:var(--canon-space-8)}.sm\:cu-m-9{margin:var(--canon-space-9)}.sm\:cu-m-10{margin:var(--canon-space-10)}.sm\:cu-m-11{margin:var(--canon-space-11)}.sm\:cu-m-12{margin:var(--canon-space-12)}.sm\:cu-m-13{margin:var(--canon-space-13)}.sm\:cu-m-14{margin:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-m{margin:var(--p-md)}.md\:cu-m-0\.5{margin:var(--canon-space-0_5)}.md\:cu-m-1{margin:var(--canon-space-1)}.md\:cu-m-1\.5{margin:var(--canon-space-1_5)}.md\:cu-m-2{margin:var(--canon-space-2)}.md\:cu-m-3{margin:var(--canon-space-3)}.md\:cu-m-4{margin:var(--canon-space-4)}.md\:cu-m-5{margin:var(--canon-space-5)}.md\:cu-m-6{margin:var(--canon-space-6)}.md\:cu-m-7{margin:var(--canon-space-7)}.md\:cu-m-8{margin:var(--canon-space-8)}.md\:cu-m-9{margin:var(--canon-space-9)}.md\:cu-m-10{margin:var(--canon-space-10)}.md\:cu-m-11{margin:var(--canon-space-11)}.md\:cu-m-12{margin:var(--canon-space-12)}.md\:cu-m-13{margin:var(--canon-space-13)}.md\:cu-m-14{margin:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-m{margin:var(--p-lg)}.lg\:cu-m-0\.5{margin:var(--canon-space-0_5)}.lg\:cu-m-1{margin:var(--canon-space-1)}.lg\:cu-m-1\.5{margin:var(--canon-space-1_5)}.lg\:cu-m-2{margin:var(--canon-space-2)}.lg\:cu-m-3{margin:var(--canon-space-3)}.lg\:cu-m-4{margin:var(--canon-space-4)}.lg\:cu-m-5{margin:var(--canon-space-5)}.lg\:cu-m-6{margin:var(--canon-space-6)}.lg\:cu-m-7{margin:var(--canon-space-7)}.lg\:cu-m-8{margin:var(--canon-space-8)}.lg\:cu-m-9{margin:var(--canon-space-9)}.lg\:cu-m-10{margin:var(--canon-space-10)}.lg\:cu-m-11{margin:var(--canon-space-11)}.lg\:cu-m-12{margin:var(--canon-space-12)}.lg\:cu-m-13{margin:var(--canon-space-13)}.lg\:cu-m-14{margin:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-m{margin:var(--p-xl)}.xl\:cu-m-0\.5{margin:var(--canon-space-0_5)}.xl\:cu-m-1{margin:var(--canon-space-1)}.xl\:cu-m-1\.5{margin:var(--canon-space-1_5)}.xl\:cu-m-2{margin:var(--canon-space-2)}.xl\:cu-m-3{margin:var(--canon-space-3)}.xl\:cu-m-4{margin:var(--canon-space-4)}.xl\:cu-m-5{margin:var(--canon-space-5)}.xl\:cu-m-6{margin:var(--canon-space-6)}.xl\:cu-m-7{margin:var(--canon-space-7)}.xl\:cu-m-8{margin:var(--canon-space-8)}.xl\:cu-m-9{margin:var(--canon-space-9)}.xl\:cu-m-10{margin:var(--canon-space-10)}.xl\:cu-m-11{margin:var(--canon-space-11)}.xl\:cu-m-12{margin:var(--canon-space-12)}.xl\:cu-m-13{margin:var(--canon-space-13)}.xl\:cu-m-14{margin:var(--canon-space-14)}}.cu-ml{margin-left:var(--ml)}.cu-ml-0\.5{margin-left:var(--canon-space-0_5)}.cu-ml-1{margin-left:var(--canon-space-1)}.cu-ml-1\.5{margin-left:var(--canon-space-1_5)}.cu-ml-2{margin-left:var(--canon-space-2)}.cu-ml-3{margin-left:var(--canon-space-3)}.cu-ml-4{margin-left:var(--canon-space-4)}.cu-ml-5{margin-left:var(--canon-space-5)}.cu-ml-6{margin-left:var(--canon-space-6)}.cu-ml-7{margin-left:var(--canon-space-7)}.cu-ml-8{margin-left:var(--canon-space-8)}.cu-ml-9{margin-left:var(--canon-space-9)}.cu-ml-10{margin-left:var(--canon-space-10)}.cu-ml-11{margin-left:var(--canon-space-11)}.cu-ml-12{margin-left:var(--canon-space-12)}.cu-ml-13{margin-left:var(--canon-space-13)}.cu-ml-14{margin-left:var(--canon-space-14)}@media (width>=640px){.xs\:cu-ml{margin-left:var(--pl-xs)}.xs\:cu-ml-0\.5{margin-left:var(--canon-space-0_5)}.xs\:cu-ml-1{margin-left:var(--canon-space-1)}.xs\:cu-ml-1\.5{margin-left:var(--canon-space-1_5)}.xs\:cu-ml-2{margin-left:var(--canon-space-2)}.xs\:cu-ml-3{margin-left:var(--canon-space-3)}.xs\:cu-ml-4{margin-left:var(--canon-space-4)}.xs\:cu-ml-5{margin-left:var(--canon-space-5)}.xs\:cu-ml-6{margin-left:var(--canon-space-6)}.xs\:cu-ml-7{margin-left:var(--canon-space-7)}.xs\:cu-ml-8{margin-left:var(--canon-space-8)}.xs\:cu-ml-9{margin-left:var(--canon-space-9)}.xs\:cu-ml-10{margin-left:var(--canon-space-10)}.xs\:cu-ml-11{margin-left:var(--canon-space-11)}.xs\:cu-ml-12{margin-left:var(--canon-space-12)}.xs\:cu-ml-13{margin-left:var(--canon-space-13)}.xs\:cu-ml-14{margin-left:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-ml{margin-left:var(--pl-sm)}.sm\:cu-ml-0\.5{margin-left:var(--canon-space-0_5)}.sm\:cu-ml-1{margin-left:var(--canon-space-1)}.sm\:cu-ml-1\.5{margin-left:var(--canon-space-1_5)}.sm\:cu-ml-2{margin-left:var(--canon-space-2)}.sm\:cu-ml-3{margin-left:var(--canon-space-3)}.sm\:cu-ml-4{margin-left:var(--canon-space-4)}.sm\:cu-ml-5{margin-left:var(--canon-space-5)}.sm\:cu-ml-6{margin-left:var(--canon-space-6)}.sm\:cu-ml-7{margin-left:var(--canon-space-7)}.sm\:cu-ml-8{margin-left:var(--canon-space-8)}.sm\:cu-ml-9{margin-left:var(--canon-space-9)}.sm\:cu-ml-10{margin-left:var(--canon-space-10)}.sm\:cu-ml-11{margin-left:var(--canon-space-11)}.sm\:cu-ml-12{margin-left:var(--canon-space-12)}.sm\:cu-ml-13{margin-left:var(--canon-space-13)}.sm\:cu-ml-14{margin-left:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-ml{margin-left:var(--pl-md)}.md\:cu-ml-0\.5{margin-left:var(--canon-space-0_5)}.md\:cu-ml-1{margin-left:var(--canon-space-1)}.md\:cu-ml-1\.5{margin-left:var(--canon-space-1_5)}.md\:cu-ml-2{margin-left:var(--canon-space-2)}.md\:cu-ml-3{margin-left:var(--canon-space-3)}.md\:cu-ml-4{margin-left:var(--canon-space-4)}.md\:cu-ml-5{margin-left:var(--canon-space-5)}.md\:cu-ml-6{margin-left:var(--canon-space-6)}.md\:cu-ml-7{margin-left:var(--canon-space-7)}.md\:cu-ml-8{margin-left:var(--canon-space-8)}.md\:cu-ml-9{margin-left:var(--canon-space-9)}.md\:cu-ml-10{margin-left:var(--canon-space-10)}.md\:cu-ml-11{margin-left:var(--canon-space-11)}.md\:cu-ml-12{margin-left:var(--canon-space-12)}.md\:cu-ml-13{margin-left:var(--canon-space-13)}.md\:cu-ml-14{margin-left:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-ml{margin-left:var(--pl-lg)}.lg\:cu-ml-0\.5{margin-left:var(--canon-space-0_5)}.lg\:cu-ml-1{margin-left:var(--canon-space-1)}.lg\:cu-ml-1\.5{margin-left:var(--canon-space-1_5)}.lg\:cu-ml-2{margin-left:var(--canon-space-2)}.lg\:cu-ml-3{margin-left:var(--canon-space-3)}.lg\:cu-ml-4{margin-left:var(--canon-space-4)}.lg\:cu-ml-5{margin-left:var(--canon-space-5)}.lg\:cu-ml-6{margin-left:var(--canon-space-6)}.lg\:cu-ml-7{margin-left:var(--canon-space-7)}.lg\:cu-ml-8{margin-left:var(--canon-space-8)}.lg\:cu-ml-9{margin-left:var(--canon-space-9)}.lg\:cu-ml-10{margin-left:var(--canon-space-10)}.lg\:cu-ml-11{margin-left:var(--canon-space-11)}.lg\:cu-ml-12{margin-left:var(--canon-space-12)}.lg\:cu-ml-13{margin-left:var(--canon-space-13)}.lg\:cu-ml-14{margin-left:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-ml{margin-left:var(--pl-xl)}.xl\:cu-ml-0\.5{margin-left:var(--canon-space-0_5)}.xl\:cu-ml-1{margin-left:var(--canon-space-1)}.xl\:cu-ml-1\.5{margin-left:var(--canon-space-1_5)}.xl\:cu-ml-2{margin-left:var(--canon-space-2)}.xl\:cu-ml-3{margin-left:var(--canon-space-3)}.xl\:cu-ml-4{margin-left:var(--canon-space-4)}.xl\:cu-ml-5{margin-left:var(--canon-space-5)}.xl\:cu-ml-6{margin-left:var(--canon-space-6)}.xl\:cu-ml-7{margin-left:var(--canon-space-7)}.xl\:cu-ml-8{margin-left:var(--canon-space-8)}.xl\:cu-ml-9{margin-left:var(--canon-space-9)}.xl\:cu-ml-10{margin-left:var(--canon-space-10)}.xl\:cu-ml-11{margin-left:var(--canon-space-11)}.xl\:cu-ml-12{margin-left:var(--canon-space-12)}.xl\:cu-ml-13{margin-left:var(--canon-space-13)}.xl\:cu-ml-14{margin-left:var(--canon-space-14)}}.cu-mr{margin-right:var(--mr)}.cu-mr-0\.5{margin-right:var(--canon-space-0_5)}.cu-mr-1{margin-right:var(--canon-space-1)}.cu-mr-1\.5{margin-right:var(--canon-space-1_5)}.cu-mr-2{margin-right:var(--canon-space-2)}.cu-mr-3{margin-right:var(--canon-space-3)}.cu-mr-4{margin-right:var(--canon-space-4)}.cu-mr-5{margin-right:var(--canon-space-5)}.cu-mr-6{margin-right:var(--canon-space-6)}.cu-mr-7{margin-right:var(--canon-space-7)}.cu-mr-8{margin-right:var(--canon-space-8)}.cu-mr-9{margin-right:var(--canon-space-9)}.cu-mr-10{margin-right:var(--canon-space-10)}.cu-mr-11{margin-right:var(--canon-space-11)}.cu-mr-12{margin-right:var(--canon-space-12)}.cu-mr-13{margin-right:var(--canon-space-13)}.cu-mr-14{margin-right:var(--canon-space-14)}@media (width>=640px){.xs\:cu-mr{margin-right:var(--pr-xs)}.xs\:cu-mr-0\.5{margin-right:var(--canon-space-0_5)}.xs\:cu-mr-1{margin-right:var(--canon-space-1)}.xs\:cu-mr-1\.5{margin-right:var(--canon-space-1_5)}.xs\:cu-mr-2{margin-right:var(--canon-space-2)}.xs\:cu-mr-3{margin-right:var(--canon-space-3)}.xs\:cu-mr-4{margin-right:var(--canon-space-4)}.xs\:cu-mr-5{margin-right:var(--canon-space-5)}.xs\:cu-mr-6{margin-right:var(--canon-space-6)}.xs\:cu-mr-7{margin-right:var(--canon-space-7)}.xs\:cu-mr-8{margin-right:var(--canon-space-8)}.xs\:cu-mr-9{margin-right:var(--canon-space-9)}.xs\:cu-mr-10{margin-right:var(--canon-space-10)}.xs\:cu-mr-11{margin-right:var(--canon-space-11)}.xs\:cu-mr-12{margin-right:var(--canon-space-12)}.xs\:cu-mr-13{margin-right:var(--canon-space-13)}.xs\:cu-mr-14{margin-right:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-mr{margin-right:var(--pr-sm)}.sm\:cu-mr-0\.5{margin-right:var(--canon-space-0_5)}.sm\:cu-mr-1{margin-right:var(--canon-space-1)}.sm\:cu-mr-1\.5{margin-right:var(--canon-space-1_5)}.sm\:cu-mr-2{margin-right:var(--canon-space-2)}.sm\:cu-mr-3{margin-right:var(--canon-space-3)}.sm\:cu-mr-4{margin-right:var(--canon-space-4)}.sm\:cu-mr-5{margin-right:var(--canon-space-5)}.sm\:cu-mr-6{margin-right:var(--canon-space-6)}.sm\:cu-mr-7{margin-right:var(--canon-space-7)}.sm\:cu-mr-8{margin-right:var(--canon-space-8)}.sm\:cu-mr-9{margin-right:var(--canon-space-9)}.sm\:cu-mr-10{margin-right:var(--canon-space-10)}.sm\:cu-mr-11{margin-right:var(--canon-space-11)}.sm\:cu-mr-12{margin-right:var(--canon-space-12)}.sm\:cu-mr-13{margin-right:var(--canon-space-13)}.sm\:cu-mr-14{margin-right:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-mr{margin-right:var(--pr-md)}.md\:cu-mr-0\.5{margin-right:var(--canon-space-0_5)}.md\:cu-mr-1{margin-right:var(--canon-space-1)}.md\:cu-mr-1\.5{margin-right:var(--canon-space-1_5)}.md\:cu-mr-2{margin-right:var(--canon-space-2)}.md\:cu-mr-3{margin-right:var(--canon-space-3)}.md\:cu-mr-4{margin-right:var(--canon-space-4)}.md\:cu-mr-5{margin-right:var(--canon-space-5)}.md\:cu-mr-6{margin-right:var(--canon-space-6)}.md\:cu-mr-7{margin-right:var(--canon-space-7)}.md\:cu-mr-8{margin-right:var(--canon-space-8)}.md\:cu-mr-9{margin-right:var(--canon-space-9)}.md\:cu-mr-10{margin-right:var(--canon-space-10)}.md\:cu-mr-11{margin-right:var(--canon-space-11)}.md\:cu-mr-12{margin-right:var(--canon-space-12)}.md\:cu-mr-13{margin-right:var(--canon-space-13)}.md\:cu-mr-14{margin-right:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-mr{margin-right:var(--pr-lg)}.lg\:cu-mr-0\.5{margin-right:var(--canon-space-0_5)}.lg\:cu-mr-1{margin-right:var(--canon-space-1)}.lg\:cu-mr-1\.5{margin-right:var(--canon-space-1_5)}.lg\:cu-mr-2{margin-right:var(--canon-space-2)}.lg\:cu-mr-3{margin-right:var(--canon-space-3)}.lg\:cu-mr-4{margin-right:var(--canon-space-4)}.lg\:cu-mr-5{margin-right:var(--canon-space-5)}.lg\:cu-mr-6{margin-right:var(--canon-space-6)}.lg\:cu-mr-7{margin-right:var(--canon-space-7)}.lg\:cu-mr-8{margin-right:var(--canon-space-8)}.lg\:cu-mr-9{margin-right:var(--canon-space-9)}.lg\:cu-mr-10{margin-right:var(--canon-space-10)}.lg\:cu-mr-11{margin-right:var(--canon-space-11)}.lg\:cu-mr-12{margin-right:var(--canon-space-12)}.lg\:cu-mr-13{margin-right:var(--canon-space-13)}.lg\:cu-mr-14{margin-right:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-mr{margin-right:var(--pr-xl)}.xl\:cu-mr-0\.5{margin-right:var(--canon-space-0_5)}.xl\:cu-mr-1{margin-right:var(--canon-space-1)}.xl\:cu-mr-1\.5{margin-right:var(--canon-space-1_5)}.xl\:cu-mr-2{margin-right:var(--canon-space-2)}.xl\:cu-mr-3{margin-right:var(--canon-space-3)}.xl\:cu-mr-4{margin-right:var(--canon-space-4)}.xl\:cu-mr-5{margin-right:var(--canon-space-5)}.xl\:cu-mr-6{margin-right:var(--canon-space-6)}.xl\:cu-mr-7{margin-right:var(--canon-space-7)}.xl\:cu-mr-8{margin-right:var(--canon-space-8)}.xl\:cu-mr-9{margin-right:var(--canon-space-9)}.xl\:cu-mr-10{margin-right:var(--canon-space-10)}.xl\:cu-mr-11{margin-right:var(--canon-space-11)}.xl\:cu-mr-12{margin-right:var(--canon-space-12)}.xl\:cu-mr-13{margin-right:var(--canon-space-13)}.xl\:cu-mr-14{margin-right:var(--canon-space-14)}}.cu-mt{margin-top:var(--mt)}.cu-mt-0\.5{margin-top:var(--canon-space-0_5)}.cu-mt-1{margin-top:var(--canon-space-1)}.cu-mt-1\.5{margin-top:var(--canon-space-1_5)}.cu-mt-2{margin-top:var(--canon-space-2)}.cu-mt-3{margin-top:var(--canon-space-3)}.cu-mt-4{margin-top:var(--canon-space-4)}.cu-mt-5{margin-top:var(--canon-space-5)}.cu-mt-6{margin-top:var(--canon-space-6)}.cu-mt-7{margin-top:var(--canon-space-7)}.cu-mt-8{margin-top:var(--canon-space-8)}.cu-mt-9{margin-top:var(--canon-space-9)}.cu-mt-10{margin-top:var(--canon-space-10)}.cu-mt-11{margin-top:var(--canon-space-11)}.cu-mt-12{margin-top:var(--canon-space-12)}.cu-mt-13{margin-top:var(--canon-space-13)}.cu-mt-14{margin-top:var(--canon-space-14)}@media (width>=640px){.xs\:cu-mt{margin-top:var(--pt-xs)}.xs\:cu-mt-0\.5{margin-top:var(--canon-space-0_5)}.xs\:cu-mt-1{margin-top:var(--canon-space-1)}.xs\:cu-mt-1\.5{margin-top:var(--canon-space-1_5)}.xs\:cu-mt-2{margin-top:var(--canon-space-2)}.xs\:cu-mt-3{margin-top:var(--canon-space-3)}.xs\:cu-mt-4{margin-top:var(--canon-space-4)}.xs\:cu-mt-5{margin-top:var(--canon-space-5)}.xs\:cu-mt-6{margin-top:var(--canon-space-6)}.xs\:cu-mt-7{margin-top:var(--canon-space-7)}.xs\:cu-mt-8{margin-top:var(--canon-space-8)}.xs\:cu-mt-9{margin-top:var(--canon-space-9)}.xs\:cu-mt-10{margin-top:var(--canon-space-10)}.xs\:cu-mt-11{margin-top:var(--canon-space-11)}.xs\:cu-mt-12{margin-top:var(--canon-space-12)}.xs\:cu-mt-13{margin-top:var(--canon-space-13)}.xs\:cu-mt-14{margin-top:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-mt{margin-top:var(--pt-sm)}.sm\:cu-mt-0\.5{margin-top:var(--canon-space-0_5)}.sm\:cu-mt-1{margin-top:var(--canon-space-1)}.sm\:cu-mt-1\.5{margin-top:var(--canon-space-1_5)}.sm\:cu-mt-2{margin-top:var(--canon-space-2)}.sm\:cu-mt-3{margin-top:var(--canon-space-3)}.sm\:cu-mt-4{margin-top:var(--canon-space-4)}.sm\:cu-mt-5{margin-top:var(--canon-space-5)}.sm\:cu-mt-6{margin-top:var(--canon-space-6)}.sm\:cu-mt-7{margin-top:var(--canon-space-7)}.sm\:cu-mt-8{margin-top:var(--canon-space-8)}.sm\:cu-mt-9{margin-top:var(--canon-space-9)}.sm\:cu-mt-10{margin-top:var(--canon-space-10)}.sm\:cu-mt-11{margin-top:var(--canon-space-11)}.sm\:cu-mt-12{margin-top:var(--canon-space-12)}.sm\:cu-mt-13{margin-top:var(--canon-space-13)}.sm\:cu-mt-14{margin-top:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-mt{margin-top:var(--pt-md)}.md\:cu-mt-0\.5{margin-top:var(--canon-space-0_5)}.md\:cu-mt-1{margin-top:var(--canon-space-1)}.md\:cu-mt-1\.5{margin-top:var(--canon-space-1_5)}.md\:cu-mt-2{margin-top:var(--canon-space-2)}.md\:cu-mt-3{margin-top:var(--canon-space-3)}.md\:cu-mt-4{margin-top:var(--canon-space-4)}.md\:cu-mt-5{margin-top:var(--canon-space-5)}.md\:cu-mt-6{margin-top:var(--canon-space-6)}.md\:cu-mt-7{margin-top:var(--canon-space-7)}.md\:cu-mt-8{margin-top:var(--canon-space-8)}.md\:cu-mt-9{margin-top:var(--canon-space-9)}.md\:cu-mt-10{margin-top:var(--canon-space-10)}.md\:cu-mt-11{margin-top:var(--canon-space-11)}.md\:cu-mt-12{margin-top:var(--canon-space-12)}.md\:cu-mt-13{margin-top:var(--canon-space-13)}.md\:cu-mt-14{margin-top:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-mt{margin-top:var(--pt-lg)}.lg\:cu-mt-0\.5{margin-top:var(--canon-space-0_5)}.lg\:cu-mt-1{margin-top:var(--canon-space-1)}.lg\:cu-mt-1\.5{margin-top:var(--canon-space-1_5)}.lg\:cu-mt-2{margin-top:var(--canon-space-2)}.lg\:cu-mt-3{margin-top:var(--canon-space-3)}.lg\:cu-mt-4{margin-top:var(--canon-space-4)}.lg\:cu-mt-5{margin-top:var(--canon-space-5)}.lg\:cu-mt-6{margin-top:var(--canon-space-6)}.lg\:cu-mt-7{margin-top:var(--canon-space-7)}.lg\:cu-mt-8{margin-top:var(--canon-space-8)}.lg\:cu-mt-9{margin-top:var(--canon-space-9)}.lg\:cu-mt-10{margin-top:var(--canon-space-10)}.lg\:cu-mt-11{margin-top:var(--canon-space-11)}.lg\:cu-mt-12{margin-top:var(--canon-space-12)}.lg\:cu-mt-13{margin-top:var(--canon-space-13)}.lg\:cu-mt-14{margin-top:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-mt{margin-top:var(--pt-xl)}.xl\:cu-mt-0\.5{margin-top:var(--canon-space-0_5)}.xl\:cu-mt-1{margin-top:var(--canon-space-1)}.xl\:cu-mt-1\.5{margin-top:var(--canon-space-1_5)}.xl\:cu-mt-2{margin-top:var(--canon-space-2)}.xl\:cu-mt-3{margin-top:var(--canon-space-3)}.xl\:cu-mt-4{margin-top:var(--canon-space-4)}.xl\:cu-mt-5{margin-top:var(--canon-space-5)}.xl\:cu-mt-6{margin-top:var(--canon-space-6)}.xl\:cu-mt-7{margin-top:var(--canon-space-7)}.xl\:cu-mt-8{margin-top:var(--canon-space-8)}.xl\:cu-mt-9{margin-top:var(--canon-space-9)}.xl\:cu-mt-10{margin-top:var(--canon-space-10)}.xl\:cu-mt-11{margin-top:var(--canon-space-11)}.xl\:cu-mt-12{margin-top:var(--canon-space-12)}.xl\:cu-mt-13{margin-top:var(--canon-space-13)}.xl\:cu-mt-14{margin-top:var(--canon-space-14)}}.cu-mb{margin-bottom:var(--mb)}.cu-mb-0\.5{margin-bottom:var(--canon-space-0_5)}.cu-mb-1{margin-bottom:var(--canon-space-1)}.cu-mb-1\.5{margin-bottom:var(--canon-space-1_5)}.cu-mb-2{margin-bottom:var(--canon-space-2)}.cu-mb-3{margin-bottom:var(--canon-space-3)}.cu-mb-4{margin-bottom:var(--canon-space-4)}.cu-mb-5{margin-bottom:var(--canon-space-5)}.cu-mb-6{margin-bottom:var(--canon-space-6)}.cu-mb-7{margin-bottom:var(--canon-space-7)}.cu-mb-8{margin-bottom:var(--canon-space-8)}.cu-mb-9{margin-bottom:var(--canon-space-9)}.cu-mb-10{margin-bottom:var(--canon-space-10)}.cu-mb-11{margin-bottom:var(--canon-space-11)}.cu-mb-12{margin-bottom:var(--canon-space-12)}.cu-mb-13{margin-bottom:var(--canon-space-13)}.cu-mb-14{margin-bottom:var(--canon-space-14)}@media (width>=640px){.xs\:cu-mb{margin-bottom:var(--pb-xs)}.xs\:cu-mb-0\.5{margin-bottom:var(--canon-space-0_5)}.xs\:cu-mb-1{margin-bottom:var(--canon-space-1)}.xs\:cu-mb-1\.5{margin-bottom:var(--canon-space-1_5)}.xs\:cu-mb-2{margin-bottom:var(--canon-space-2)}.xs\:cu-mb-3{margin-bottom:var(--canon-space-3)}.xs\:cu-mb-4{margin-bottom:var(--canon-space-4)}.xs\:cu-mb-5{margin-bottom:var(--canon-space-5)}.xs\:cu-mb-6{margin-bottom:var(--canon-space-6)}.xs\:cu-mb-7{margin-bottom:var(--canon-space-7)}.xs\:cu-mb-8{margin-bottom:var(--canon-space-8)}.xs\:cu-mb-9{margin-bottom:var(--canon-space-9)}.xs\:cu-mb-10{margin-bottom:var(--canon-space-10)}.xs\:cu-mb-11{margin-bottom:var(--canon-space-11)}.xs\:cu-mb-12{margin-bottom:var(--canon-space-12)}.xs\:cu-mb-13{margin-bottom:var(--canon-space-13)}.xs\:cu-mb-14{margin-bottom:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-mb{margin-bottom:var(--pb-sm)}.sm\:cu-mb-0\.5{margin-bottom:var(--canon-space-0_5)}.sm\:cu-mb-1{margin-bottom:var(--canon-space-1)}.sm\:cu-mb-1\.5{margin-bottom:var(--canon-space-1_5)}.sm\:cu-mb-2{margin-bottom:var(--canon-space-2)}.sm\:cu-mb-3{margin-bottom:var(--canon-space-3)}.sm\:cu-mb-4{margin-bottom:var(--canon-space-4)}.sm\:cu-mb-5{margin-bottom:var(--canon-space-5)}.sm\:cu-mb-6{margin-bottom:var(--canon-space-6)}.sm\:cu-mb-7{margin-bottom:var(--canon-space-7)}.sm\:cu-mb-8{margin-bottom:var(--canon-space-8)}.sm\:cu-mb-9{margin-bottom:var(--canon-space-9)}.sm\:cu-mb-10{margin-bottom:var(--canon-space-10)}.sm\:cu-mb-11{margin-bottom:var(--canon-space-11)}.sm\:cu-mb-12{margin-bottom:var(--canon-space-12)}.sm\:cu-mb-13{margin-bottom:var(--canon-space-13)}.sm\:cu-mb-14{margin-bottom:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-mb{margin-bottom:var(--pb-md)}.md\:cu-mb-0\.5{margin-bottom:var(--canon-space-0_5)}.md\:cu-mb-1{margin-bottom:var(--canon-space-1)}.md\:cu-mb-1\.5{margin-bottom:var(--canon-space-1_5)}.md\:cu-mb-2{margin-bottom:var(--canon-space-2)}.md\:cu-mb-3{margin-bottom:var(--canon-space-3)}.md\:cu-mb-4{margin-bottom:var(--canon-space-4)}.md\:cu-mb-5{margin-bottom:var(--canon-space-5)}.md\:cu-mb-6{margin-bottom:var(--canon-space-6)}.md\:cu-mb-7{margin-bottom:var(--canon-space-7)}.md\:cu-mb-8{margin-bottom:var(--canon-space-8)}.md\:cu-mb-9{margin-bottom:var(--canon-space-9)}.md\:cu-mb-10{margin-bottom:var(--canon-space-10)}.md\:cu-mb-11{margin-bottom:var(--canon-space-11)}.md\:cu-mb-12{margin-bottom:var(--canon-space-12)}.md\:cu-mb-13{margin-bottom:var(--canon-space-13)}.md\:cu-mb-14{margin-bottom:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-mb{margin-bottom:var(--pb-lg)}.lg\:cu-mb-0\.5{margin-bottom:var(--canon-space-0_5)}.lg\:cu-mb-1{margin-bottom:var(--canon-space-1)}.lg\:cu-mb-1\.5{margin-bottom:var(--canon-space-1_5)}.lg\:cu-mb-2{margin-bottom:var(--canon-space-2)}.lg\:cu-mb-3{margin-bottom:var(--canon-space-3)}.lg\:cu-mb-4{margin-bottom:var(--canon-space-4)}.lg\:cu-mb-5{margin-bottom:var(--canon-space-5)}.lg\:cu-mb-6{margin-bottom:var(--canon-space-6)}.lg\:cu-mb-7{margin-bottom:var(--canon-space-7)}.lg\:cu-mb-8{margin-bottom:var(--canon-space-8)}.lg\:cu-mb-9{margin-bottom:var(--canon-space-9)}.lg\:cu-mb-10{margin-bottom:var(--canon-space-10)}.lg\:cu-mb-11{margin-bottom:var(--canon-space-11)}.lg\:cu-mb-12{margin-bottom:var(--canon-space-12)}.lg\:cu-mb-13{margin-bottom:var(--canon-space-13)}.lg\:cu-mb-14{margin-bottom:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-mb{margin-bottom:var(--pb-xl)}.xl\:cu-mb-0\.5{margin-bottom:var(--canon-space-0_5)}.xl\:cu-mb-1{margin-bottom:var(--canon-space-1)}.xl\:cu-mb-1\.5{margin-bottom:var(--canon-space-1_5)}.xl\:cu-mb-2{margin-bottom:var(--canon-space-2)}.xl\:cu-mb-3{margin-bottom:var(--canon-space-3)}.xl\:cu-mb-4{margin-bottom:var(--canon-space-4)}.xl\:cu-mb-5{margin-bottom:var(--canon-space-5)}.xl\:cu-mb-6{margin-bottom:var(--canon-space-6)}.xl\:cu-mb-7{margin-bottom:var(--canon-space-7)}.xl\:cu-mb-8{margin-bottom:var(--canon-space-8)}.xl\:cu-mb-9{margin-bottom:var(--canon-space-9)}.xl\:cu-mb-10{margin-bottom:var(--canon-space-10)}.xl\:cu-mb-11{margin-bottom:var(--canon-space-11)}.xl\:cu-mb-12{margin-bottom:var(--canon-space-12)}.xl\:cu-mb-13{margin-bottom:var(--canon-space-13)}.xl\:cu-mb-14{margin-bottom:var(--canon-space-14)}}.cu-my{margin-top:var(--my);margin-bottom:var(--my)}.cu-my-0\.5{margin-top:var(--canon-space-0_5);margin-bottom:var(--canon-space-0_5)}.cu-my-1{margin-top:var(--canon-space-1);margin-bottom:var(--canon-space-1)}.cu-my-1\.5{margin-top:var(--canon-space-1_5);margin-bottom:var(--canon-space-1_5)}.cu-my-2{margin-top:var(--canon-space-2);margin-bottom:var(--canon-space-2)}.cu-my-3{margin-top:var(--canon-space-3);margin-bottom:var(--canon-space-3)}.cu-my-4{margin-top:var(--canon-space-4);margin-bottom:var(--canon-space-4)}.cu-my-5{margin-top:var(--canon-space-5);margin-bottom:var(--canon-space-5)}.cu-my-6{margin-top:var(--canon-space-6);margin-bottom:var(--canon-space-6)}.cu-my-7{margin-top:var(--canon-space-7);margin-bottom:var(--canon-space-7)}.cu-my-8{margin-top:var(--canon-space-8);margin-bottom:var(--canon-space-8)}.cu-my-9{margin-top:var(--canon-space-9);margin-bottom:var(--canon-space-9)}.cu-my-10{margin-top:var(--canon-space-10);margin-bottom:var(--canon-space-10)}.cu-my-11{margin-top:var(--canon-space-11);margin-bottom:var(--canon-space-11)}.cu-my-12{margin-top:var(--canon-space-12);margin-bottom:var(--canon-space-12)}.cu-my-13{margin-top:var(--canon-space-13);margin-bottom:var(--canon-space-13)}.cu-my-14{margin-top:var(--canon-space-14);margin-bottom:var(--canon-space-14)}@media (width>=640px){.xs\:cu-my{margin-top:var(--py-xs);margin-bottom:var(--py-xs)}.xs\:cu-my-0\.5{margin-top:var(--canon-space-0_5);margin-bottom:var(--canon-space-0_5)}.xs\:cu-my-1{margin-top:var(--canon-space-1);margin-bottom:var(--canon-space-1)}.xs\:cu-my-1\.5{margin-top:var(--canon-space-1_5);margin-bottom:var(--canon-space-1_5)}.xs\:cu-my-2{margin-top:var(--canon-space-2);margin-bottom:var(--canon-space-2)}.xs\:cu-my-3{margin-top:var(--canon-space-3);margin-bottom:var(--canon-space-3)}.xs\:cu-my-4{margin-top:var(--canon-space-4);margin-bottom:var(--canon-space-4)}.xs\:cu-my-5{margin-top:var(--canon-space-5);margin-bottom:var(--canon-space-5)}.xs\:cu-my-6{margin-top:var(--canon-space-6);margin-bottom:var(--canon-space-6)}.xs\:cu-my-7{margin-top:var(--canon-space-7);margin-bottom:var(--canon-space-7)}.xs\:cu-my-8{margin-top:var(--canon-space-8);margin-bottom:var(--canon-space-8)}.xs\:cu-my-9{margin-top:var(--canon-space-9);margin-bottom:var(--canon-space-9)}.xs\:cu-my-10{margin-top:var(--canon-space-10);margin-bottom:var(--canon-space-10)}.xs\:cu-my-11{margin-top:var(--canon-space-11);margin-bottom:var(--canon-space-11)}.xs\:cu-my-12{margin-top:var(--canon-space-12);margin-bottom:var(--canon-space-12)}.xs\:cu-my-13{margin-top:var(--canon-space-13);margin-bottom:var(--canon-space-13)}.xs\:cu-my-14{margin-top:var(--canon-space-14);margin-bottom:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-my{margin-top:var(--py-sm);margin-bottom:var(--py-sm)}.sm\:cu-my-0\.5{margin-top:var(--canon-space-0_5);margin-bottom:var(--canon-space-0_5)}.sm\:cu-my-1{margin-top:var(--canon-space-1);margin-bottom:var(--canon-space-1)}.sm\:cu-my-1\.5{margin-top:var(--canon-space-1_5);margin-bottom:var(--canon-space-1_5)}.sm\:cu-my-2{margin-top:var(--canon-space-2);margin-bottom:var(--canon-space-2)}.sm\:cu-my-3{margin-top:var(--canon-space-3);margin-bottom:var(--canon-space-3)}.sm\:cu-my-4{margin-top:var(--canon-space-4);margin-bottom:var(--canon-space-4)}.sm\:cu-my-5{margin-top:var(--canon-space-5);margin-bottom:var(--canon-space-5)}.sm\:cu-my-6{margin-top:var(--canon-space-6);margin-bottom:var(--canon-space-6)}.sm\:cu-my-7{margin-top:var(--canon-space-7);margin-bottom:var(--canon-space-7)}.sm\:cu-my-8{margin-top:var(--canon-space-8);margin-bottom:var(--canon-space-8)}.sm\:cu-my-9{margin-top:var(--canon-space-9);margin-bottom:var(--canon-space-9)}.sm\:cu-my-10{margin-top:var(--canon-space-10);margin-bottom:var(--canon-space-10)}.sm\:cu-my-11{margin-top:var(--canon-space-11);margin-bottom:var(--canon-space-11)}.sm\:cu-my-12{margin-top:var(--canon-space-12);margin-bottom:var(--canon-space-12)}.sm\:cu-my-13{margin-top:var(--canon-space-13);margin-bottom:var(--canon-space-13)}.sm\:cu-my-14{margin-top:var(--canon-space-14);margin-bottom:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-my{margin-top:var(--py-md);margin-bottom:var(--py-md)}.md\:cu-my-0\.5{margin-top:var(--canon-space-0_5);margin-bottom:var(--canon-space-0_5)}.md\:cu-my-1{margin-top:var(--canon-space-1);margin-bottom:var(--canon-space-1)}.md\:cu-my-1\.5{margin-top:var(--canon-space-1_5);margin-bottom:var(--canon-space-1_5)}.md\:cu-my-2{margin-top:var(--canon-space-2);margin-bottom:var(--canon-space-2)}.md\:cu-my-3{margin-top:var(--canon-space-3);margin-bottom:var(--canon-space-3)}.md\:cu-my-4{margin-top:var(--canon-space-4);margin-bottom:var(--canon-space-4)}.md\:cu-my-5{margin-top:var(--canon-space-5);margin-bottom:var(--canon-space-5)}.md\:cu-my-6{margin-top:var(--canon-space-6);margin-bottom:var(--canon-space-6)}.md\:cu-my-7{margin-top:var(--canon-space-7);margin-bottom:var(--canon-space-7)}.md\:cu-my-8{margin-top:var(--canon-space-8);margin-bottom:var(--canon-space-8)}.md\:cu-my-9{margin-top:var(--canon-space-9);margin-bottom:var(--canon-space-9)}.md\:cu-my-10{margin-top:var(--canon-space-10);margin-bottom:var(--canon-space-10)}.md\:cu-my-11{margin-top:var(--canon-space-11);margin-bottom:var(--canon-space-11)}.md\:cu-my-12{margin-top:var(--canon-space-12);margin-bottom:var(--canon-space-12)}.md\:cu-my-13{margin-top:var(--canon-space-13);margin-bottom:var(--canon-space-13)}.md\:cu-my-14{margin-top:var(--canon-space-14);margin-bottom:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-my{margin-top:var(--py-lg);margin-bottom:var(--py-lg)}.lg\:cu-my-0\.5{margin-top:var(--canon-space-0_5);margin-bottom:var(--canon-space-0_5)}.lg\:cu-my-1{margin-top:var(--canon-space-1);margin-bottom:var(--canon-space-1)}.lg\:cu-my-1\.5{margin-top:var(--canon-space-1_5);margin-bottom:var(--canon-space-1_5)}.lg\:cu-my-2{margin-top:var(--canon-space-2);margin-bottom:var(--canon-space-2)}.lg\:cu-my-3{margin-top:var(--canon-space-3);margin-bottom:var(--canon-space-3)}.lg\:cu-my-4{margin-top:var(--canon-space-4);margin-bottom:var(--canon-space-4)}.lg\:cu-my-5{margin-top:var(--canon-space-5);margin-bottom:var(--canon-space-5)}.lg\:cu-my-6{margin-top:var(--canon-space-6);margin-bottom:var(--canon-space-6)}.lg\:cu-my-7{margin-top:var(--canon-space-7);margin-bottom:var(--canon-space-7)}.lg\:cu-my-8{margin-top:var(--canon-space-8);margin-bottom:var(--canon-space-8)}.lg\:cu-my-9{margin-top:var(--canon-space-9);margin-bottom:var(--canon-space-9)}.lg\:cu-my-10{margin-top:var(--canon-space-10);margin-bottom:var(--canon-space-10)}.lg\:cu-my-11{margin-top:var(--canon-space-11);margin-bottom:var(--canon-space-11)}.lg\:cu-my-12{margin-top:var(--canon-space-12);margin-bottom:var(--canon-space-12)}.lg\:cu-my-13{margin-top:var(--canon-space-13);margin-bottom:var(--canon-space-13)}.lg\:cu-my-14{margin-top:var(--canon-space-14);margin-bottom:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-my{margin-top:var(--py-xl);margin-bottom:var(--py-xl)}.xl\:cu-my-0\.5{margin-top:var(--canon-space-0_5);margin-bottom:var(--canon-space-0_5)}.xl\:cu-my-1{margin-top:var(--canon-space-1);margin-bottom:var(--canon-space-1)}.xl\:cu-my-1\.5{margin-top:var(--canon-space-1_5);margin-bottom:var(--canon-space-1_5)}.xl\:cu-my-2{margin-top:var(--canon-space-2);margin-bottom:var(--canon-space-2)}.xl\:cu-my-3{margin-top:var(--canon-space-3);margin-bottom:var(--canon-space-3)}.xl\:cu-my-4{margin-top:var(--canon-space-4);margin-bottom:var(--canon-space-4)}.xl\:cu-my-5{margin-top:var(--canon-space-5);margin-bottom:var(--canon-space-5)}.xl\:cu-my-6{margin-top:var(--canon-space-6);margin-bottom:var(--canon-space-6)}.xl\:cu-my-7{margin-top:var(--canon-space-7);margin-bottom:var(--canon-space-7)}.xl\:cu-my-8{margin-top:var(--canon-space-8);margin-bottom:var(--canon-space-8)}.xl\:cu-my-9{margin-top:var(--canon-space-9);margin-bottom:var(--canon-space-9)}.xl\:cu-my-10{margin-top:var(--canon-space-10);margin-bottom:var(--canon-space-10)}.xl\:cu-my-11{margin-top:var(--canon-space-11);margin-bottom:var(--canon-space-11)}.xl\:cu-my-12{margin-top:var(--canon-space-12);margin-bottom:var(--canon-space-12)}.xl\:cu-my-13{margin-top:var(--canon-space-13);margin-bottom:var(--canon-space-13)}.xl\:cu-my-14{margin-top:var(--canon-space-14);margin-bottom:var(--canon-space-14)}}.cu-mx{margin-left:var(--mx);margin-right:var(--mx)}.cu-mx-0\.5{margin-left:var(--canon-space-0_5);margin-right:var(--canon-space-0_5)}.cu-mx-1{margin-left:var(--canon-space-1);margin-right:var(--canon-space-1)}.cu-mx-1\.5{margin-left:var(--canon-space-1_5);margin-right:var(--canon-space-1_5)}.cu-mx-2{margin-left:var(--canon-space-2);margin-right:var(--canon-space-2)}.cu-mx-3{margin-left:var(--canon-space-3);margin-right:var(--canon-space-3)}.cu-mx-4{margin-left:var(--canon-space-4);margin-right:var(--canon-space-4)}.cu-mx-5{margin-left:var(--canon-space-5);margin-right:var(--canon-space-5)}.cu-mx-6{margin-left:var(--canon-space-6);margin-right:var(--canon-space-6)}.cu-mx-7{margin-left:var(--canon-space-7);margin-right:var(--canon-space-7)}.cu-mx-8{margin-left:var(--canon-space-8);margin-right:var(--canon-space-8)}.cu-mx-9{margin-left:var(--canon-space-9);margin-right:var(--canon-space-9)}.cu-mx-10{margin-left:var(--canon-space-10);margin-right:var(--canon-space-10)}.cu-mx-11{margin-left:var(--canon-space-11);margin-right:var(--canon-space-11)}.cu-mx-12{margin-left:var(--canon-space-12);margin-right:var(--canon-space-12)}.cu-mx-13{margin-left:var(--canon-space-13);margin-right:var(--canon-space-13)}.cu-mx-14{margin-left:var(--canon-space-14);margin-right:var(--canon-space-14)}@media (width>=640px){.xs\:cu-mx{margin-left:var(--px-xs);margin-right:var(--px-xs)}.xs\:cu-mx-0\.5{margin-left:var(--canon-space-0_5);margin-right:var(--canon-space-0_5)}.xs\:cu-mx-1{margin-left:var(--canon-space-1);margin-right:var(--canon-space-1)}.xs\:cu-mx-1\.5{margin-left:var(--canon-space-1_5);margin-right:var(--canon-space-1_5)}.xs\:cu-mx-2{margin-left:var(--canon-space-2);margin-right:var(--canon-space-2)}.xs\:cu-mx-3{margin-left:var(--canon-space-3);margin-right:var(--canon-space-3)}.xs\:cu-mx-4{margin-left:var(--canon-space-4);margin-right:var(--canon-space-4)}.xs\:cu-mx-5{margin-left:var(--canon-space-5);margin-right:var(--canon-space-5)}.xs\:cu-mx-6{margin-left:var(--canon-space-6);margin-right:var(--canon-space-6)}.xs\:cu-mx-7{margin-left:var(--canon-space-7);margin-right:var(--canon-space-7)}.xs\:cu-mx-8{margin-left:var(--canon-space-8);margin-right:var(--canon-space-8)}.xs\:cu-mx-9{margin-left:var(--canon-space-9);margin-right:var(--canon-space-9)}.xs\:cu-mx-10{margin-left:var(--canon-space-10);margin-right:var(--canon-space-10)}.xs\:cu-mx-11{margin-left:var(--canon-space-11);margin-right:var(--canon-space-11)}.xs\:cu-mx-12{margin-left:var(--canon-space-12);margin-right:var(--canon-space-12)}.xs\:cu-mx-13{margin-left:var(--canon-space-13);margin-right:var(--canon-space-13)}.xs\:cu-mx-14{margin-left:var(--canon-space-14);margin-right:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-mx{margin-left:var(--px-sm);margin-right:var(--px-sm)}.sm\:cu-mx-0\.5{margin-left:var(--canon-space-0_5);margin-right:var(--canon-space-0_5)}.sm\:cu-mx-1{margin-left:var(--canon-space-1);margin-right:var(--canon-space-1)}.sm\:cu-mx-1\.5{margin-left:var(--canon-space-1_5);margin-right:var(--canon-space-1_5)}.sm\:cu-mx-2{margin-left:var(--canon-space-2);margin-right:var(--canon-space-2)}.sm\:cu-mx-3{margin-left:var(--canon-space-3);margin-right:var(--canon-space-3)}.sm\:cu-mx-4{margin-left:var(--canon-space-4);margin-right:var(--canon-space-4)}.sm\:cu-mx-5{margin-left:var(--canon-space-5);margin-right:var(--canon-space-5)}.sm\:cu-mx-6{margin-left:var(--canon-space-6);margin-right:var(--canon-space-6)}.sm\:cu-mx-7{margin-left:var(--canon-space-7);margin-right:var(--canon-space-7)}.sm\:cu-mx-8{margin-left:var(--canon-space-8);margin-right:var(--canon-space-8)}.sm\:cu-mx-9{margin-left:var(--canon-space-9);margin-right:var(--canon-space-9)}.sm\:cu-mx-10{margin-left:var(--canon-space-10);margin-right:var(--canon-space-10)}.sm\:cu-mx-11{margin-left:var(--canon-space-11);margin-right:var(--canon-space-11)}.sm\:cu-mx-12{margin-left:var(--canon-space-12);margin-right:var(--canon-space-12)}.sm\:cu-mx-13{margin-left:var(--canon-space-13);margin-right:var(--canon-space-13)}.sm\:cu-mx-14{margin-left:var(--canon-space-14);margin-right:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-mx{margin-left:var(--px-md);margin-right:var(--px-md)}.md\:cu-mx-0\.5{margin-left:var(--canon-space-0_5);margin-right:var(--canon-space-0_5)}.md\:cu-mx-1{margin-left:var(--canon-space-1);margin-right:var(--canon-space-1)}.md\:cu-mx-1\.5{margin-left:var(--canon-space-1_5);margin-right:var(--canon-space-1_5)}.md\:cu-mx-2{margin-left:var(--canon-space-2);margin-right:var(--canon-space-2)}.md\:cu-mx-3{margin-left:var(--canon-space-3);margin-right:var(--canon-space-3)}.md\:cu-mx-4{margin-left:var(--canon-space-4);margin-right:var(--canon-space-4)}.md\:cu-mx-5{margin-left:var(--canon-space-5);margin-right:var(--canon-space-5)}.md\:cu-mx-6{margin-left:var(--canon-space-6);margin-right:var(--canon-space-6)}.md\:cu-mx-7{margin-left:var(--canon-space-7);margin-right:var(--canon-space-7)}.md\:cu-mx-8{margin-left:var(--canon-space-8);margin-right:var(--canon-space-8)}.md\:cu-mx-9{margin-left:var(--canon-space-9);margin-right:var(--canon-space-9)}.md\:cu-mx-10{margin-left:var(--canon-space-10);margin-right:var(--canon-space-10)}.md\:cu-mx-11{margin-left:var(--canon-space-11);margin-right:var(--canon-space-11)}.md\:cu-mx-12{margin-left:var(--canon-space-12);margin-right:var(--canon-space-12)}.md\:cu-mx-13{margin-left:var(--canon-space-13);margin-right:var(--canon-space-13)}.md\:cu-mx-14{margin-left:var(--canon-space-14);margin-right:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-mx{margin-left:var(--px-lg);margin-right:var(--px-lg)}.lg\:cu-mx-0\.5{margin-left:var(--canon-space-0_5);margin-right:var(--canon-space-0_5)}.lg\:cu-mx-1{margin-left:var(--canon-space-1);margin-right:var(--canon-space-1)}.lg\:cu-mx-1\.5{margin-left:var(--canon-space-1_5);margin-right:var(--canon-space-1_5)}.lg\:cu-mx-2{margin-left:var(--canon-space-2);margin-right:var(--canon-space-2)}.lg\:cu-mx-3{margin-left:var(--canon-space-3);margin-right:var(--canon-space-3)}.lg\:cu-mx-4{margin-left:var(--canon-space-4);margin-right:var(--canon-space-4)}.lg\:cu-mx-5{margin-left:var(--canon-space-5);margin-right:var(--canon-space-5)}.lg\:cu-mx-6{margin-left:var(--canon-space-6);margin-right:var(--canon-space-6)}.lg\:cu-mx-7{margin-left:var(--canon-space-7);margin-right:var(--canon-space-7)}.lg\:cu-mx-8{margin-left:var(--canon-space-8);margin-right:var(--canon-space-8)}.lg\:cu-mx-9{margin-left:var(--canon-space-9);margin-right:var(--canon-space-9)}.lg\:cu-mx-10{margin-left:var(--canon-space-10);margin-right:var(--canon-space-10)}.lg\:cu-mx-11{margin-left:var(--canon-space-11);margin-right:var(--canon-space-11)}.lg\:cu-mx-12{margin-left:var(--canon-space-12);margin-right:var(--canon-space-12)}.lg\:cu-mx-13{margin-left:var(--canon-space-13);margin-right:var(--canon-space-13)}.lg\:cu-mx-14{margin-left:var(--canon-space-14);margin-right:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-mx{margin-left:var(--px-xl);margin-right:var(--px-xl)}.xl\:cu-mx-0\.5{margin-left:var(--canon-space-0_5);margin-right:var(--canon-space-0_5)}.xl\:cu-mx-1{margin-left:var(--canon-space-1);margin-right:var(--canon-space-1)}.xl\:cu-mx-1\.5{margin-left:var(--canon-space-1_5);margin-right:var(--canon-space-1_5)}.xl\:cu-mx-2{margin-left:var(--canon-space-2);margin-right:var(--canon-space-2)}.xl\:cu-mx-3{margin-left:var(--canon-space-3);margin-right:var(--canon-space-3)}.xl\:cu-mx-4{margin-left:var(--canon-space-4);margin-right:var(--canon-space-4)}.xl\:cu-mx-5{margin-left:var(--canon-space-5);margin-right:var(--canon-space-5)}.xl\:cu-mx-6{margin-left:var(--canon-space-6);margin-right:var(--canon-space-6)}.xl\:cu-mx-7{margin-left:var(--canon-space-7);margin-right:var(--canon-space-7)}.xl\:cu-mx-8{margin-left:var(--canon-space-8);margin-right:var(--canon-space-8)}.xl\:cu-mx-9{margin-left:var(--canon-space-9);margin-right:var(--canon-space-9)}.xl\:cu-mx-10{margin-left:var(--canon-space-10);margin-right:var(--canon-space-10)}.xl\:cu-mx-11{margin-left:var(--canon-space-11);margin-right:var(--canon-space-11)}.xl\:cu-mx-12{margin-left:var(--canon-space-12);margin-right:var(--canon-space-12)}.xl\:cu-mx-13{margin-left:var(--canon-space-13);margin-right:var(--canon-space-13)}.xl\:cu-mx-14{margin-left:var(--canon-space-14);margin-right:var(--canon-space-14)}}.cu-display-none{display:none}.cu-display-inline{display:inline}.cu-display-inline-block{display:inline-block}.cu-display-block{display:block}@media (width>=640px){.xs\:cu-display-none{display:none}.xs\:cu-display-inline{display:inline}.xs\:cu-display-inline-block{display:inline-block}.xs\:cu-display-block{display:block}}@media (width>=768px){.sm\:cu-display-none{display:none}.sm\:cu-display-inline{display:inline}.sm\:cu-display-inline-block{display:inline-block}.sm\:cu-display-block{display:block}}@media (width>=1024px){.md\:cu-display-none{display:none}.md\:cu-display-inline{display:inline}.md\:cu-display-inline-block{display:inline-block}.md\:cu-display-block{display:block}}@media (width>=1280px){.lg\:cu-display-none{display:none}.lg\:cu-display-inline{display:inline}.lg\:cu-display-inline-block{display:inline-block}.lg\:cu-display-block{display:block}}@media (width>=1536px){.xl\:cu-display-none{display:none}.xl\:cu-display-inline{display:inline}.xl\:cu-display-inline-block{display:inline-block}.xl\:cu-display-block{display:block}}.cu-w{width:var(--width)}.cu-min-w{min-width:var(--min-width)}.cu-max-w{max-width:var(--max-width)}@media (width>=640px){.xs\:cu-w{width:var(--width)}.xs\:cu-min-w{min-width:var(--min-width)}.xs\:cu-max-w{max-width:var(--max-width)}}@media (width>=768px){.sm\:cu-w{width:var(--width)}.sm\:cu-min-w{min-width:var(--min-width)}.sm\:cu-max-w{max-width:var(--max-width)}}@media (width>=1024px){.md\:cu-w{width:var(--width)}.md\:cu-min-w{min-width:var(--min-width)}.md\:cu-max-w{max-width:var(--max-width)}}@media (width>=1280px){.lg\:cu-w{width:var(--width)}.lg\:cu-min-w{min-width:var(--min-width)}.lg\:cu-max-w{max-width:var(--max-width)}}@media (width>=1536px){.xl\:cu-w{width:var(--width)}.xl\:cu-min-w{min-width:var(--min-width)}.xl\:cu-max-w{max-width:var(--max-width)}}.cu-h{height:var(--height)}.cu-min-h{min-height:var(--min-height)}.cu-max-h{max-height:var(--max-height)}@media (width>=640px){.xs\:cu-h{height:var(--height)}.xs\:cu-min-h{min-height:var(--min-height)}.xs\:cu-max-h{max-height:var(--max-height)}}@media (width>=768px){.sm\:cu-h{height:var(--height)}.sm\:cu-min-h{min-height:var(--min-height)}.sm\:cu-max-h{max-height:var(--max-height)}}@media (width>=1024px){.md\:cu-h{height:var(--height)}.md\:cu-min-h{min-height:var(--min-height)}.md\:cu-max-h{max-height:var(--max-height)}}@media (width>=1280px){.lg\:cu-h{height:var(--height)}.lg\:cu-min-h{min-height:var(--min-height)}.lg\:cu-max-h{max-height:var(--max-height)}}@media (width>=1536px){.xl\:cu-h{height:var(--height)}.xl\:cu-min-h{min-height:var(--min-height)}.xl\:cu-max-h{max-height:var(--max-height)}}.cu-position-absolute{position:absolute}.cu-position-fixed{position:fixed}.cu-position-sticky{position:sticky}.cu-position-relative{position:relative}.cu-position-static{position:static}@media (width>=640px){.xs\:cu-position-absolute{position:absolute}.xs\:cu-position-fixed{position:fixed}.xs\:cu-position-sticky{position:sticky}.xs\:cu-position-relative{position:relative}.xs\:cu-position-static{position:static}}@media (width>=768px){.sm\:cu-position-absolute{position:absolute}.sm\:cu-position-fixed{position:fixed}.sm\:cu-position-sticky{position:sticky}.sm\:cu-position-relative{position:relative}.sm\:cu-position-static{position:static}}@media (width>=1024px){.md\:cu-position-absolute{position:absolute}.md\:cu-position-fixed{position:fixed}.md\:cu-position-sticky{position:sticky}.md\:cu-position-relative{position:relative}.md\:cu-position-static{position:static}}@media (width>=1280px){.lg\:cu-position-absolute{position:absolute}.lg\:cu-position-fixed{position:fixed}.lg\:cu-position-sticky{position:sticky}.lg\:cu-position-relative{position:relative}.lg\:cu-position-static{position:static}}@media (width>=1536px){.xl\:cu-position-absolute{position:absolute}.xl\:cu-position-fixed{position:fixed}.xl\:cu-position-sticky{position:sticky}.xl\:cu-position-relative{position:relative}.xl\:cu-position-static{position:static}}.cu-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.cu-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.cu-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.cu-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.cu-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.cu-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.cu-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.cu-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.cu-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.cu-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.cu-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.cu-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.cu-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.cu-col-span-1{grid-column:span 1/span 1}.cu-col-span-2{grid-column:span 2/span 2}.cu-col-span-3{grid-column:span 3/span 3}.cu-col-span-4{grid-column:span 4/span 4}.cu-col-span-5{grid-column:span 5/span 5}.cu-col-span-6{grid-column:span 6/span 6}.cu-col-span-7{grid-column:span 7/span 7}.cu-col-span-8{grid-column:span 8/span 8}.cu-col-span-9{grid-column:span 9/span 9}.cu-col-span-10{grid-column:span 10/span 10}.cu-col-span-11{grid-column:span 11/span 11}.cu-col-span-12{grid-column:span 12/span 12}.cu-col-span-auto{grid-column:span auto/span auto}.cu-col-start-1{grid-column-start:1}.cu-col-start-2{grid-column-start:2}.cu-col-start-3{grid-column-start:3}.cu-col-start-4{grid-column-start:4}.cu-col-start-5{grid-column-start:5}.cu-col-start-6{grid-column-start:6}.cu-col-start-7{grid-column-start:7}.cu-col-start-8{grid-column-start:8}.cu-col-start-9{grid-column-start:9}.cu-col-start-10{grid-column-start:10}.cu-col-start-11{grid-column-start:11}.cu-col-start-12{grid-column-start:12}.cu-col-start-13{grid-column-start:13}.cu-col-start-auto{grid-column-start:auto}.cu-col-end-1{grid-column-end:1}.cu-col-end-2{grid-column-end:2}.cu-col-end-3{grid-column-end:3}.cu-col-end-4{grid-column-end:4}.cu-col-end-5{grid-column-end:5}.cu-col-end-6{grid-column-end:6}.cu-col-end-7{grid-column-end:7}.cu-col-end-8{grid-column-end:8}.cu-col-end-9{grid-column-end:9}.cu-col-end-10{grid-column-end:10}.cu-col-end-11{grid-column-end:11}.cu-col-end-12{grid-column-end:12}.cu-col-end-13{grid-column-end:13}.cu-col-end-auto{grid-column-end:auto}.cu-row-span-1{grid-row:span 1/span 1}.cu-row-span-2{grid-row:span 2/span 2}.cu-row-span-3{grid-row:span 3/span 3}.cu-row-span-4{grid-row:span 4/span 4}.cu-row-span-5{grid-row:span 5/span 5}.cu-row-span-6{grid-row:span 6/span 6}.cu-row-span-7{grid-row:span 7/span 7}.cu-row-span-8{grid-row:span 8/span 8}.cu-row-span-9{grid-row:span 9/span 9}.cu-row-span-10{grid-row:span 10/span 10}.cu-row-span-11{grid-row:span 11/span 11}.cu-row-span-12{grid-row:span 12/span 12}.cu-row-span-auto{grid-row:span auto/span auto}@media (width>=640px){.xs\:cu-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xs\:cu-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xs\:cu-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xs\:cu-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xs\:cu-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xs\:cu-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xs\:cu-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xs\:cu-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xs\:cu-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xs\:cu-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xs\:cu-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xs\:cu-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xs\:cu-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xs\:cu-col-span-1{grid-column:span 1/span 1}.xs\:cu-col-span-2{grid-column:span 2/span 2}.xs\:cu-col-span-3{grid-column:span 3/span 3}.xs\:cu-col-span-4{grid-column:span 4/span 4}.xs\:cu-col-span-5{grid-column:span 5/span 5}.xs\:cu-col-span-6{grid-column:span 6/span 6}.xs\:cu-col-span-7{grid-column:span 7/span 7}.xs\:cu-col-span-8{grid-column:span 8/span 8}.xs\:cu-col-span-9{grid-column:span 9/span 9}.xs\:cu-col-span-10{grid-column:span 10/span 10}.xs\:cu-col-span-11{grid-column:span 11/span 11}.xs\:cu-col-span-12{grid-column:span 12/span 12}.xs\:cu-col-span-auto{grid-column:span auto/span auto}.xs\:cu-col-start-1{grid-column-start:1}.xs\:cu-col-start-2{grid-column-start:2}.xs\:cu-col-start-3{grid-column-start:3}.xs\:cu-col-start-4{grid-column-start:4}.xs\:cu-col-start-5{grid-column-start:5}.xs\:cu-col-start-6{grid-column-start:6}.xs\:cu-col-start-7{grid-column-start:7}.xs\:cu-col-start-8{grid-column-start:8}.xs\:cu-col-start-9{grid-column-start:9}.xs\:cu-col-start-10{grid-column-start:10}.xs\:cu-col-start-11{grid-column-start:11}.xs\:cu-col-start-12{grid-column-start:12}.xs\:cu-col-start-13{grid-column-start:13}.xs\:cu-col-start-auto{grid-column-start:auto}.xs\:cu-col-end-1{grid-column-end:1}.xs\:cu-col-end-2{grid-column-end:2}.xs\:cu-col-end-3{grid-column-end:3}.xs\:cu-col-end-4{grid-column-end:4}.xs\:cu-col-end-5{grid-column-end:5}.xs\:cu-col-end-6{grid-column-end:6}.xs\:cu-col-end-7{grid-column-end:7}.xs\:cu-col-end-8{grid-column-end:8}.xs\:cu-col-end-9{grid-column-end:9}.xs\:cu-col-end-10{grid-column-end:10}.xs\:cu-col-end-11{grid-column-end:11}.xs\:cu-col-end-12{grid-column-end:12}.xs\:cu-col-end-13{grid-column-end:13}.xs\:cu-col-end-auto{grid-column-end:auto}.xs\:cu-row-span-1{grid-row:span 1/span 1}.xs\:cu-row-span-2{grid-row:span 2/span 2}.xs\:cu-row-span-3{grid-row:span 3/span 3}.xs\:cu-row-span-4{grid-row:span 4/span 4}.xs\:cu-row-span-5{grid-row:span 5/span 5}.xs\:cu-row-span-6{grid-row:span 6/span 6}.xs\:cu-row-span-7{grid-row:span 7/span 7}.xs\:cu-row-span-8{grid-row:span 8/span 8}.xs\:cu-row-span-9{grid-row:span 9/span 9}.xs\:cu-row-span-10{grid-row:span 10/span 10}.xs\:cu-row-span-11{grid-row:span 11/span 11}.xs\:cu-row-span-12{grid-row:span 12/span 12}.xs\:cu-row-span-auto{grid-row:span auto/span auto}}@media (width>=768px){.sm\:cu-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:cu-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:cu-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:cu-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:cu-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:cu-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:cu-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:cu-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:cu-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.sm\:cu-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:cu-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:cu-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:cu-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:cu-col-span-1{grid-column:span 1/span 1}.sm\:cu-col-span-2{grid-column:span 2/span 2}.sm\:cu-col-span-3{grid-column:span 3/span 3}.sm\:cu-col-span-4{grid-column:span 4/span 4}.sm\:cu-col-span-5{grid-column:span 5/span 5}.sm\:cu-col-span-6{grid-column:span 6/span 6}.sm\:cu-col-span-7{grid-column:span 7/span 7}.sm\:cu-col-span-8{grid-column:span 8/span 8}.sm\:cu-col-span-9{grid-column:span 9/span 9}.sm\:cu-col-span-10{grid-column:span 10/span 10}.sm\:cu-col-span-11{grid-column:span 11/span 11}.sm\:cu-col-span-12{grid-column:span 12/span 12}.sm\:cu-col-span-auto{grid-column:span auto/span auto}.sm\:cu-col-start-1{grid-column-start:1}.sm\:cu-col-start-2{grid-column-start:2}.sm\:cu-col-start-3{grid-column-start:3}.sm\:cu-col-start-4{grid-column-start:4}.sm\:cu-col-start-5{grid-column-start:5}.sm\:cu-col-start-6{grid-column-start:6}.sm\:cu-col-start-7{grid-column-start:7}.sm\:cu-col-start-8{grid-column-start:8}.sm\:cu-col-start-9{grid-column-start:9}.sm\:cu-col-start-10{grid-column-start:10}.sm\:cu-col-start-11{grid-column-start:11}.sm\:cu-col-start-12{grid-column-start:12}.sm\:cu-col-start-13{grid-column-start:13}.sm\:cu-col-start-auto{grid-column-start:auto}.sm\:cu-col-end-1{grid-column-end:1}.sm\:cu-col-end-2{grid-column-end:2}.sm\:cu-col-end-3{grid-column-end:3}.sm\:cu-col-end-4{grid-column-end:4}.sm\:cu-col-end-5{grid-column-end:5}.sm\:cu-col-end-6{grid-column-end:6}.sm\:cu-col-end-7{grid-column-end:7}.sm\:cu-col-end-8{grid-column-end:8}.sm\:cu-col-end-9{grid-column-end:9}.sm\:cu-col-end-10{grid-column-end:10}.sm\:cu-col-end-11{grid-column-end:11}.sm\:cu-col-end-12{grid-column-end:12}.sm\:cu-col-end-13{grid-column-end:13}.sm\:cu-col-end-auto{grid-column-end:auto}.sm\:cu-row-span-1{grid-row:span 1/span 1}.sm\:cu-row-span-2{grid-row:span 2/span 2}.sm\:cu-row-span-3{grid-row:span 3/span 3}.sm\:cu-row-span-4{grid-row:span 4/span 4}.sm\:cu-row-span-5{grid-row:span 5/span 5}.sm\:cu-row-span-6{grid-row:span 6/span 6}.sm\:cu-row-span-7{grid-row:span 7/span 7}.sm\:cu-row-span-8{grid-row:span 8/span 8}.sm\:cu-row-span-9{grid-row:span 9/span 9}.sm\:cu-row-span-10{grid-row:span 10/span 10}.sm\:cu-row-span-11{grid-row:span 11/span 11}.sm\:cu-row-span-12{grid-row:span 12/span 12}.sm\:cu-row-span-auto{grid-row:span auto/span auto}}@media (width>=1024px){.md\:cu-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:cu-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:cu-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:cu-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:cu-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:cu-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:cu-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:cu-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:cu-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:cu-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:cu-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:cu-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:cu-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.md\:cu-col-span-1{grid-column:span 1/span 1}.md\:cu-col-span-2{grid-column:span 2/span 2}.md\:cu-col-span-3{grid-column:span 3/span 3}.md\:cu-col-span-4{grid-column:span 4/span 4}.md\:cu-col-span-5{grid-column:span 5/span 5}.md\:cu-col-span-6{grid-column:span 6/span 6}.md\:cu-col-span-7{grid-column:span 7/span 7}.md\:cu-col-span-8{grid-column:span 8/span 8}.md\:cu-col-span-9{grid-column:span 9/span 9}.md\:cu-col-span-10{grid-column:span 10/span 10}.md\:cu-col-span-11{grid-column:span 11/span 11}.md\:cu-col-span-12{grid-column:span 12/span 12}.md\:cu-col-span-auto{grid-column:span auto/span auto}.md\:cu-col-start-1{grid-column-start:1}.md\:cu-col-start-2{grid-column-start:2}.md\:cu-col-start-3{grid-column-start:3}.md\:cu-col-start-4{grid-column-start:4}.md\:cu-col-start-5{grid-column-start:5}.md\:cu-col-start-6{grid-column-start:6}.md\:cu-col-start-7{grid-column-start:7}.md\:cu-col-start-8{grid-column-start:8}.md\:cu-col-start-9{grid-column-start:9}.md\:cu-col-start-10{grid-column-start:10}.md\:cu-col-start-11{grid-column-start:11}.md\:cu-col-start-12{grid-column-start:12}.md\:cu-col-start-13{grid-column-start:13}.md\:cu-col-start-auto{grid-column-start:auto}.md\:cu-col-end-1{grid-column-end:1}.md\:cu-col-end-2{grid-column-end:2}.md\:cu-col-end-3{grid-column-end:3}.md\:cu-col-end-4{grid-column-end:4}.md\:cu-col-end-5{grid-column-end:5}.md\:cu-col-end-6{grid-column-end:6}.md\:cu-col-end-7{grid-column-end:7}.md\:cu-col-end-8{grid-column-end:8}.md\:cu-col-end-9{grid-column-end:9}.md\:cu-col-end-10{grid-column-end:10}.md\:cu-col-end-11{grid-column-end:11}.md\:cu-col-end-12{grid-column-end:12}.md\:cu-col-end-13{grid-column-end:13}.md\:cu-col-end-auto{grid-column-end:auto}.md\:cu-row-span-1{grid-row:span 1/span 1}.md\:cu-row-span-2{grid-row:span 2/span 2}.md\:cu-row-span-3{grid-row:span 3/span 3}.md\:cu-row-span-4{grid-row:span 4/span 4}.md\:cu-row-span-5{grid-row:span 5/span 5}.md\:cu-row-span-6{grid-row:span 6/span 6}.md\:cu-row-span-7{grid-row:span 7/span 7}.md\:cu-row-span-8{grid-row:span 8/span 8}.md\:cu-row-span-9{grid-row:span 9/span 9}.md\:cu-row-span-10{grid-row:span 10/span 10}.md\:cu-row-span-11{grid-row:span 11/span 11}.md\:cu-row-span-12{grid-row:span 12/span 12}.md\:cu-row-span-auto{grid-row:span auto/span auto}}@media (width>=1280px){.lg\:cu-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:cu-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:cu-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:cu-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:cu-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:cu-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:cu-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:cu-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:cu-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:cu-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:cu-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:cu-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:cu-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.lg\:cu-col-span-1{grid-column:span 1/span 1}.lg\:cu-col-span-2{grid-column:span 2/span 2}.lg\:cu-col-span-3{grid-column:span 3/span 3}.lg\:cu-col-span-4{grid-column:span 4/span 4}.lg\:cu-col-span-5{grid-column:span 5/span 5}.lg\:cu-col-span-6{grid-column:span 6/span 6}.lg\:cu-col-span-7{grid-column:span 7/span 7}.lg\:cu-col-span-8{grid-column:span 8/span 8}.lg\:cu-col-span-9{grid-column:span 9/span 9}.lg\:cu-col-span-10{grid-column:span 10/span 10}.lg\:cu-col-span-11{grid-column:span 11/span 11}.lg\:cu-col-span-12{grid-column:span 12/span 12}.lg\:cu-col-span-auto{grid-column:span auto/span auto}.lg\:cu-col-start-1{grid-column-start:1}.lg\:cu-col-start-2{grid-column-start:2}.lg\:cu-col-start-3{grid-column-start:3}.lg\:cu-col-start-4{grid-column-start:4}.lg\:cu-col-start-5{grid-column-start:5}.lg\:cu-col-start-6{grid-column-start:6}.lg\:cu-col-start-7{grid-column-start:7}.lg\:cu-col-start-8{grid-column-start:8}.lg\:cu-col-start-9{grid-column-start:9}.lg\:cu-col-start-10{grid-column-start:10}.lg\:cu-col-start-11{grid-column-start:11}.lg\:cu-col-start-12{grid-column-start:12}.lg\:cu-col-start-13{grid-column-start:13}.lg\:cu-col-start-auto{grid-column-start:auto}.lg\:cu-col-end-1{grid-column-end:1}.lg\:cu-col-end-2{grid-column-end:2}.lg\:cu-col-end-3{grid-column-end:3}.lg\:cu-col-end-4{grid-column-end:4}.lg\:cu-col-end-5{grid-column-end:5}.lg\:cu-col-end-6{grid-column-end:6}.lg\:cu-col-end-7{grid-column-end:7}.lg\:cu-col-end-8{grid-column-end:8}.lg\:cu-col-end-9{grid-column-end:9}.lg\:cu-col-end-10{grid-column-end:10}.lg\:cu-col-end-11{grid-column-end:11}.lg\:cu-col-end-12{grid-column-end:12}.lg\:cu-col-end-13{grid-column-end:13}.lg\:cu-col-end-auto{grid-column-end:auto}.lg\:cu-row-span-1{grid-row:span 1/span 1}.lg\:cu-row-span-2{grid-row:span 2/span 2}.lg\:cu-row-span-3{grid-row:span 3/span 3}.lg\:cu-row-span-4{grid-row:span 4/span 4}.lg\:cu-row-span-5{grid-row:span 5/span 5}.lg\:cu-row-span-6{grid-row:span 6/span 6}.lg\:cu-row-span-7{grid-row:span 7/span 7}.lg\:cu-row-span-8{grid-row:span 8/span 8}.lg\:cu-row-span-9{grid-row:span 9/span 9}.lg\:cu-row-span-10{grid-row:span 10/span 10}.lg\:cu-row-span-11{grid-row:span 11/span 11}.lg\:cu-row-span-12{grid-row:span 12/span 12}.lg\:cu-row-span-auto{grid-row:span auto/span auto}}@media (width>=1536px){.xl\:cu-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:cu-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:cu-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:cu-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:cu-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:cu-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xl\:cu-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xl\:cu-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xl\:cu-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xl\:cu-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xl\:cu-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xl\:cu-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:cu-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xl\:cu-col-span-1{grid-column:span 1/span 1}.xl\:cu-col-span-2{grid-column:span 2/span 2}.xl\:cu-col-span-3{grid-column:span 3/span 3}.xl\:cu-col-span-4{grid-column:span 4/span 4}.xl\:cu-col-span-5{grid-column:span 5/span 5}.xl\:cu-col-span-6{grid-column:span 6/span 6}.xl\:cu-col-span-7{grid-column:span 7/span 7}.xl\:cu-col-span-8{grid-column:span 8/span 8}.xl\:cu-col-span-9{grid-column:span 9/span 9}.xl\:cu-col-span-10{grid-column:span 10/span 10}.xl\:cu-col-span-11{grid-column:span 11/span 11}.xl\:cu-col-span-12{grid-column:span 12/span 12}.xl\:cu-col-span-auto{grid-column:span auto/span auto}.xl\:cu-col-start-1{grid-column-start:1}.xl\:cu-col-start-2{grid-column-start:2}.xl\:cu-col-start-3{grid-column-start:3}.xl\:cu-col-start-4{grid-column-start:4}.xl\:cu-col-start-5{grid-column-start:5}.xl\:cu-col-start-6{grid-column-start:6}.xl\:cu-col-start-7{grid-column-start:7}.xl\:cu-col-start-8{grid-column-start:8}.xl\:cu-col-start-9{grid-column-start:9}.xl\:cu-col-start-10{grid-column-start:10}.xl\:cu-col-start-11{grid-column-start:11}.xl\:cu-col-start-12{grid-column-start:12}.xl\:cu-col-start-13{grid-column-start:13}.xl\:cu-col-start-auto{grid-column-start:auto}.xl\:cu-col-end-1{grid-column-end:1}.xl\:cu-col-end-2{grid-column-end:2}.xl\:cu-col-end-3{grid-column-end:3}.xl\:cu-col-end-4{grid-column-end:4}.xl\:cu-col-end-5{grid-column-end:5}.xl\:cu-col-end-6{grid-column-end:6}.xl\:cu-col-end-7{grid-column-end:7}.xl\:cu-col-end-8{grid-column-end:8}.xl\:cu-col-end-9{grid-column-end:9}.xl\:cu-col-end-10{grid-column-end:10}.xl\:cu-col-end-11{grid-column-end:11}.xl\:cu-col-end-12{grid-column-end:12}.xl\:cu-col-end-13{grid-column-end:13}.xl\:cu-col-end-auto{grid-column-end:auto}.xl\:cu-row-span-1{grid-row:span 1/span 1}.xl\:cu-row-span-2{grid-row:span 2/span 2}.xl\:cu-row-span-3{grid-row:span 3/span 3}.xl\:cu-row-span-4{grid-row:span 4/span 4}.xl\:cu-row-span-5{grid-row:span 5/span 5}.xl\:cu-row-span-6{grid-row:span 6/span 6}.xl\:cu-row-span-7{grid-row:span 7/span 7}.xl\:cu-row-span-8{grid-row:span 8/span 8}.xl\:cu-row-span-9{grid-row:span 9/span 9}.xl\:cu-row-span-10{grid-row:span 10/span 10}.xl\:cu-row-span-11{grid-row:span 11/span 11}.xl\:cu-row-span-12{grid-row:span 12/span 12}.xl\:cu-row-span-auto{grid-row:span auto/span auto}}.cu-gap{gap:var(--gap)}.cu-gap-0\.5{gap:var(--canon-space-0_5)}.cu-gap-1{gap:var(--canon-space-1)}.cu-gap-1\.5{gap:var(--canon-space-1_5)}.cu-gap-2{gap:var(--canon-space-2)}.cu-gap-3{gap:var(--canon-space-3)}.cu-gap-4{gap:var(--canon-space-4)}.cu-gap-5{gap:var(--canon-space-5)}.cu-gap-6{gap:var(--canon-space-6)}.cu-gap-7{gap:var(--canon-space-7)}.cu-gap-8{gap:var(--canon-space-8)}.cu-gap-9{gap:var(--canon-space-9)}.cu-gap-10{gap:var(--canon-space-10)}.cu-gap-11{gap:var(--canon-space-11)}.cu-gap-12{gap:var(--canon-space-12)}.cu-gap-13{gap:var(--canon-space-13)}.cu-gap-14{gap:var(--canon-space-14)}@media (width>=640px){.xs\:cu-gap{gap:var(--gap-xs)}.xs\:cu-gap-0\.5{gap:var(--canon-space-0_5)}.xs\:cu-gap-1{gap:var(--canon-space-1)}.xs\:cu-gap-1\.5{gap:var(--canon-space-1_5)}.xs\:cu-gap-2{gap:var(--canon-space-2)}.xs\:cu-gap-3{gap:var(--canon-space-3)}.xs\:cu-gap-4{gap:var(--canon-space-4)}.xs\:cu-gap-5{gap:var(--canon-space-5)}.xs\:cu-gap-6{gap:var(--canon-space-6)}.xs\:cu-gap-7{gap:var(--canon-space-7)}.xs\:cu-gap-8{gap:var(--canon-space-8)}.xs\:cu-gap-9{gap:var(--canon-space-9)}.xs\:cu-gap-10{gap:var(--canon-space-10)}.xs\:cu-gap-11{gap:var(--canon-space-11)}.xs\:cu-gap-12{gap:var(--canon-space-12)}.xs\:cu-gap-13{gap:var(--canon-space-13)}.xs\:cu-gap-14{gap:var(--canon-space-14)}}@media (width>=768px){.sm\:cu-gap{gap:var(--gap-sm)}.sm\:cu-gap-0\.5{gap:var(--canon-space-0_5)}.sm\:cu-gap-1{gap:var(--canon-space-1)}.sm\:cu-gap-1\.5{gap:var(--canon-space-1_5)}.sm\:cu-gap-2{gap:var(--canon-space-2)}.sm\:cu-gap-3{gap:var(--canon-space-3)}.sm\:cu-gap-4{gap:var(--canon-space-4)}.sm\:cu-gap-5{gap:var(--canon-space-5)}.sm\:cu-gap-6{gap:var(--canon-space-6)}.sm\:cu-gap-7{gap:var(--canon-space-7)}.sm\:cu-gap-8{gap:var(--canon-space-8)}.sm\:cu-gap-9{gap:var(--canon-space-9)}.sm\:cu-gap-10{gap:var(--canon-space-10)}.sm\:cu-gap-11{gap:var(--canon-space-11)}.sm\:cu-gap-12{gap:var(--canon-space-12)}.sm\:cu-gap-13{gap:var(--canon-space-13)}.sm\:cu-gap-14{gap:var(--canon-space-14)}}@media (width>=1024px){.md\:cu-gap{gap:var(--gap-md)}.md\:cu-gap-0\.5{gap:var(--canon-space-0_5)}.md\:cu-gap-1{gap:var(--canon-space-1)}.md\:cu-gap-1\.5{gap:var(--canon-space-1_5)}.md\:cu-gap-2{gap:var(--canon-space-2)}.md\:cu-gap-3{gap:var(--canon-space-3)}.md\:cu-gap-4{gap:var(--canon-space-4)}.md\:cu-gap-5{gap:var(--canon-space-5)}.md\:cu-gap-6{gap:var(--canon-space-6)}.md\:cu-gap-7{gap:var(--canon-space-7)}.md\:cu-gap-8{gap:var(--canon-space-8)}.md\:cu-gap-9{gap:var(--canon-space-9)}.md\:cu-gap-10{gap:var(--canon-space-10)}.md\:cu-gap-11{gap:var(--canon-space-11)}.md\:cu-gap-12{gap:var(--canon-space-12)}.md\:cu-gap-13{gap:var(--canon-space-13)}.md\:cu-gap-14{gap:var(--canon-space-14)}}@media (width>=1280px){.lg\:cu-gap{gap:var(--gap-lg)}.lg\:cu-gap-0\.5{gap:var(--canon-space-0_5)}.lg\:cu-gap-1{gap:var(--canon-space-1)}.lg\:cu-gap-1\.5{gap:var(--canon-space-1_5)}.lg\:cu-gap-2{gap:var(--canon-space-2)}.lg\:cu-gap-3{gap:var(--canon-space-3)}.lg\:cu-gap-4{gap:var(--canon-space-4)}.lg\:cu-gap-5{gap:var(--canon-space-5)}.lg\:cu-gap-6{gap:var(--canon-space-6)}.lg\:cu-gap-7{gap:var(--canon-space-7)}.lg\:cu-gap-8{gap:var(--canon-space-8)}.lg\:cu-gap-9{gap:var(--canon-space-9)}.lg\:cu-gap-10{gap:var(--canon-space-10)}.lg\:cu-gap-11{gap:var(--canon-space-11)}.lg\:cu-gap-12{gap:var(--canon-space-12)}.lg\:cu-gap-13{gap:var(--canon-space-13)}.lg\:cu-gap-14{gap:var(--canon-space-14)}}@media (width>=1536px){.xl\:cu-gap{gap:var(--gap-xl)}.xl\:cu-gap-0\.5{gap:var(--canon-space-0_5)}.xl\:cu-gap-1{gap:var(--canon-space-1)}.xl\:cu-gap-1\.5{gap:var(--canon-space-1_5)}.xl\:cu-gap-2{gap:var(--canon-space-2)}.xl\:cu-gap-3{gap:var(--canon-space-3)}.xl\:cu-gap-4{gap:var(--canon-space-4)}.xl\:cu-gap-5{gap:var(--canon-space-5)}.xl\:cu-gap-6{gap:var(--canon-space-6)}.xl\:cu-gap-7{gap:var(--canon-space-7)}.xl\:cu-gap-8{gap:var(--canon-space-8)}.xl\:cu-gap-9{gap:var(--canon-space-9)}.xl\:cu-gap-10{gap:var(--canon-space-10)}.xl\:cu-gap-11{gap:var(--canon-space-11)}.xl\:cu-gap-12{gap:var(--canon-space-12)}.xl\:cu-gap-13{gap:var(--canon-space-13)}.xl\:cu-gap-14{gap:var(--canon-space-14)}}.cu-align-start{align-items:start}.cu-align-center{align-items:center}.cu-align-end{align-items:end}.cu-align-stretch{align-items:stretch}.cu-jc-start{justify-content:start}.cu-jc-center{justify-content:center}.cu-jc-end{justify-content:end}.cu-jc-between{justify-content:space-between}.cu-fd-row{flex-direction:row}.cu-fd-column{flex-direction:column}.cu-fd-row-reverse{flex-direction:row-reverse}.cu-fd-column-reverse{flex-direction:column-reverse}@media (width>=640px){.xs\:cu-align-start{align-items:start}.xs\:cu-align-center{align-items:center}.xs\:cu-align-end{align-items:end}.xs\:cu-align-stretch{align-items:stretch}.xs\:cu-jc-start{justify-content:start}.xs\:cu-jc-center{justify-content:center}.xs\:cu-jc-end{justify-content:end}.xs\:cu-jc-between{justify-content:space-between}.xs\:cu-fd-row{flex-direction:row}.xs\:cu-fd-column{flex-direction:column}.xs\:cu-fd-row-reverse{flex-direction:row-reverse}.xs\:cu-fd-column-reverse{flex-direction:column-reverse}}@media (width>=768px){.sm\:cu-align-start{align-items:start}.sm\:cu-align-center{align-items:center}.sm\:cu-align-end{align-items:end}.sm\:cu-align-stretch{align-items:stretch}.sm\:cu-jc-start{justify-content:start}.sm\:cu-jc-center{justify-content:center}.sm\:cu-jc-end{justify-content:end}.sm\:cu-jc-between{justify-content:space-between}.sm\:cu-fd-row{flex-direction:row}.sm\:cu-fd-column{flex-direction:column}.sm\:cu-fd-row-reverse{flex-direction:row-reverse}.sm\:cu-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1024px){.md\:cu-align-start{align-items:start}.md\:cu-align-center{align-items:center}.md\:cu-align-end{align-items:end}.md\:cu-align-stretch{align-items:stretch}.md\:cu-jc-start{justify-content:start}.md\:cu-jc-center{justify-content:center}.md\:cu-jc-end{justify-content:end}.md\:cu-jc-between{justify-content:space-between}.md\:cu-fd-row{flex-direction:row}.md\:cu-fd-column{flex-direction:column}.md\:cu-fd-row-reverse{flex-direction:row-reverse}.md\:cu-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1280px){.lg\:cu-align-start{align-items:start}.lg\:cu-align-center{align-items:center}.lg\:cu-align-end{align-items:end}.lg\:cu-align-stretch{align-items:stretch}.lg\:cu-jc-start{justify-content:start}.lg\:cu-jc-center{justify-content:center}.lg\:cu-jc-end{justify-content:end}.lg\:cu-jc-between{justify-content:space-between}.lg\:cu-fd-row{flex-direction:row}.lg\:cu-fd-column{flex-direction:column}.lg\:cu-fd-row-reverse{flex-direction:row-reverse}.lg\:cu-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1536px){.xl\:cu-align-start{align-items:start}.xl\:cu-align-center{align-items:center}.xl\:cu-align-end{align-items:end}.xl\:cu-align-stretch{align-items:stretch}.xl\:cu-jc-start{justify-content:start}.xl\:cu-jc-center{justify-content:center}.xl\:cu-jc-end{justify-content:end}.xl\:cu-jc-between{justify-content:space-between}.xl\:cu-fd-row{flex-direction:row}.xl\:cu-fd-column{flex-direction:column}.xl\:cu-fd-row-reverse{flex-direction:row-reverse}.xl\:cu-fd-column-reverse{flex-direction:column-reverse}}:where(a){color:inherit;text-decoration:none}:root{--canon-font-regular:system-ui;--canon-font-monospace:ui-monospace,"Menlo","Monaco","Consolas","Liberation Mono","Courier New",monospace;--canon-font-weight-regular:400;--canon-font-weight-bold:600;--canon-font-size-1:.625rem;--canon-font-size-2:.75rem;--canon-font-size-3:.875rem;--canon-font-size-4:1rem;--canon-font-size-5:1.25rem;--canon-font-size-6:1.5rem;--canon-font-size-7:2rem;--canon-font-size-8:3rem;--canon-font-size-9:4rem;--canon-font-size-10:5.75rem;--canon-space:.25rem;--canon-space-0_5:calc(var(--canon-space)*.5);--canon-space-1:var(--canon-space);--canon-space-1_5:calc(var(--canon-space)*1.5);--canon-space-2:calc(var(--canon-space)*2);--canon-space-3:calc(var(--canon-space)*3);--canon-space-4:calc(var(--canon-space)*4);--canon-space-5:calc(var(--canon-space)*5);--canon-space-6:calc(var(--canon-space)*6);--canon-space-7:calc(var(--canon-space)*7);--canon-space-8:calc(var(--canon-space)*8);--canon-space-9:calc(var(--canon-space)*9);--canon-space-10:calc(var(--canon-space)*10);--canon-space-11:calc(var(--canon-space)*11);--canon-space-12:calc(var(--canon-space)*12);--canon-space-13:calc(var(--canon-space)*13);--canon-space-14:calc(var(--canon-space)*14);--canon-radius-1:calc(.125rem);--canon-radius-2:calc(.25rem);--canon-radius-3:calc(.5rem);--canon-radius-4:calc(.75rem);--canon-radius-5:calc(1rem);--canon-radius-6:calc(1.25rem);--canon-radius-full:9999px;--canon-black:#000;--canon-white:#fff;--canon-gray-1:#f8f8f8;--canon-gray-2:#ececec;--canon-gray-3:#d9d9d9;--canon-gray-4:#c1c1c1;--canon-gray-5:#9e9e9e;--canon-gray-6:#8c8c8c;--canon-gray-7:#757575;--canon-gray-8:#595959;--canon-bg:var(--canon-gray-1);--canon-bg-surface-1:var(--canon-white);--canon-bg-surface-2:var(--canon-gray-2);--canon-bg-solid:#1f5493;--canon-bg-solid-hover:#163a66;--canon-bg-solid-pressed:#0f2b4e;--canon-bg-solid-disabled:#ebebeb;--canon-bg-tint:transparent;--canon-bg-tint-hover:#1f549366;--canon-bg-tint-pressed:#1f549399;--canon-bg-tint-disabled:#ebebeb;--canon-bg-danger:#feebe7;--canon-bg-warning:#fff2b2;--canon-bg-success:#e6f6eb;--canon-fg-primary:var(--canon-black);--canon-fg-secondary:var(--canon-gray-7);--canon-fg-link:#1f5493;--canon-fg-link-hover:#1f2d5c;--canon-fg-disabled:#9e9e9e;--canon-fg-solid:var(--canon-white);--canon-fg-solid-disabled:#9c9c9c;--canon-fg-tint:#1f5493;--canon-fg-tint-disabled:var(--canon-gray-5);--canon-fg-danger:#e22b2b;--canon-fg-warning:#e36d05;--canon-fg-success:#1db954;--canon-border:#0000001a;--canon-border-hover:#0003;--canon-border-pressed:#0006;--canon-border-disabled:#0000001a;--canon-border-danger:#f87a7a;--canon-border-warning:#e36d05;--canon-border-success:#53db83;--canon-ring:#1f5493;--canon-scrollbar:#a0a0a03b;--canon-scrollbar-thumb:#a0a0a0}[data-theme=dark]{--canon-gray-1:#191919;--canon-gray-2:#242424;--canon-gray-3:#373737;--canon-gray-4:#464646;--canon-gray-5:#575757;--canon-gray-6:#7b7b7b;--canon-gray-7:#9e9e9e;--canon-gray-8:#b4b4b4;--canon-bg:var(--canon-black);--canon-bg-surface-1:var(--canon-gray-1);--canon-bg-surface-2:var(--canon-gray-2);--canon-bg-solid:#9cc9ff;--canon-bg-solid-hover:#83b9fd;--canon-bg-solid-pressed:#83b9fd;--canon-bg-solid-disabled:#222;--canon-bg-tint:transparent;--canon-bg-tint-hover:#9cc9ff1f;--canon-bg-tint-pressed:#9cc9ff29;--canon-bg-tint-disabled:transparent;--canon-bg-danger:#3b1219;--canon-bg-warning:#302008;--canon-bg-success:#132d21;--canon-fg-primary:var(--canon-white);--canon-fg-secondary:var(--canon-gray-7);--canon-fg-link:#9cc9ff;--canon-fg-link-hover:#7eb5f7;--canon-fg-disabled:var(--canon-gray-7);--canon-fg-solid:#101821;--canon-fg-solid-disabled:var(--canon-gray-5);--canon-fg-tint:#9cc9ff;--canon-fg-tint-disabled:var(--canon-gray-5);--canon-fg-danger:#e22b2b;--canon-fg-warning:#e36d05;--canon-fg-success:#1db954;--canon-border:#fff3;--canon-border-hover:#fff6;--canon-border-pressed:#ffffff80;--canon-border-disabled:#fff3;--canon-border-danger:#f87a7a;--canon-border-warning:#e36d05;--canon-border-success:#53db83;--canon-ring:#1f5493;--canon-scrollbar:#3636363a;--canon-scrollbar-thumb:#575757}.canon-AvatarRoot{vertical-align:middle;user-select:none;color:var(--canon-fg-primary);background-color:var(--canon-bg-surface-2);border-radius:100%;justify-content:center;align-items:center;width:2rem;height:2rem;font-size:1rem;font-weight:500;line-height:1;display:inline-flex;overflow:hidden}.canon-AvatarRoot[data-size=small]{width:1.5rem;height:1.5rem}.canon-AvatarRoot[data-size=medium]{width:2rem;height:2rem}.canon-AvatarRoot[data-size=large]{width:3rem;height:3rem}.canon-AvatarImage{object-fit:cover;width:100%;height:100%}.canon-AvatarFallback{width:100%;height:100%;font-size:var(--canon-font-size-3);font-weight:var(--canon-font-weight-regular);box-shadow:inset 0 0 0 1px var(--canon-border);border-radius:var(--canon-radius-full);justify-content:center;align-items:center;display:flex}.canon-Box{font-family:var(--canon-font-regular);font-weight:var(--canon-font-weight-regular);color:var(--canon-fg-primary)}.canon-Button{user-select:none;font-family:var(--canon-font-regular);font-weight:var(--canon-font-weight-bold);cursor:pointer;border-radius:var(--canon-radius-2);justify-content:center;align-items:center;gap:var(--canon-space-1_5);border:none;padding:0;display:inline-flex;&:disabled{cursor:not-allowed}}.canon-Button[data-variant=primary]{background-color:var(--canon-bg-solid);color:var(--canon-fg-solid);transition:background-color .15s,box-shadow .15s;&:hover{background-color:var(--canon-bg-solid-hover)}&:active{background-color:var(--canon-bg-solid-pressed)}&:focus-visible{outline:2px solid var(--canon-ring);outline-offset:2px}&:disabled{background-color:var(--canon-bg-solid-disabled);color:var(--canon-fg-solid-disabled)}}.canon-Button[data-variant=secondary]{background-color:var(--canon-bg-surface-1);box-shadow:inset 0 0 0 1px var(--canon-border);color:var(--canon-fg-primary);transition:box-shadow .15s;&:hover{box-shadow:inset 0 0 0 1px var(--canon-border-hover)}&:active{box-shadow:inset 0 0 0 1px var(--canon-border-pressed)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--canon-ring);outline:none;transition:none}&:disabled{box-shadow:inset 0 0 0 1px var(--canon-border-disabled);color:var(--canon-fg-disabled)}}.canon-Button[data-size=medium]{font-size:var(--canon-font-size-4);padding:0 var(--canon-space-3);height:2.5rem}.canon-Button[data-size=small]{font-size:var(--canon-font-size-3);padding:0 var(--canon-space-2);height:2rem}.canon-Button[data-size=small] svg{width:1rem;height:1rem}.canon-Button[data-size=medium] svg{width:1.25rem;height:1.25rem}.canon-ButtonIcon{justify-content:center;align-items:center}.canon-ButtonIcon[data-size=small]{width:2rem;padding:0}.canon-ButtonIcon[data-size=medium]{width:2.5rem;padding:0}.canon-CheckboxRoot{width:1rem;height:1rem;box-shadow:inset 0 0 0 1px var(--canon-border);cursor:pointer;background-color:var(--canon-bg-surface-1);border:none;border-radius:2px;flex-shrink:0;justify-content:center;align-items:center;padding:0;transition:background-color .2s ease-in-out;display:flex}.canon-CheckboxRoot:focus-visible{outline:2px solid var(--canon-ring);outline-offset:2px;transition:none}.canon-CheckboxRoot[data-checked]{background-color:var(--canon-bg-solid);box-shadow:none;color:var(--canon-fg-solid)}.canon-CheckboxLabel{align-items:center;gap:var(--canon-space-2);font-size:var(--canon-font-size-3);font-family:var(--canon-font-regular);font-weight:var(--canon-font-weight-regular);color:var(--canon-fg-primary);user-select:none;flex-direction:row;display:flex;&:hover{& .canon-CheckboxRoot:not([data-checked]){box-shadow:inset 0 0 0 1px var(--canon-border-hover)}}}.canon-CheckboxIndicator{color:var(--canon-fg-solid);justify-content:center;align-items:center;display:flex}.canon-CollapsiblePanel{height:var(--collapsible-panel-height);transition:all .15s ease-out;display:flex;overflow:hidden;&[data-starting-style],&[data-ending-style]{height:0}}.canon-Container{max-width:120rem;padding-inline:var(--canon-space-4);margin-inline:auto;transition:padding .2s ease-in-out}@media (width>=640px){.canon-Container{padding-inline:var(--canon-space-8)}}@media (width>=1024px){.canon-Container{padding-inline:var(--canon-space-12)}}.canon-DataTableRoot{gap:var(--canon-space-3);flex-direction:column;display:flex}.canon-DataTablePagination{padding-top:var(--canon-space-5);justify-content:space-between;align-items:center;display:flex}.canon-DataTablePagination--left{justify-content:space-between;align-items:center;display:flex}.canon-DataTablePagination--right{justify-content:space-between;align-items:center;gap:var(--canon-space-2);display:flex}.canon-DataTablePagination--select{min-width:10.5rem}.canon-FieldError{color:var(--canon-fg-danger);font-size:var(--canon-font-size-2);font-weight:var(--canon-font-weight-regular);margin-top:var(--canon-space-2)}.canon-FieldLabelWrapper{margin-bottom:var(--canon-space-3);gap:var(--canon-space-1);flex-direction:column;display:flex}.canon-FieldLabel{color:var(--canon-fg-primary);cursor:pointer;font-weight:var(--canon-font-weight-regular);font-size:var(--canon-font-size-2);margin-right:auto}.canon-FieldSecondaryLabel{color:var(--canon-fg-secondary);font-weight:var(--canon-font-weight-regular);margin-left:var(--canon-space-1)}.canon-FieldDescription{font-weight:var(--canon-font-weight-regular);font-size:var(--canon-font-size-2);color:var(--canon-fg-secondary);margin:0}.canon-Flex{min-width:0;display:flex}.canon-Grid{display:grid}.canon-Heading{font-family:var(--canon-font-regular);color:var(--canon-fg-primary);margin:0;padding:0;line-height:100%}.canon-Heading[data-variant=display]{font-size:var(--canon-font-size-10);font-weight:var(--canon-font-weight-bold)}.canon-Heading[data-variant=title1]{font-size:var(--canon-font-size-9);font-weight:var(--canon-font-weight-bold)}.canon-Heading[data-variant=title2]{font-size:var(--canon-font-size-8);font-weight:var(--canon-font-weight-bold)}.canon-Heading[data-variant=title3]{font-size:var(--canon-font-size-7);font-weight:var(--canon-font-weight-bold)}.canon-Heading[data-variant=title4]{font-size:var(--canon-font-size-6);font-weight:var(--canon-font-weight-bold)}.canon-Heading[data-variant=title5]{font-size:var(--canon-font-size-5);font-weight:var(--canon-font-weight-bold)}.canon-Heading[data-color=primary]{color:var(--canon-fg-primary)}.canon-Heading[data-color=secondary]{color:var(--canon-fg-secondary)}.canon-Heading[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.canon-Icon{width:1rem;height:1rem}.canon-Link{font-family:var(--canon-font-regular);color:var(--canon-fg-link);cursor:pointer;margin:0;padding:0;text-decoration-line:none;&:hover{color:var(--canon-fg-link-hover);text-underline-offset:calc(.025em + 2px);text-decoration-line:underline;text-decoration-style:solid;text-decoration-thickness:min(2px,max(1px,.05em));text-decoration-color:color-mix(in srgb,var(--canon-fg-link-hover)30%,transparent)}}.canon-Link[data-variant=body]{font-size:var(--canon-font-size-3);line-height:140%}.canon-Link[data-variant=subtitle]{font-size:var(--canon-font-size-4);line-height:140%}.canon-Link[data-variant=caption]{font-size:var(--canon-font-size-2);line-height:140%}.canon-Link[data-variant=label]{font-size:var(--canon-font-size-1);line-height:140%}.canon-Link[data-weight=regular]{font-weight:var(--canon-font-weight-regular)}.canon-Link[data-weight=bold]{font-weight:var(--canon-font-weight-bold)}.canon-MenuPositioner{outline:0}.canon-MenuPopup{background-color:var(--canon-bg-surface-1);border:1px solid var(--canon-border);color:var(--canon-fg-primary);transform-origin:var(--transform-origin);max-width:min(var(--available-width),340px);max-height:min(var(--available-height),500px);padding-bottom:var(--canon-space-1);border-radius:.375rem;outline:none;flex-direction:column;transition:transform .15s,opacity .15s;display:flex;position:relative;overflow:auto;&[data-starting-style],&[data-ending-style]{opacity:0;transform:scale(.9)}}.canon-MenuItem{user-select:none;align-items:center;gap:var(--canon-space-2);height:32px;color:var(--canon-fg-primary);border-radius:var(--canon-radius-2);margin-inline:var(--canon-space-1);padding-inline:var(--canon-space-2);font-size:var(--canon-font-size-3);cursor:pointer;outline:0;flex-shrink:0;text-decoration:none;display:flex;&:first-child{margin-top:var(--canon-space-1)}&[data-highlighted]{background-color:var(--canon-gray-3)}}.canon-MenuSubmenuTrigger{user-select:none;justify-content:space-between;align-items:center;gap:var(--canon-space-2);height:32px;color:var(--canon-fg-primary);border-radius:var(--canon-radius-2);margin-inline:var(--canon-space-1);padding-inline:var(--canon-space-2);font-size:var(--canon-font-size-3);cursor:pointer;outline:0;flex-shrink:0;text-decoration:none;display:flex;& .canon-Icon{color:var(--canon-fg-secondary)}&:first-child{margin-top:var(--canon-space-1)}&[data-popup-open],&[data-highlighted]{background-color:var(--canon-gray-3);& .canon-Icon{color:var(--canon-fg-primary)}}}.canon-MenuSeparator{background-color:var(--color-gray-200);height:1px;margin:.375rem 1rem}.canon-SubmenuComboboxSearch{padding-inline:var(--canon-space-3);border:none;border-bottom:1px solid var(--canon-border);background-color:var(--canon-bg-surface-1);width:100%;height:32px;color:var(--canon-fg-primary);line-height:140%;font-size:var(--canon-font-size-3);z-index:1;outline:none;position:sticky;top:0;&::placeholder{color:var(--canon-fg-secondary)}&:disabled{opacity:.6;cursor:not-allowed}}.canon-SubmenuComboboxItems{padding-top:var(--canon-space-2);outline:none;flex-direction:column;display:flex;overflow-y:auto}.canon-SubmenuComboboxNoResults{padding-inline:var(--canon-space-3);padding-top:var(--canon-space-2);padding-bottom:var(--canon-space-4);color:var(--canon-fg-secondary);font-size:var(--canon-font-size-3)}.canon-SubmenuComboboxItem{user-select:none;justify-content:space-between;align-items:center;gap:var(--canon-space-2);height:32px;color:var(--canon-fg-primary);border-radius:var(--canon-radius-2);margin-inline:var(--canon-space-1);padding-inline:var(--canon-space-2);font-size:var(--canon-font-size-3);cursor:pointer;outline:0;flex-shrink:0;text-decoration:none;display:flex;&[data-highlighted]{background-color:var(--canon-gray-3)}&[data-disabled]{opacity:.5;cursor:not-allowed}}.canon-SubmenuComboboxItemCheckbox{width:16px;height:16px;color:var(--canon-fg-primary);border-radius:var(--canon-radius-2);border:1px solid var(--canon-border);background:var(--canon-bg-surface-1);flex-shrink:0;justify-content:center;align-items:center;display:flex}.canon-SubmenuComboboxItemLabel{text-overflow:ellipsis;white-space:nowrap;flex:1;overflow:hidden}.canon-RadioGroup{color:var(--canon-fg-primary);flex-direction:column;display:flex}.canon-RadioGroup[data-orientation=horizontal] .canon-RadioGroupContent{gap:var(--canon-space-4);flex-direction:row}.canon-RadioGroupContent{gap:var(--canon-space-2);flex-direction:column;display:flex}.canon-Radio{align-items:center;gap:var(--canon-space-2);font-size:var(--canon-font-size-2);color:var(--canon-fg-primary);forced-color-adjust:none;display:flex;position:relative;&:before{content:"";box-sizing:border-box;border:.125rem solid var(--canon-border);background:var(--canon-gray-1);border-radius:var(--canon-radius-full);width:1rem;height:1rem;transition:all .2s;display:block}&[data-pressed]:before{border-color:var(--canon-border)}&[data-selected]{&:before{border-color:var(--canon-bg-solid);border-width:.25rem}&[data-pressed]:before{border-color:var(--canon-bg-solid)}}&[data-focus-visible]:before{outline:2px solid var(--canon-ring);outline-offset:2px}&[data-disabled]{cursor:not-allowed;color:var(--canon-fg-disabled);&:before{border-color:var(--canon-border-disabled);background:var(--canon-bg-disabled)}&[data-selected]:before{border-color:var(--canon-border-disabled)}}&[data-invalid]:before,&[data-invalid][data-selected]:before{border-color:var(--canon-border-danger)}&[data-disabled][data-invalid]{color:var(--canon-fg-disabled);&:before{border-color:var(--canon-border-disabled);background:var(--canon-bg-disabled)}&[data-selected]:before{border-color:var(--canon-border-disabled)}}}.canon-TableRoot{caption-side:bottom;border-collapse:collapse;width:100%}.canon-TableHead{text-align:left;padding:var(--canon-space-3);font-size:var(--canon-font-size-3);color:var(--canon-fg-primary)}.canon-TableBody{color:var(--canon-fg-primary)}.canon-TableRow{border-bottom:1px solid var(--canon-border);transition:color .2s ease-in-out}.canon-TableBody .canon-TableRow:hover{background-color:var(--canon-gray-2)}.canon-TableCell{padding:var(--canon-space-3);font-size:var(--canon-font-size-3)}.canon-TableCellText,.canon-TableCellLink{gap:var(--canon-space-0_5);flex-direction:column;display:flex}.canon-TableCellProfile{gap:var(--canon-space-2);flex-direction:row;align-items:center;display:flex}.canon-TableCellProfileAvatar{vertical-align:middle;user-select:none;color:var(--canon-fg-primary);background-color:var(--canon-bg-surface-2);border-radius:100%;justify-content:center;align-items:center;width:1.25rem;height:1.25rem;font-size:1rem;font-weight:500;line-height:1;display:inline-flex;overflow:hidden}.canon-TableCellProfileAvatarImage{object-fit:cover;width:100%;height:100%}.canon-TableCellProfileAvatarFallback{width:100%;height:100%;font-size:var(--canon-font-size-2);font-weight:var(--canon-font-weight-regular);box-shadow:inset 0 0 0 1px var(--canon-border);border-radius:var(--canon-radius-full);justify-content:center;align-items:center;display:flex}.canon-TabsRoot{border:1px solid var(--color-gray-200);border-radius:.375rem}.canon-TabsList{z-index:0;display:flex;position:relative}.canon-TabsTab{appearance:none;color:var(--canon-fg-secondary);user-select:none;padding-inline:var(--canon-space-3);height:2rem;font-family:inherit;font-size:.875rem;font-weight:500;line-height:1.25rem;font-size:var(--canon-font-size-2);cursor:pointer;background:0 0;border:0;outline:0;justify-content:center;align-items:center;margin:0;padding-block:0;transition:color .2s ease-in-out;display:flex;&[data-selected]{color:var(--canon-fg-primary)}@media (hover:hover){&:hover{color:var(--canon-fg-primary)}}&:focus-visible{position:relative;&:before{content:"";outline:1px solid var(--canon-ring);outline-offset:-1px;border-radius:.25rem;position:absolute;inset:.25rem 0}}}.canon-TabsIndicator{z-index:-1;translate:var(--active-tab-left)-50%;width:var(--active-tab-width);background-color:var(--canon-bg-solid);height:1px;transition-property:translate,width;transition-duration:.2s;transition-timing-function:ease-in-out;position:absolute;bottom:0;left:0}.canon-TabsPanel{&[hidden]{display:none}}.canon-Text{font-family:var(--canon-font-regular);margin:0;padding:0}.canon-Text[data-variant=body]{font-size:var(--canon-font-size-3);line-height:140%}.canon-Text[data-variant=subtitle]{font-size:var(--canon-font-size-4);line-height:140%}.canon-Text[data-variant=caption]{font-size:var(--canon-font-size-2);line-height:140%}.canon-Text[data-variant=label]{font-size:var(--canon-font-size-1);line-height:140%}.canon-Text[data-weight=regular]{font-weight:var(--canon-font-weight-regular)}.canon-Text[data-weight=bold]{font-weight:var(--canon-font-weight-bold)}.canon-Text[data-color=primary]{color:var(--canon-fg-primary)}.canon-Text[data-color=secondary]{color:var(--canon-fg-secondary)}.canon-Text[data-color=danger]{color:var(--canon-fg-danger)}.canon-Text[data-color=warning]{color:var(--canon-fg-warning)}.canon-Text[data-color=success]{color:var(--canon-fg-success)}.canon-Text[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.canon-TextField{font-family:var(--canon-font-regular);flex-direction:column;width:100%;display:flex}.canon-InputWrapper{position:relative;&[data-size=small] .canon-Input{height:2rem}&[data-size=medium] .canon-Input{height:2.5rem}&[data-size=small] .canon-Input[data-icon]{padding-left:var(--canon-space-8)}&[data-size=medium] .canon-Input[data-icon]{padding-left:var(--canon-space-9)}}.canon-InputIcon{left:var(--canon-space-3);margin-right:var(--canon-space-1);color:var(--canon-fg-primary);flex-shrink:0;position:absolute;top:50%;transform:translateY(-50%);&[data-size=small],&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium],&[data-size=medium] svg{width:1.25rem;height:1.25rem}}.canon-Input{padding:0 var(--canon-space-3);border-radius:var(--canon-radius-3);border:1px solid var(--canon-border);background-color:var(--canon-bg-surface-1);font-size:var(--canon-font-size-3);font-family:var(--canon-font-regular);font-weight:var(--canon-font-weight-regular);color:var(--canon-fg-primary);width:100%;height:100%;cursor:inherit;align-items:center;transition:border-color .2s ease-in-out,outline-color .2s ease-in-out;display:flex;&::-webkit-search-cancel-button,&::-webkit-search-decoration{-webkit-appearance:none}&::placeholder{color:var(--canon-fg-secondary)}&[data-focused]{outline-color:var(--canon-border-pressed);outline-width:0}&[data-hovered]{border-color:var(--canon-border-hover)}&[data-focused]{border-color:var(--canon-border-pressed);outline-width:0}&[data-invalid]{border-color:var(--canon-fg-danger)}&[data-disabled]{opacity:.5;cursor:not-allowed;border:1px solid var(--canon-border-disabled)}}.canon-SearchField[data-empty] .canon-InputClear{display:none}.canon-InputClear{cursor:pointer;color:var(--canon-fg-secondary);background-color:#0000;border:none;justify-content:center;align-items:center;margin:0;padding:0;transition:color .2s ease-in-out;display:flex;position:absolute;top:0;bottom:0;right:0}.canon-InputClear:hover{color:var(--canon-fg-primary)}.canon-InputClear[data-size=small]{width:2rem;height:2rem}.canon-InputClear[data-size=medium]{width:2.5rem;height:2.5rem}.canon-InputClear svg{width:1rem;height:1rem}.canon-TooltipPopup{box-sizing:border-box;transform-origin:var(--transform-origin);background-color:canvas;background-color:var(--canon-bg-surface-1);color:var(--canon-fg-primary);outline:1px solid var(--canon-border);box-shadow:0 10px 15px -3px var(--canon-border),0 4px 6px -4px var(--canon-border);border-radius:.375rem;flex-direction:column;padding:.25rem .5rem;font-size:.875rem;line-height:1.25rem;transition:transform .15s,opacity .15s;display:flex;&[data-starting-style],&[data-ending-style]{opacity:0;transform:scale(.9)}&[data-instant]{transition-duration:0s}}.canon-TooltipArrow{display:flex;&[data-side=top]{bottom:-8px;rotate:180deg}&[data-side=bottom]{top:-8px;rotate:none}&[data-side=left]{right:-13px;rotate:90deg}&[data-side=right]{left:-13px;rotate:-90deg}}.canon-TooltipArrow-fill{fill:var(--canon-bg-surface-1)}.canon-TooltipArrow-outer-stroke{@media (prefers-color-scheme:light){&{fill:var(--canon-border)}}}.canon-ScrollAreaRoot{box-sizing:border-box;width:24rem;max-width:calc(100vw - 8rem);height:8.5rem}.canon-ScrollAreaViewport{overscroll-behavior:contain;height:100%}.canon-ScrollAreaContent{padding-block:.75rem;flex-direction:column;gap:1rem;padding-left:1rem;padding-right:1.5rem;display:flex}.canon-ScrollAreaScrollbar{background-color:var(--canon-scrollbar);opacity:0;border-radius:.375rem;justify-content:center;width:.25rem;margin:.5rem;transition:opacity .15s .3s;display:flex;&[data-hovering],&[data-scrolling]{opacity:1;transition-duration:75ms;transition-delay:0s}&:before{content:"";width:1.25rem;height:100%;position:absolute}}.canon-ScrollAreaThumb{border-radius:inherit;background-color:var(--canon-scrollbar-thumb);width:100%}.canon-Select{font-family:var(--canon-font-regular);flex-direction:column;width:100%;display:flex}.canon-SelectLabel{font-size:var(--canon-font-size-2);font-weight:var(--canon-font-weight-regular);color:var(--canon-fg-primary);margin-bottom:var(--canon-space-1_5);cursor:pointer}.canon-SelectLabel[data-disabled]{cursor:default}.canon-SelectDescription{font-size:var(--canon-font-size-2);font-weight:var(--canon-font-weight-regular);color:var(--canon-fg-secondary);padding-top:var(--canon-space-1_5);margin:0}.canon-SelectError{font-size:var(--canon-font-size-2);font-weight:var(--canon-font-weight-regular);color:var(--canon-fg-danger);padding-top:var(--canon-space-1_5);margin:0}.canon-SelectTrigger{box-sizing:border-box;border-radius:var(--canon-radius-3);border:1px solid var(--canon-border);padding:0 var(--canon-space-4);background-color:var(--canon-bg-surface-1);font-size:var(--canon-font-size-3);font-family:var(--canon-font-regular);font-weight:var(--canon-font-weight-regular);color:var(--canon-fg-primary);cursor:pointer;justify-content:space-between;align-items:center;gap:var(--canon-space-2);width:100%;transition:border-color .2s ease-in-out,outline-color .2s ease-in-out;display:flex}.canon-SelectTrigger::placeholder{color:var(--canon-fg-secondary)}.canon-SelectTrigger:hover{border-color:var(--canon-border-hover)}.canon-SelectTrigger:focus-visible{border-color:var(--canon-border-pressed);outline:0}.canon-SelectTrigger[data-invalid]{border-color:var(--canon-fg-danger)}.canon-SelectTrigger[data-invalid]:hover,.canon-SelectTrigger[data-invalid]:focus-visible{border-width:2px}.canon-SelectTrigger[data-disabled]{cursor:not-allowed;border-color:var(--canon-border-disabled);color:var(--canon-fg-disabled)}.canon-SelectTrigger[data-size=small]{height:2rem}.canon-SelectTrigger[data-size=medium]{height:3rem}.canon-SelectIcon{margin-left:var(--canon-space-5);transition:transform .2s}.canon-SelectTrigger[data-popup-open] .canon-SelectIcon{transform:rotate(180deg)}.canon-SelectPopup{box-sizing:border-box;max-height:var(--available-height);background-color:var(--canon-bg-surface-1);border:1px solid var(--canon-border);border-radius:var(--canon-radius-3);padding-block:var(--canon-space-1);z-index:1;transform-origin:var(--transform-origin);outline:0;transition:transform .15s,opacity .15s;overflow-y:auto;box-shadow:0 4px 12px #0003}.canon-SelectPopup[data-starting-style],.canon-SelectPopup[data-ending-style]{opacity:0;transform:scale(.9)}.canon-SelectItem{width:var(--anchor-width);padding-block:var(--canon-space-2);padding-inline:var(--canon-space-4);color:var(--canon-fg-primary);border-radius:var(--canon-radius-3);cursor:pointer;user-select:none;font-size:var(--canon-font-size-3);align-items:center;gap:var(--canon-space-2);outline:none;grid-template-columns:1rem 1fr;grid-template-areas:"icon text";display:grid;position:relative}.canon-SelectItem[data-highlighted]{z-index:0;color:var(--canon-fg-primary);position:relative}.canon-SelectItem[data-highlighted]:before{content:"";z-index:-1;background-color:var(--canon-bg-tint-hover);border-radius:.25rem;position:absolute;inset-block:0;inset-inline:.25rem}.canon-SelectItem[data-disabled]{cursor:not-allowed;color:var(--canon-fg-disabled)}.canon-SelectItemIndicator{grid-area:icon;justify-content:center;align-items:center;display:flex}.canon-SelectItemText{flex:1;grid-area:text}.canon-SelectRequired{color:var(--canon-fg-secondary);font-size:var(--canon-font-size-2);font-weight:var(--canon-font-weight-regular);margin-left:var(--canon-space-1)}.canon-SelectIcon{justify-content:center;align-items:center;display:flex}.canon-SelectValue{text-overflow:ellipsis;white-space:nowrap;width:100%;overflow:hidden}.canon-Switch{align-items:center;gap:var(--canon-space-3);font-size:var(--canon-font-size-3);color:var(--canon-fg-primary);cursor:pointer;display:flex;position:relative;&[data-pressed] .canon-SwitchIndicator{&:before{background:var(--canon-fg-solid)}}&[data-selected]{& .canon-SwitchIndicator{background:var(--canon-bg-solid);&:before{background:var(--canon-fg-solid);transform:translate(100%)}}&[data-pressed]{& .indicator{background:var(--canon-gray-3)}}}&[data-focus-visible] .canon-SwitchIndicator{outline-offset:2px;outline:2px solid}}.canon-SwitchIndicator{background:var(--canon-gray-3);border:2px;border-radius:1.143rem;width:2rem;height:1.143rem;transition:all .2s;&:before{content:"";background:var(--canon-fg-solid);border-radius:16px;width:.857rem;height:.857rem;margin:.143rem;transition:all .2s;display:block}} \ No newline at end of file diff --git a/canon-docs/public/theme-spotify.css b/canon-docs/public/theme-spotify.css new file mode 100644 index 0000000000..8e650bb7c9 --- /dev/null +++ b/canon-docs/public/theme-spotify.css @@ -0,0 +1 @@ +@font-face{font-family:CircularSp;font-weight:700;font-display:swap;unicode-range:U+0,U+D,U+20-7E,U+A0-17E,U+18F,U+192,U+1A0-1A1,U+1AF-1B0,U+1B5-1B6,U+1C4-1C6,U+1F1-1F3,U+1FA-1FF,U+218-21B,U+237,U+259,U+2BB-2BC,U+2C6-2C7,U+2C9,U+2D8-2DD,U+300-301,U+303,U+309,U+323,U+394,U+3A9,U+3BC,U+3C0,U+1E80-1E85,U+1E8A-1E8B,U+1EA0-1EF9,U+1FD6,U+2007-2008,U+200B,U+2010-2011,U+2013-2014,U+2018-201A,U+201C-201E,U+2020-2022,U+2026,U+2030,U+2032-2033,U+2039-203A,U+2042,U+2044,U+2051,U+2070,U+2074-2079,U+2080-2089,U+20AB-20AC,U+2113,U+2117,U+2122,U+2126,U+2160-2169,U+216C-216F,U+2190-2193,U+2196-2199,U+21A9,U+21B0-21B5,U+21C6,U+2202,U+2206,U+220F,U+2211-2212,U+2215,U+2219-221A,U+221E,U+222B,U+2248,U+2260,U+2264-2265,U+22C5,U+24C5,U+25A0-25A1,U+25AF,U+25B2-25B3,U+25CA-25CB,U+25CF,U+262E,U+2713,U+2715,U+2780-2788,U+E000,U+E002,U+F6C3,U+FB00-FB04,U+FEFF,U+FF0C,U+FF0E,U+FF1A-FF1B,U+FFFF;src:url(https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2)format("woff2"),url(https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff)format("woff")}[data-theme=dark][data-theme-name=spotify]{--canon-font-text:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--canon-font-title:CircularSpTitle,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--canon-font-regular:CircularSp,CircularSp-Arab,CircularSp-Hebr,CircularSp-Cyrl,CircularSp-Grek,CircularSp-Deva;--canon-gray-1:#191919;--canon-gray-2:#242424;--canon-gray-3:#373737;--canon-gray-4:#464646;--canon-gray-5:#575757;--canon-gray-6:#7b7b7b;--canon-gray-7:#9e9e9e;--canon-gray-8:#b4b4b4;--canon-bg:#000;--canon-bg-surface-1:#191919;--canon-bg-surface-2:#242424;--canon-bg-solid:#1ed760;--canon-bg-solid-hover:#3be477;--canon-bg-solid-pressed:#1abc54;--canon-bg-solid-disabled:#0f6c30;--canon-bg-tint:#242424;--canon-bg-tint-hover:#202020;--canon-bg-tint-pressed:#292929;--canon-bg-tint-disabled:#fffc;--canon-bg-danger:#3b1219;--canon-bg-warning:#302008;--canon-bg-success:#132d21;--canon-bg-underline:#d16ecb;--canon-fg-primary:#fff;--canon-fg-secondary:#9e9e9e;--canon-fg-link:#fff;--canon-fg-link-hover:#fff;--canon-fg-disabled:#575757;--canon-fg-solid:#000;--canon-fg-solid-disabled:#083618;--canon-fg-tint:#fff;--canon-fg-tint-disabled:#575757;--canon-fg-danger:#e22b2b;--canon-fg-warning:#e36d05;--canon-fg-success:#1db954;--canon-border:var(--canon-gray-3);--canon-border-hover:#fff6;--canon-border-pressed:#ffffff80;--canon-border-disabled:#fff3;--canon-border-danger:#f87a7a;--canon-border-warning:#e36d05;--canon-border-success:#53db83;--canon-ring:#fff3}#root{padding-top:var(--header-height)}.canon-Button,.canon-IconButton{border-radius:var(--canon-radius-3);transition:background-color .2s ease-in-out,color .2s ease-in-out,box-shadow .2s ease-in-out}.canon-Button--variant-primary,.canon-IconButton--variant-primary{&:hover{box-shadow:inset 0 0 0 1px var(--canon-bg-solid);color:var(--canon-fg-primary);background-color:#0000}&:active{background-color:#1ed7601a}&:disabled{background-color:var(--canon-bg-solid-disabled);color:var(--canon-fg-solid-disabled);box-shadow:none}}.canon-Button[data-size=medium],.canon-Button[data-size=small]{padding-inline:var(--canon-space-3)}.canon-MenuTrigger{all:unset;display:inline-flex}.canon-MenuPopup{box-sizing:border-box;max-width:21.25rem}.canon-MenuSubmenuTrigger,.canon-MenuItem{height:auto;min-height:2rem}.canon-Text{font-family:var(--canon-font-text)}.canon-Heading{font-family:var(--canon-font-title)}.canon-TableRow{border-radius:var(--canon-radius-4);border:none}.canon-TableRow:hover td:first-child{border-top-left-radius:var(--canon-radius-2);border-bottom-left-radius:var(--canon-radius-2)}.canon-TableRow:hover td:last-child{border-top-right-radius:var(--canon-radius-2);border-bottom-right-radius:var(--canon-radius-2)}.canon-TableBody:before,.canon-TableBody:after{line-height:var(--canon-space-1);content:"‌";display:block}.canon-TableHeader .canon-TableRow{border-bottom:1px solid var(--canon-border)}.canon-TableHead{font-size:var(--canon-font-size-2);color:var(--canon-fg-secondary);font-weight:var(--canon-font-weight-regular)}.canon-ScrollAreaRoot{width:100%;height:unset}.canon-TabsIndicator{background-color:var(--canon-bg-underline)}.canon-TabsTab[data-selected]{background:radial-gradient(at bottom,#d16ecb40 0%,#0000 95%)} \ No newline at end of file diff --git a/canon-docs/scripts/build-css.js b/canon-docs/scripts/build-css.js deleted file mode 100644 index dd9775150f..0000000000 --- a/canon-docs/scripts/build-css.js +++ /dev/null @@ -1,39 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const { bundle } = require('lightningcss'); - -const source = '../../packages/canon/src/css'; -const destination = '../public'; - -const source1 = path.join(__dirname, `${source}/core.css`); -const destination1 = path.join(__dirname, `${destination}/core.css`); -const source2 = path.join(__dirname, `${source}/components.css`); -const destination2 = path.join(__dirname, `${destination}/components.css`); - -// Function to bundle and copy the CSS file -const bundleAndCopyFile = async (source, destination) => { - try { - const result = await bundle({ - filename: source, - minify: true, - }); - - fs.writeFileSync(destination, result.code); - console.log('File bundled and copied successfully!'); - } catch (err) { - console.error('Error bundling file:', err); - } -}; - -// Initial bundle and copy -Promise.all([ - bundleAndCopyFile(source1, destination1), - bundleAndCopyFile(source2, destination2), -]) - .then(() => { - // Add an empty line after all operations are complete - It looks better in the terminal :) - console.log(''); - }) - .catch(err => { - console.error('Error in processing files:', err); - }); diff --git a/canon-docs/scripts/sync-css.js b/canon-docs/scripts/sync-css.js new file mode 100644 index 0000000000..fcafb46297 --- /dev/null +++ b/canon-docs/scripts/sync-css.js @@ -0,0 +1,149 @@ +const fs = require('fs'); +const path = require('path'); +const { bundle } = require('lightningcss'); +const chokidar = require('chokidar'); + +// Configuration +const config = { + canonPath: '../../packages/canon', + publicPath: '../public', + files: [ + { + source: 'css/styles.css', + destination: 'theme-backstage.css', + name: 'Main Styles', + }, + { + source: '.storybook/themes/spotify.css', + destination: 'theme-spotify.css', + name: 'Spotify Theme', + }, + ], +}; + +class CSSSync { + constructor() { + this.canonPath = path.resolve(__dirname, config.canonPath); + this.publicPath = path.resolve(__dirname, config.publicPath); + this.isWatching = process.argv.includes('--watch'); + } + + async syncFile(fileConfig) { + const sourcePath = path.join(this.canonPath, fileConfig.source); + const destPath = path.join(this.publicPath, fileConfig.destination); + + try { + // Check if source file exists + if (!fs.existsSync(sourcePath)) { + console.warn(`⚠️ Source file not found: ${sourcePath}`); + return false; + } + + // Ensure destination directory exists + fs.mkdirSync(path.dirname(destPath), { recursive: true }); + + // Bundle and optimize CSS + const result = await bundle({ + filename: sourcePath, + minify: true, + }); + + // Write to destination + fs.writeFileSync(destPath, result.code); + + console.log( + `✅ ${fileConfig.name}: ${fileConfig.source} → ${fileConfig.destination}`, + ); + return true; + } catch (error) { + console.error(`❌ Error syncing ${fileConfig.name}:`, error.message); + return false; + } + } + + async syncAll() { + console.log('🔄 Syncing CSS files...\n'); + + let successCount = 0; + for (const fileConfig of config.files) { + if (await this.syncFile(fileConfig)) { + successCount++; + } + } + + console.log( + `\n✨ Synced ${successCount}/${config.files.length} CSS files successfully!`, + ); + + if (successCount > 0) { + console.log('\n📁 Available CSS files in public/:'); + config.files.forEach(file => { + const destPath = path.join(this.publicPath, file.destination); + if (fs.existsSync(destPath)) { + const stats = fs.statSync(destPath); + const size = (stats.size / 1024).toFixed(2); + console.log(` • ${file.destination} (${size} KB)`); + } + }); + } + } + + startWatching() { + console.log('👀 Watching for CSS changes...\n'); + + // Watch all source files + const watchPaths = config.files.map(file => + path.join(this.canonPath, file.source), + ); + + const watcher = chokidar.watch(watchPaths, { + ignored: /node_modules/, + persistent: true, + }); + + watcher.on('change', async filePath => { + console.log( + `\n🔄 Change detected: ${path.relative(this.canonPath, filePath)}`, + ); + + // Find which file changed and sync it + const fileConfig = config.files.find(file => + filePath.endsWith(file.source.replace(/\//g, path.sep)), + ); + + if (fileConfig) { + await this.syncFile(fileConfig); + } + }); + + watcher.on('error', error => console.error('❌ Watch error:', error)); + + // Handle process termination + process.on('SIGINT', () => { + console.log('\n👋 Stopping CSS sync...'); + watcher.close(); + process.exit(0); + }); + } + + async run() { + console.log('🎨 Canon CSS Sync Tool\n'); + console.log(`📂 Canon path: ${this.canonPath}`); + console.log(`📂 Public path: ${this.publicPath}\n`); + + // Initial sync + await this.syncAll(); + + // Watch for changes if requested + if (this.isWatching) { + this.startWatching(); + } + } +} + +// Run the sync tool +const cssSync = new CSSSync(); +cssSync.run().catch(error => { + console.error('❌ CSS Sync failed:', error); + process.exit(1); +}); diff --git a/canon-docs/src/app/(docs)/changelog/page.mdx b/canon-docs/src/app/(docs)/changelog/page.mdx new file mode 100644 index 0000000000..7cc0b2bf3e --- /dev/null +++ b/canon-docs/src/app/(docs)/changelog/page.mdx @@ -0,0 +1,13 @@ +import { Changelog } from '@/components/Changelog'; + +# Changelog + + + +## Version 0.1.0 + +We're excited to share the initial release of Canon 💚 In this first alpha version, +you'll find the foundation of our design system: a set of versatile layout components +and a handful of essential atomic elements to help you get started. While Canon is +still in its early stages, it's ready for exploration and we'd love for you to give +it a try and share your feedback. diff --git a/canon-docs/src/app/(docs)/components/[slug]/page.tsx b/canon-docs/src/app/(docs)/components/[slug]/page.tsx new file mode 100644 index 0000000000..d6f98c8f93 --- /dev/null +++ b/canon-docs/src/app/(docs)/components/[slug]/page.tsx @@ -0,0 +1,25 @@ +import { components, layoutComponents } from '@/utils/data'; + +export default async function Page({ + params, +}: { + params: Promise<{ slug: string }>; +}) { + const { slug } = await params; + + const { default: Component } = await import( + `@/content/components/${slug}.mdx` + ); + + return ; +} + +export function generateStaticParams() { + const list = [...components, ...layoutComponents]; + + return list.map(component => ({ + slug: component.slug, + })); +} + +export const dynamicParams = false; diff --git a/canon-docs/src/app/(docs)/components/avatar/page.mdx b/canon-docs/src/app/(docs)/components/avatar/page.mdx deleted file mode 100644 index b46caf8d62..0000000000 --- a/canon-docs/src/app/(docs)/components/avatar/page.mdx +++ /dev/null @@ -1,75 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { AvatarSnippet } from '@/snippets/stories-snippets'; -import { avatarPropDefs } from './props'; - -# Avatar - -An avatar component with a fallback for initials. - -} - code={``} -/> - - - - Usage - Theming - - - `} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - - `canon-AvatarRoot` - - `canon-AvatarRoot[data-size='small']` - - `canon-AvatarRoot[data-size='medium']` - - `canon-AvatarRoot[data-size='large']` - - `canon-AvatarImage` - - `canon-AvatarFallback` - - - -## API reference - - - -## Examples - -### Sizes - -Avatar sizes can be set using the `size` prop. - -} - code={` - - - - `} -/> - -### Fallback - -If the image is not available, the avatar will show the initials of the name. - -} - code={``} -/> diff --git a/canon-docs/src/app/(docs)/components/avatar/props.ts b/canon-docs/src/app/(docs)/components/avatar/props.ts deleted file mode 100644 index e86c67a41e..0000000000 --- a/canon-docs/src/app/(docs)/components/avatar/props.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { classNamePropDefs, stylePropDefs } from '@/utils/propDefs'; -import type { PropDef } from '@/utils/propDefs'; - -export const avatarPropDefs: Record = { - src: { - type: 'string', - }, - name: { - type: 'string', - }, - size: { - type: 'enum', - values: ['small', 'medium', 'large'], - default: 'medium', - responsive: true, - }, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/box/props.ts b/canon-docs/src/app/(docs)/components/box/props.ts deleted file mode 100644 index f3e38984dd..0000000000 --- a/canon-docs/src/app/(docs)/components/box/props.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { - classNamePropDefs, - displayPropDefs, - heightPropDefs, - positionPropDefs, - stylePropDefs, - widthPropDefs, -} from '../../../../utils/propDefs'; -import type { PropDef } from '../../../../utils/propDefs'; - -export const boxPropDefs: Record = { - as: { - type: 'enum', - values: ['div', 'span'], - default: 'div', - responsive: true, - }, - ...widthPropDefs, - ...heightPropDefs, - ...positionPropDefs, - ...displayPropDefs, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/button/page.mdx b/canon-docs/src/app/(docs)/components/button/page.mdx deleted file mode 100644 index e1ecee8920..0000000000 --- a/canon-docs/src/app/(docs)/components/button/page.mdx +++ /dev/null @@ -1,136 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { ButtonSnippet } from '@/snippets/stories-snippets'; -import { buttonVariants } from '@/snippets/code-snippets'; -import { buttonPropDefs } from './props'; - -# Button - -A button component that can be used to trigger actions. - -} - code={` - - - -`} -/> - - - - Usage - Theming - - - -`} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - `} - /> - - - - -## API reference - - - -## Examples - -### Variants - -Here's a view when buttons have different variants. - -} - code={buttonVariants} -/> - -### Sizes - -Here's a view when buttons have different sizes. - -} - code={` - - -`} -/> - -### With Icons - -Here's a view when buttons have icons. - -} - code={` - - - -`} -/> - -### Full width - -Here's a view when buttons are full width. - -} - code={` - -`} -/> - -### Disabled - -Here's a view when buttons are disabled. - -} - code={``} -/> - -### Responsive - -Here's a view when buttons are responsive. - - - Responsive Button - `} -/> diff --git a/canon-docs/src/app/(docs)/components/button/props.ts b/canon-docs/src/app/(docs)/components/button/props.ts deleted file mode 100644 index 813dcaa6f0..0000000000 --- a/canon-docs/src/app/(docs)/components/button/props.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs'; -import type { PropDef } from '../../../../utils/propDefs'; - -export const buttonPropDefs: Record = { - variant: { - type: 'enum', - values: ['primary', 'secondary'], - default: 'primary', - responsive: true, - }, - size: { - type: 'enum', - values: ['small', 'medium'], - default: 'medium', - responsive: true, - }, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/checkbox/page.mdx b/canon-docs/src/app/(docs)/components/checkbox/page.mdx deleted file mode 100644 index 413636dc9a..0000000000 --- a/canon-docs/src/app/(docs)/components/checkbox/page.mdx +++ /dev/null @@ -1,66 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { CheckboxSnippet } from '@/snippets/stories-snippets'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { BaseUI } from '@/components/HeadlessBanners/BaseUI'; -import { checkboxPropDefs } from './props'; - -# Checkbox - -A checkbox component that can be used to trigger actions. - -} - code={``} -/> - - - - Usage - Theming - - - -`} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - `} - /> - - - - -## API reference - - - - - -## Examples - -### All variants - -Here's a view when checkboxes have different variants. - -} - code={` - - - - - `} -/> diff --git a/canon-docs/src/app/(docs)/components/collapsible/page.mdx b/canon-docs/src/app/(docs)/components/collapsible/page.mdx deleted file mode 100644 index e013dff89c..0000000000 --- a/canon-docs/src/app/(docs)/components/collapsible/page.mdx +++ /dev/null @@ -1,113 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { CollapsibleSnippet } from '@/snippets/stories-snippets'; -import { - collapsibleRootPropDefs, - collapsibleTriggerPropDefs, - collapsiblePanelPropDefs, -} from './props'; - -# Collapsible - -An avatar component with a fallback for initials. - -} - code={` - ( - - )} /> - - - It's the edge of the world and all of Western civilization - The sun may rise in the East, at least it settled in a final location - It's understood that Hollywood sells Californication - - -`} -/> - - - - Usage - Theming - - - - ( - - )} /> - Your content -`} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - - `canon-CollapsibleRoot` - - `canon-CollapsibleTrigger` - - `canon-CollapsiblePanel` - - - -## API reference - -### Collapsible.Root - -Groups all parts of the collapsible. Renders a `
` element. - - - -### Collapsible.Trigger - -The trigger by default render a simple unstyled button. Because menus can be rendered in different ways, we recommend -using the `render` prop to render a custom trigger. - - - )} /> - - - It's the edge of the world and all of Western civilization - The sun may rise in the East, at least it settled in a final location - It's understood that Hollywood sells Californication - - -`} -/> diff --git a/canon-docs/src/app/(docs)/components/collapsible/props.ts b/canon-docs/src/app/(docs)/components/collapsible/props.ts deleted file mode 100644 index 02c62dc89e..0000000000 --- a/canon-docs/src/app/(docs)/components/collapsible/props.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { - classNamePropDefs, - stylePropDefs, - renderPropDefs, -} from '@/utils/propDefs'; -import type { PropDef } from '@/utils/propDefs'; - -export const collapsibleRootPropDefs: Record = { - defaultOpen: { - type: 'boolean', - default: 'false', - }, - open: { - type: 'boolean', - }, - onOpenChange: { - type: 'enum', - values: ['(open) => void'], - }, - ...renderPropDefs, - ...classNamePropDefs, - ...stylePropDefs, -}; - -export const collapsibleTriggerPropDefs: Record = { - ...renderPropDefs, - ...classNamePropDefs, - ...stylePropDefs, -}; - -export const collapsiblePanelPropDefs: Record = { - hiddenUntilFound: { - type: 'boolean', - default: 'false', - }, - keepMounted: { - type: 'boolean', - default: 'false', - }, - ...renderPropDefs, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/container/props.ts b/canon-docs/src/app/(docs)/components/container/props.ts deleted file mode 100644 index 4a3410ec12..0000000000 --- a/canon-docs/src/app/(docs)/components/container/props.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { - classNamePropDefs, - stylePropDefs, - gapPropDefs, -} from '../../../../utils/propDefs'; -import type { PropDef } from '../../../../utils/propDefs'; - -export const containerPropDefs: Record = { - ...gapPropDefs, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/flex/page.mdx b/canon-docs/src/app/(docs)/components/flex/page.mdx deleted file mode 100644 index 8150f3e3c5..0000000000 --- a/canon-docs/src/app/(docs)/components/flex/page.mdx +++ /dev/null @@ -1,83 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { - flexFAQ1, - flexSimple, - flexResponsive, - flexAlign, -} from '@/snippets/code-snippets'; -import { Snippet } from '@/components/Snippet'; -import { FlexSnippet } from '@/snippets/stories-snippets'; -import { flexPropDefs } from './props'; -import { spacingPropDefs } from '../../../../utils/propDefs'; - -# Flex - -This is the flex container component. It will help to define the number of -columns that will be used in the grid. You can also define the gap between the -columns. All values are responsive. - -} - code={` - - - -`} -/> - - - - Usage - - - -`} - /> - - - -## API reference - - - -The grid component also accepts all the spacing props from the Box component. - - - -## Common questions - -### Can I stack horizontally? - -The Flex component only allows for stacking elements vertically. If you want -to create a column layout, please use the Grid component. - - - -## Examples - -### Simple - -A simple example of how to use the Flex component. - - - -### Responsive - -The Flex component also supports responsive values, making it easy to create -responsive designs. - - - -### Align - -The Flex component also supports responsive alignment, making it easy to -create responsive designs. - - diff --git a/canon-docs/src/app/(docs)/components/flex/props.ts b/canon-docs/src/app/(docs)/components/flex/props.ts deleted file mode 100644 index 2268a6909d..0000000000 --- a/canon-docs/src/app/(docs)/components/flex/props.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { - PropDef, - childrenPropDefs, - classNamePropDefs, - stylePropDefs, -} from '../../../../utils/propDefs'; - -export const flexPropDefs: Record = { - align: { - type: 'enum', - values: ['start', 'center', 'end', 'baseline', 'stretch'], - responsive: true, - }, - direction: { - type: 'enum', - values: ['row', 'column', 'row-reverse', 'column-reverse'], - responsive: true, - }, - justify: { - type: 'enum', - values: ['start', 'center', 'end', 'between'], - responsive: true, - }, - ...childrenPropDefs, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/grid/props.ts b/canon-docs/src/app/(docs)/components/grid/props.ts deleted file mode 100644 index a9e8717fa1..0000000000 --- a/canon-docs/src/app/(docs)/components/grid/props.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { - PropDef, - childrenPropDefs, - classNamePropDefs, - stylePropDefs, -} from '../../../../utils/propDefs'; - -const columnsValues = [ - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - '10', - '11', - '12', -]; - -export const gridPropDefs: Record = { - columns: { - type: 'enum | string', - values: [...columnsValues, 'auto'], - responsive: true, - default: 'auto', - }, - ...childrenPropDefs, - ...classNamePropDefs, - ...stylePropDefs, -}; - -export const gridItemPropDefs: Record = { - colSpan: { - type: 'enum | string', - values: [...columnsValues, 'full'], - responsive: true, - }, - rowSpan: { - type: 'enum | string', - values: [...columnsValues, 'full'], - responsive: true, - }, - start: { - type: 'enum | string', - values: [...columnsValues, 'auto'], - responsive: true, - }, - end: { - type: 'enum | string', - values: [...columnsValues, 'auto'], - responsive: true, - }, - ...childrenPropDefs, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/heading/page.mdx b/canon-docs/src/app/(docs)/components/heading/page.mdx deleted file mode 100644 index e09bae9945..0000000000 --- a/canon-docs/src/app/(docs)/components/heading/page.mdx +++ /dev/null @@ -1,90 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { HeadingSnippet } from '@/snippets/stories-snippets'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { headingPropDefs } from './props'; - -# Heading - -Headings are used to structure the content of your page. - -} - code={`Hello World!`} -/> - - - - Usage - Theming - - - -`} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - `} - /> - - - - -## API reference - - - -## Examples - -### All variants - -The `Heading` component has a `variant` prop that can be used to change the -appearance of the heading. - -} - code={` - Display - Title 1 - Title 2 - Title 3 - Title 4 -`} -/> - -### Truncate - -The `Heading` component has a `truncate` prop that can be used to truncate the -heading. - -} - code={` - A man looks at a painting in a museum and says, “Brothers and sisters I - have none, but that man's father is my father's son.” Who is - in the painting? - `} -/> - -### Responsive - -You can also use the `variant` prop to change the appearance of the text based -on the screen size. - - - Responsive heading - `} -/> diff --git a/canon-docs/src/app/(docs)/components/heading/props.ts b/canon-docs/src/app/(docs)/components/heading/props.ts deleted file mode 100644 index 6d62d2dee1..0000000000 --- a/canon-docs/src/app/(docs)/components/heading/props.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs'; -import type { PropDef } from '../../../../utils/propDefs'; - -export const headingPropDefs: Record = { - variant: { - type: 'enum', - values: ['display', 'title1', 'title2', 'title3', 'title4', 'title5'], - responsive: true, - }, - children: { - type: 'enum', - values: ['ReactNode'], - responsive: false, - }, - truncate: { - type: 'boolean', - default: 'false', - }, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/icon-button/page.mdx b/canon-docs/src/app/(docs)/components/icon-button/page.mdx deleted file mode 100644 index 60530ec9ea..0000000000 --- a/canon-docs/src/app/(docs)/components/icon-button/page.mdx +++ /dev/null @@ -1,97 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { IconButtonSnippet } from '@/snippets/stories-snippets'; -import { iconButtonVariants } from '@/snippets/code-snippets'; -import { iconButtonPropDefs } from './props'; - -# Icon Button - -A button component with a single icon that can be used to trigger actions. - -} - code={` - - - `} -/> - - - - Usage - Theming - - - -`} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - `} - /> - - - - -## API reference - - - -## Examples - -### Variants - -Here's a view when buttons have different variants. - -} - code={iconButtonVariants} -/> - -### Sizes - -Here's a view when buttons have different sizes. - -} - code={` - - -`} -/> - -### Disabled - -Here's a view when buttons are disabled. - -} - code={``} -/> - -### Responsive - -Here's a view when buttons are responsive. - -`} -/> diff --git a/canon-docs/src/app/(docs)/components/icon-button/props.ts b/canon-docs/src/app/(docs)/components/icon-button/props.ts deleted file mode 100644 index bcb1580247..0000000000 --- a/canon-docs/src/app/(docs)/components/icon-button/props.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { classNamePropDefs, stylePropDefs } from '../../../../utils/propDefs'; -import type { PropDef } from '../../../../utils/propDefs'; - -export const iconButtonPropDefs: Record = { - variant: { - type: 'enum', - values: ['primary', 'secondary'], - default: 'primary', - responsive: true, - }, - size: { - type: 'enum', - values: ['small', 'medium'], - default: 'medium', - responsive: true, - }, - icon: { type: 'enum', values: 'icon', responsive: false }, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/icon/page.mdx b/canon-docs/src/app/(docs)/components/icon/page.mdx deleted file mode 100644 index 66be460d13..0000000000 --- a/canon-docs/src/app/(docs)/components/icon/page.mdx +++ /dev/null @@ -1,44 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { IconSnippet } from '@/snippets/stories-snippets'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { iconPropDefs } from './props'; - -# Icon - -Icons are used to represent an action or a state. - -} - code={``} -/> - - - - Usage - Theming - - - -`} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - `} - /> - - - - -## API reference - - diff --git a/canon-docs/src/app/(docs)/components/link/page.mdx b/canon-docs/src/app/(docs)/components/link/page.mdx deleted file mode 100644 index 64a3261590..0000000000 --- a/canon-docs/src/app/(docs)/components/link/page.mdx +++ /dev/null @@ -1,84 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { - MenuSnippet, - ButtonSnippet, - LinkSnippet, -} from '@/snippets/stories-snippets'; -import { linkPropDefs } from './props'; - -# Link - -A link component that renders a `` element. - -} - code={`Sign up for Backstage`} -/> - - - - Usage - Theming - - - Sign up for Backstage`} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - - `canon-Link` - - `canon-Link[data-variant='body']` - - `canon-Link[data-variant='subtitle']` - - `canon-Link[data-variant='caption']` - - `canon-Link[data-variant='label']` - - `canon-Link[data-weight='regular']` - - `canon-Link[data-weight='bold']` - - - -## API reference - - - -## Examples - -### Variants - -Here's a view when links have different variants. - -} - code={` - - - - - `} -/> - -### Weights - -Here's a view when links have different weights. - -} - code={` - - - `} -/> diff --git a/canon-docs/src/app/(docs)/components/link/props.ts b/canon-docs/src/app/(docs)/components/link/props.ts deleted file mode 100644 index 83507c5594..0000000000 --- a/canon-docs/src/app/(docs)/components/link/props.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { classNamePropDefs, stylePropDefs } from '@/utils/propDefs'; -import type { PropDef } from '@/utils/propDefs'; - -export const linkPropDefs: Record = { - to: { - type: 'string', - }, - variant: { - type: 'enum', - values: ['subtitle', 'body', 'caption', 'label'], - default: 'body', - responsive: true, - }, - weight: { - type: 'enum', - values: ['regular', 'bold'], - default: 'regular', - responsive: true, - }, - ...classNamePropDefs, - ...stylePropDefs, -}; diff --git a/canon-docs/src/app/(docs)/components/menu/page.mdx b/canon-docs/src/app/(docs)/components/menu/page.mdx deleted file mode 100644 index 524db26cd1..0000000000 --- a/canon-docs/src/app/(docs)/components/menu/page.mdx +++ /dev/null @@ -1,202 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { MenuSnippet } from '@/snippets/stories-snippets'; -import { BaseUI } from '@/components/HeadlessBanners/BaseUI'; -import { - menuRootPropDefs, - menuTriggerPropDefs, - menuPositionerPropDefs, - menuItemPropDefs, -} from './props'; - -# Menu - -A list of actions in a dropdown, enhanced with keyboard navigation. - -} - code={` - ( - - )} - /> - - - - Settings - Invite new members - Download app - Log out - - - - `} -/> - - - - Usage - Theming - - - - - - - - - - - - `} - /> - - - We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with - your brand. For additional flexibility, you can use the provided class names for each element listed below. - - `canon-MenuTrigger` - - `canon-MenuBackdrop` - - `canon-MenuPositioner` - - `canon-MenuPopup` - - `canon-MenuArrow` - - `canon-MenuItem` - - `canon-MenuGroup` - - `canon-MenuGroupLabel` - - `canon-MenuRadioGroup` - - `canon-MenuRadioItem` - - `canon-MenuRadioItemIndicator` - - `canon-MenuCheckboxItem` - - `canon-MenuCheckboxItemIndicator` - - `canon-MenuSubmenuTrigger` - - `canon-MenuSeparator` - - - -## API reference - - - -### Menu.Root - -Groups all parts of the menu. Doesn't render its own HTML element. - - - -### Menu.Trigger - -The trigger by default render a simple unstyled button. Because menus can be rendered in different ways, we recommend -using the `render` prop to render a custom trigger. - - - )} - /> - - - - Settings - Invite new members - Download app - Log out - - - - `} -/> - -### Nested navigation - -You can nest menus to create a more complex navigation structure. - -} - code={` ( - - )} - /> - - - - Settings - Invite new members - Download app - Log out - - Submenu - - - - Submenu Item 1 - Submenu Item 2 - Submenu Item 3 - - - - - - - `} -/> diff --git a/canon-docs/src/app/(docs)/components/select/page.mdx b/canon-docs/src/app/(docs)/components/select/page.mdx deleted file mode 100644 index 4399f62235..0000000000 --- a/canon-docs/src/app/(docs)/components/select/page.mdx +++ /dev/null @@ -1,128 +0,0 @@ -import { PropsTable } from '@/components/PropsTable'; -import { Snippet } from '@/components/Snippet'; -import { Tabs } from '@/components/Tabs'; -import { CodeBlock } from '@/components/CodeBlock'; -import { SelectSnippet } from '@/snippets/stories-snippets'; -import { selectPropDefs } from './props'; - -# Select - -A common form component for choosing a predefined value in a dropdown menu. - -} - code={``} -/> - -### Sizes - -Here's a view when the selects have different sizes. - -} - code={` - - `} -/> - -### Disabled - -Here's a view when the select is disabled. - -} - code={``; + +export const selectDefaultSnippet = ``; + +export const selectSizesSnippet = ` + +`; + +export const selectDisabledSnippet = ``; diff --git a/canon-docs/src/content/components/switch.mdx b/canon-docs/src/content/components/switch.mdx new file mode 100644 index 0000000000..068ec96217 --- /dev/null +++ b/canon-docs/src/content/components/switch.mdx @@ -0,0 +1,41 @@ +import { PropsTable } from '@/components/PropsTable'; +import { Snippet } from '@/components/Snippet'; +import { CodeBlock } from '@/components/CodeBlock'; +import { SwitchSnippet } from '@/snippets/stories-snippets'; +import { switchPropDefs, snippetUsage } from './switch.props'; +import { ComponentInfos } from '@/components/ComponentInfos'; + +# Switch + +A control that indicates whether a setting is on or off. + +} + code={``} +/> + + + +## API reference + + + +## Examples + +### Disabled + +A switch can be disabled using the `isDisabled` prop. + +} + code={``} +/> diff --git a/canon-docs/src/content/components/switch.props.ts b/canon-docs/src/content/components/switch.props.ts new file mode 100644 index 0000000000..ddbca4e049 --- /dev/null +++ b/canon-docs/src/content/components/switch.props.ts @@ -0,0 +1,71 @@ +import { classNamePropDefs, stylePropDefs } from '@/utils/propDefs'; +import type { PropDef } from '@/utils/propDefs'; + +export const switchPropDefs: Record = { + autoFocus: { + type: 'boolean', + }, + defaultSelected: { + type: 'boolean', + }, + ...classNamePropDefs, + isDisabled: { + type: 'boolean', + }, + isReadOnly: { + type: 'boolean', + }, + isSelected: { + type: 'boolean', + }, + label: { + type: 'string', + }, + name: { + type: 'string', + }, + onChange: { + type: 'enum', + values: ['(isSelected: boolean) => void'], + }, + onFocus: { + type: 'enum', + values: ['(e: FocusEvent) => void'], + }, + onBlur: { + type: 'enum', + values: ['(e: FocusEvent) => void'], + }, + onFocusChange: { + type: 'enum', + values: ['(isFocused: boolean) => void'], + }, + onKeyDown: { + type: 'enum', + values: ['(e: KeyboardEvent) => void'], + }, + onKeyUp: { + type: 'enum', + values: ['(e: KeyboardEvent) => void'], + }, + onHoverStart: { + type: 'enum', + values: ['(e: HoverEvent) => void'], + }, + onHoverEnd: { + type: 'enum', + values: ['(e: HoverEvent) => void'], + }, + onHoverChange: { + type: 'enum', + values: ['(isHovered: boolean) => void'], + }, + ...stylePropDefs, + value: { + type: 'string', + }, +}; + +export const snippetUsage = `import { Switch } from '@backstage/canon'; + +`; diff --git a/canon-docs/src/app/(docs)/components/table/page.mdx b/canon-docs/src/content/components/table.mdx similarity index 100% rename from canon-docs/src/app/(docs)/components/table/page.mdx rename to canon-docs/src/content/components/table.mdx diff --git a/canon-docs/src/content/components/tabs.mdx b/canon-docs/src/content/components/tabs.mdx new file mode 100644 index 0000000000..85cfa34af2 --- /dev/null +++ b/canon-docs/src/content/components/tabs.mdx @@ -0,0 +1,61 @@ +import { PropsTable } from '@/components/PropsTable'; +import { TabsSnippet } from '@/snippets/stories-snippets'; +import { Snippet } from '@/components/Snippet'; +import { CodeBlock } from '@/components/CodeBlock'; +import { + tabsRootPropDefs, + tabsListPropDefs, + tabsTabPropDefs, + tabsPanelPropDefs, + tabsUsageSnippet, + tabsDefaultSnippet, +} from './tabs.props'; +import { ComponentInfos } from '@/components/ComponentInfos'; + +# Tabs + +A component for toggling between related panels on the same page. + +} + code={tabsDefaultSnippet} +/> + + + +## API reference + +### Tabs.Root + +Groups the tabs and the corresponding panels. Renders a `
` element. + + + +### Tabs.List + +Groups the individual tab buttons. Renders a `
` element. + + + +### Tabs.Tab + +An individual interactive tab button that toggles the corresponding panel. Renders a ` - - - -`; - -export const iconButtonVariants = ` - - - -`; - -export const flexFAQ1 = ` - Hello World - Hello World - Hello World -`; - -export const flexSimple = ` - Hello World - Hello World - Hello World -`; - -export const flexResponsive = ` - Hello World - Hello World - Hello World -`; - -export const flexAlign = ` - Hello World - Hello World - Hello World -`; diff --git a/canon-docs/src/snippets/stories-snippets.tsx b/canon-docs/src/snippets/stories-snippets.tsx index 64047ebde9..62b0a99232 100644 --- a/canon-docs/src/snippets/stories-snippets.tsx +++ b/canon-docs/src/snippets/stories-snippets.tsx @@ -3,11 +3,12 @@ import { composeStories } from '@storybook/react'; import * as BoxStories from '../../../packages/canon/src/components/Box/Box.stories'; import * as ButtonStories from '../../../packages/canon/src/components/Button/Button.stories'; +import * as ButtonIconStories from '../../../packages/canon/src/components/ButtonIcon/ButtonIcon.stories'; +import * as ButtonLinkStories from '../../../packages/canon/src/components/ButtonLink/ButtonLink.stories'; import * as CheckboxStories from '../../../packages/canon/src/components/Checkbox/Checkbox.stories'; import * as ContainerStories from '../../../packages/canon/src/components/Container/Container.stories'; import * as GridStories from '../../../packages/canon/src/components/Grid/Grid.stories'; import * as HeadingStories from '../../../packages/canon/src/components/Heading/Heading.stories'; -import * as IconButtonStories from '../../../packages/canon/src/components/IconButton/IconButton.stories'; import * as IconStories from '../../../packages/canon/src/components/Icon/Icon.stories'; import * as TextFieldStories from '../../../packages/canon/src/components/TextField/TextField.stories'; import * as TextStories from '../../../packages/canon/src/components/Text/Text.stories'; @@ -17,7 +18,10 @@ import * as MenuStories from '../../../packages/canon/src/components/Menu/Menu.s import * as LinkStories from '../../../packages/canon/src/components/Link/Link.stories'; import * as AvatarStories from '../../../packages/canon/src/components/Avatar/Avatar.stories'; import * as CollapsibleStories from '../../../packages/canon/src/components/Collapsible/Collapsible.stories'; +import * as RadioGroupStories from '../../../packages/canon/src/components/RadioGroup/RadioGroup.stories'; import * as TabsStories from '../../../packages/canon/src/components/Tabs/Tabs.stories'; +import * as SwitchStories from '../../../packages/canon/src/components/Switch/Switch.stories'; +import * as SearchFieldStories from '../../../packages/canon/src/components/SearchField/SearchField.stories'; export const BoxSnippet = ({ story }: { story: keyof typeof BoxStories }) => { const stories = composeStories(BoxStories); @@ -37,6 +41,28 @@ export const ButtonSnippet = ({ return StoryComponent ? : null; }; +export const ButtonIconSnippet = ({ + story, +}: { + story: keyof typeof ButtonIconStories; +}) => { + const stories = composeStories(ButtonIconStories); + const StoryComponent = stories[story as keyof typeof stories]; + + return StoryComponent ? : null; +}; + +export const ButtonLinkSnippet = ({ + story, +}: { + story: keyof typeof ButtonLinkStories; +}) => { + const stories = composeStories(ButtonLinkStories); + const StoryComponent = stories[story as keyof typeof stories]; + + return StoryComponent ? : null; +}; + export const CheckboxSnippet = ({ story, }: { @@ -95,17 +121,6 @@ export const HeadingSnippet = ({ return StoryComponent ? : null; }; -export const IconButtonSnippet = ({ - story, -}: { - story: keyof typeof IconButtonStories; -}) => { - const stories = composeStories(IconButtonStories); - const StoryComponent = stories[story as keyof typeof stories]; - - return StoryComponent ? : null; -}; - export const IconSnippet = ({ story }: { story: keyof typeof IconStories }) => { const stories = composeStories(IconStories); const StoryComponent = stories[story as keyof typeof stories]; @@ -173,3 +188,36 @@ export const TabsSnippet = ({ story }: { story: keyof typeof TabsStories }) => { return StoryComponent ? : null; }; + +export const SwitchSnippet = ({ + story, +}: { + story: keyof typeof SwitchStories; +}) => { + const stories = composeStories(SwitchStories); + const StoryComponent = stories[story as keyof typeof stories]; + + return StoryComponent ? : null; +}; + +export const RadioGroupSnippet = ({ + story, +}: { + story: keyof typeof RadioGroupStories; +}) => { + const stories = composeStories(RadioGroupStories); + const StoryComponent = stories[story as keyof typeof stories]; + + return StoryComponent ? : null; +}; + +export const SearchFieldSnippet = ({ + story, +}: { + story: keyof typeof SearchFieldStories; +}) => { + const stories = composeStories(SearchFieldStories); + const StoryComponent = stories[story as keyof typeof stories]; + + return StoryComponent ? : null; +}; diff --git a/canon-docs/src/utils/changelog.ts b/canon-docs/src/utils/changelog.ts new file mode 100644 index 0000000000..94317ab78b --- /dev/null +++ b/canon-docs/src/utils/changelog.ts @@ -0,0 +1,386 @@ +export type Component = + | 'avatar' + | 'box' + | 'button' + | 'heading' + | 'text' + | 'icon-button' + | 'icon' + | 'tabs' + | 'menu' + | 'textfield' + | 'datatable' + | 'select' + | 'collapsible' + | 'checkbox' + | 'container' + | 'link' + | 'tooltip' + | 'scrollarea' + | 'flex' + | 'switch'; + +export type Version = `${number}.${number}.${number}`; + +export interface ChangelogProps { + components: Component[]; + description: string; + version: Version; + platform: 'oss' | 'portal'; + prs: string[]; +} + +export const changelog: ChangelogProps[] = [ + { + components: ['switch'], + version: '0.5.0', + description: '✨ Add new `Switch` component', + platform: 'portal', + prs: ['30251'], + }, + { + components: ['tabs'], + version: '0.4.0', + description: '✨ Add new `Tabs` component', + platform: 'portal', + prs: ['29996'], + }, + { + components: ['text', 'heading'], + version: '0.4.0', + description: '✨ Add `truncate` prop to `Text` and `Heading`', + platform: 'portal', + prs: ['29988'], + }, + { + components: ['menu'], + version: '0.4.0', + description: '✨ Add combobox option to `Menu`', + platform: 'portal', + prs: ['29986'], + }, + { + components: ['textfield'], + version: '0.4.0', + description: '✨ Add icon prop on `TextField`', + platform: 'portal', + prs: ['29820'], + }, + { + components: ['button', 'icon-button'], + version: '0.4.0', + description: 'Improve icon props on `Button` and `IconButton`', + platform: 'portal', + prs: ['29667'], + }, + { + components: ['text', 'heading'], + version: '0.4.0', + description: + 'Improve the way we treat custom render on `Text` and `Heading`', + platform: 'portal', + prs: ['29989'], + }, + { + components: ['menu'], + version: '0.4.0', + description: 'Improve `Menu` styles', + platform: 'portal', + prs: ['29986'], + }, + { + components: ['textfield'], + version: '0.4.0', + description: 'Improve `TextField` styles', + platform: 'portal', + prs: ['29974'], + }, + { + components: ['textfield'], + version: '0.4.0', + description: 'Improve clear button on `TextField`', + platform: 'portal', + prs: ['29878'], + }, + { + components: ['flex'], + version: '0.4.0', + description: 'Fix spacing props on all layout components', + platform: 'portal', + prs: ['30013'], + }, + { + components: [], + version: '0.4.0', + description: 'Fix - Pin Base UI version', + platform: 'portal', + prs: ['29782'], + }, + { + components: ['select'], + version: '0.4.0', + description: 'Fix - Clicking `Select` label moves focus to trigger', + platform: 'portal', + prs: ['29755'], + }, + { + components: ['datatable'], + version: '0.4.0', + description: 'Fix `DataTable.Pagination` count issue', + platform: 'portal', + prs: ['29688'], + }, + { + components: ['datatable'], + version: '0.3.0', + description: 'Add `DataTable` component', + platform: 'portal', + prs: ['29484', '29603'], + }, + { + components: ['select'], + version: '0.3.0', + description: 'Add `Select` component', + platform: 'portal', + prs: ['29440'], + }, + { + components: ['avatar'], + version: '0.3.0', + description: 'Add `Avatar` component', + platform: 'portal', + prs: ['29594'], + }, + { + components: ['collapsible'], + version: '0.3.0', + description: 'Add `Collapsible` component', + platform: 'portal', + prs: ['29617'], + }, + { + components: ['textfield'], + version: '0.3.0', + description: 'Add `TextField` component instead of `Field` + `Input`', + platform: 'portal', + prs: ['29364'], + }, + { + components: ['datatable'], + version: '0.3.0', + description: 'Add `TableCellProfile`', + platform: 'portal', + prs: ['29600'], + }, + { + components: [], + version: '0.3.0', + description: 'Add breakpoint hooks - `up()` and `down()`', + platform: 'portal', + prs: ['29564'], + }, + { + components: [], + version: '0.3.0', + description: 'Add gray scale css tokens', + platform: 'portal', + prs: ['29543'], + }, + { + components: [], + version: '0.3.0', + description: + 'Update CSS styling API using `[data-___]` instead of class names for props', + platform: 'portal', + prs: ['29560'], + }, + { + components: ['checkbox'], + version: '0.3.0', + description: 'Update `Checkbox` dark mode', + platform: 'portal', + prs: ['29544'], + }, + { + components: ['container'], + version: '0.3.0', + description: 'Update `Container` styles', + platform: 'portal', + prs: ['29475'], + }, + { + components: ['menu'], + version: '0.3.0', + description: 'Update `Menu` styles', + platform: 'portal', + prs: ['29351'], + }, + { + components: ['select'], + version: '0.3.0', + description: 'Fix `Select` styles on small sizes + with long option names', + platform: 'portal', + prs: ['29545'], + }, + { + components: ['link'], + version: '0.3.0', + description: 'Fix render prop on `Link`', + platform: 'portal', + prs: ['29247'], + }, + { + components: ['textfield', 'select'], + version: '0.3.0', + description: 'Remove `Field` from `TextField` + `Select`', + platform: 'portal', + prs: ['29482'], + }, + { + components: ['text', 'heading'], + version: '0.3.0', + description: 'Update `textDecoration` to `none` on `Text` / `Heading`', + platform: 'portal', + prs: ['29357'], + }, + { + components: ['text', 'heading'], + version: '0.3.0', + description: 'Update `textDecoration` to `none` on `Text` / `Heading`', + platform: 'portal', + prs: ['29357'], + }, + { + components: [], + version: '0.3.0', + description: 'Docs - Use stories from Storybook for all examples in Nextjs', + platform: 'portal', + prs: ['29306'], + }, + { + components: [], + version: '0.3.0', + description: 'Docs - Add release page (this one 🤗)', + platform: 'portal', + prs: ['29461'], + }, + { + components: [], + version: '0.3.0', + description: 'Docs - Add docs for Menu, Link', + platform: 'portal', + prs: ['29576'], + }, + { + components: [], + version: '0.3.0', + description: 'Fix CSS watch mode', + platform: 'portal', + prs: ['29352'], + }, + { + components: ['menu'], + version: '0.2.0', + description: 'New `Menu` component', + platform: 'portal', + prs: ['29151'], + }, + { + components: ['icon-button'], + version: '0.2.0', + description: 'New `IconButton` component', + platform: 'portal', + prs: ['29239'], + }, + { + components: ['scrollarea'], + version: '0.2.0', + description: 'New `ScrollArea` component', + platform: 'portal', + prs: ['29240'], + }, + { + components: ['button', 'checkbox'], + version: '0.2.0', + description: 'Improve `Button` & `Checkbox` styles', + platform: 'portal', + prs: ['29127', '28789'], + }, + { + components: ['text'], + version: '0.2.0', + description: 'Improve `Text` styles', + platform: 'portal', + prs: ['29200'], + }, + { + components: ['icon'], + version: '0.2.0', + description: 'Renamed `CanonProvider` to `IconProvider`', + platform: 'portal', + prs: ['29002'], + }, + { + components: ['icon'], + version: '0.2.0', + description: 'Added about 40+ new icons', + platform: 'portal', + prs: ['29264'], + }, + { + components: [], + version: '0.2.0', + description: 'Simplified styling into a unique styles.css file', + platform: 'portal', + prs: ['29199'], + }, + { + components: [], + version: '0.2.0', + description: 'Added Canon styles to Backstage', + platform: 'portal', + prs: ['29137'], + }, + { + components: [], + version: '0.2.0', + description: 'Update global CSS tokens', + platform: 'portal', + prs: ['28804'], + }, + { + components: ['flex'], + version: '0.2.0', + description: 'Merge Stack + Inline into Flex', + platform: 'portal', + prs: ['28634'], + }, + { + components: ['button'], + version: '0.2.0', + description: 'Improve `Button` types', + platform: 'portal', + prs: ['29205'], + }, + { + components: [], + version: '0.2.0', + description: 'Move font weight and family back to each components', + platform: 'portal', + prs: ['28972'], + }, + { + components: [], + version: '0.2.0', + description: 'Fix custom values in spacing props', + platform: 'portal', + prs: ['28770'], + }, + { + components: [], + version: '0.2.0', + description: 'Multiple updates on the Canon Docs site', + platform: 'portal', + prs: ['28760'], + }, +]; diff --git a/canon-docs/src/utils/data.ts b/canon-docs/src/utils/data.ts index ba4fd5e432..c1997f5b1f 100644 --- a/canon-docs/src/utils/data.ts +++ b/canon-docs/src/utils/data.ts @@ -14,8 +14,8 @@ export const overview: Page[] = [ slug: 'about', }, { - title: 'Releases', - slug: 'releases', + title: 'Changelog', + slug: 'changelog', }, ]; @@ -76,6 +76,16 @@ export const components: Page[] = [ slug: 'button', status: 'alpha', }, + { + title: 'ButtonIcon', + slug: 'button-icon', + status: 'alpha', + }, + { + title: 'ButtonLink', + slug: 'button-link', + status: 'alpha', + }, { title: 'Checkbox', slug: 'checkbox', @@ -96,11 +106,6 @@ export const components: Page[] = [ slug: 'icon', status: 'alpha', }, - { - title: 'IconButton', - slug: 'icon-button', - status: 'alpha', - }, { title: 'Link', slug: 'link', @@ -111,11 +116,26 @@ export const components: Page[] = [ slug: 'menu', status: 'alpha', }, + { + title: 'RadioGroup', + slug: 'radio-group', + status: 'alpha', + }, + { + title: 'SearchField', + slug: 'search-field', + status: 'alpha', + }, { title: 'Select', slug: 'select', status: 'alpha', }, + { + title: 'Switch', + slug: 'switch', + status: 'alpha', + }, { title: 'Table', slug: 'table', diff --git a/canon-docs/src/utils/playground-context.tsx b/canon-docs/src/utils/playground-context.tsx index 9d4e23217f..35c881b2d8 100644 --- a/canon-docs/src/utils/playground-context.tsx +++ b/canon-docs/src/utils/playground-context.tsx @@ -40,16 +40,29 @@ export const PlaygroundProvider = ({ children }: { children: ReactNode }) => { const [selectedComponents, setSelectedComponents] = useState( components.map(component => component.slug), ); - const [selectedTheme, setSelectedTheme] = useState(() => { - return isBrowser - ? (localStorage.getItem('theme') as Theme) || 'light' - : 'light'; - }); - const [selectedThemeName, setSelectedThemeName] = useState(() => { - return isBrowser - ? (localStorage.getItem('theme-name') as ThemeName) || 'default' - : 'default'; - }); + const [selectedTheme, setSelectedTheme] = useState('light'); + const [selectedThemeName, setSelectedThemeName] = + useState('default'); + + // Load saved theme from localStorage after hydration + useEffect(() => { + if (isBrowser) { + const savedTheme = localStorage.getItem('theme') as Theme; + if (savedTheme) { + setSelectedTheme(savedTheme); + } + } + }, [isBrowser]); + + // Load saved theme name from localStorage after hydration + useEffect(() => { + if (isBrowser) { + const savedThemeName = localStorage.getItem('theme-name') as ThemeName; + if (savedThemeName) { + setSelectedThemeName(savedThemeName); + } + } + }, [isBrowser]); useEffect(() => { if (isBrowser) { diff --git a/canon-docs/src/utils/theme-switcher.ts b/canon-docs/src/utils/theme-switcher.ts new file mode 100644 index 0000000000..5849d767f6 --- /dev/null +++ b/canon-docs/src/utils/theme-switcher.ts @@ -0,0 +1,32 @@ +// Auto-generated theme switcher utility + +export const availableThemes = { + default: '/styles.css', + spotify: '/spotify-theme.css', +} as const; + +export type ThemeName = keyof typeof availableThemes; + +export function switchTheme(themeName: ThemeName) { + // Remove existing theme links + const existingLinks = document.querySelectorAll('link[data-theme]'); + existingLinks.forEach(link => link.remove()); + + // Add new theme link + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = availableThemes[themeName]; + link.setAttribute('data-theme', themeName); + document.head.appendChild(link); +} + +export function getCurrentTheme(): ThemeName { + const existingLink = document.querySelector('link[data-theme]'); + if (existingLink) { + const href = existingLink.getAttribute('href'); + for (const [name, path] of Object.entries(availableThemes)) { + if (path === href) return name as ThemeName; + } + } + return 'default'; +} diff --git a/canon-docs/tsconfig.json b/canon-docs/tsconfig.json index 2baa7cde8f..e1b3951aa8 100644 --- a/canon-docs/tsconfig.json +++ b/canon-docs/tsconfig.json @@ -3,7 +3,7 @@ "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "skipLibCheck": true, - "strict": true, + "strict": false, "noEmit": true, "esModuleInterop": true, "module": "esnext", @@ -12,6 +12,7 @@ "isolatedModules": true, "jsx": "preserve", "incremental": true, + "noImplicitAny": false, "plugins": [ { "name": "next" @@ -19,14 +20,16 @@ ], "paths": { "@/*": ["./src/*"] - } + }, + "target": "ES2017" }, "include": [ "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", - "dist/types/**/*.ts" + "dist/types/**/*.ts", + "src/types/**/*.d.ts" ], "exclude": ["node_modules"] } diff --git a/canon-docs/yarn.lock b/canon-docs/yarn.lock index decb4e7efe..53cec56764 100644 --- a/canon-docs/yarn.lock +++ b/canon-docs/yarn.lock @@ -5,36 +5,52 @@ __metadata: version: 8 cacheKey: 10 -"@babel/runtime@npm:^7.18.6": - version: 7.26.10 - resolution: "@babel/runtime@npm:7.26.10" +"@babel/code-frame@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/code-frame@npm:7.27.1" dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: 10/9d7ff8e96abe3791047c1138789c742411e3ef19c4d7ca18ce916f83cec92c06ec5dc64401759f6dd1e377cf8a01bbd2c62e033eb7550f435cf6579768d0d4a5 + "@babel/helper-validator-identifier": "npm:^7.27.1" + js-tokens: "npm:^4.0.0" + picocolors: "npm:^1.1.1" + checksum: 10/721b8a6e360a1fa0f1c9fe7351ae6c874828e119183688b533c477aa378f1010f37cc9afbfc4722c686d1f5cdd00da02eab4ba7278a0c504fa0d7a321dcd4fdf + languageName: node + linkType: hard + +"@babel/helper-validator-identifier@npm:^7.27.1": + version: 7.27.1 + resolution: "@babel/helper-validator-identifier@npm:7.27.1" + checksum: 10/75041904d21bdc0cd3b07a8ac90b11d64cd3c881e89cb936fa80edd734bf23c35e6bd1312611e8574c4eab1f3af0f63e8a5894f4699e9cfdf70c06fcf4252320 + languageName: node + linkType: hard + +"@babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.21.0": + version: 7.27.6 + resolution: "@babel/runtime@npm:7.27.6" + checksum: 10/cc957a12ba3781241b83d528eb69ddeb86ca5ac43179a825e83aa81263a6b3eb88c57bed8a937cdeacfc3192e07ec24c73acdfea4507d0c0428c8e23d6322bfe languageName: node linkType: hard "@codemirror/autocomplete@npm:^6.0.0": - version: 6.18.4 - resolution: "@codemirror/autocomplete@npm:6.18.4" + version: 6.18.6 + resolution: "@codemirror/autocomplete@npm:6.18.6" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.17.0" "@lezer/common": "npm:^1.0.0" - checksum: 10/7cd62db2ee87d6cb3936ced4f211bdcd9ce75515f64922119370c303a8bdbf5640e640a8d802c30d01cb55fb6c9b5299426ff799f04cff0bef8d0c3450fe2528 + checksum: 10/0574d96fd04ccf2d3b7ae3c4efe0a72f423fa81658876ec50865ce3371cea038aeddf026976ec0d0ccbee72ac66bdf7deec9106dee251ad49019ae7e1a871663 languageName: node linkType: hard "@codemirror/commands@npm:^6.0.0, @codemirror/commands@npm:^6.1.0": - version: 6.8.0 - resolution: "@codemirror/commands@npm:6.8.0" + version: 6.8.1 + resolution: "@codemirror/commands@npm:6.8.1" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.4.0" "@codemirror/view": "npm:^6.27.0" "@lezer/common": "npm:^1.1.0" - checksum: 10/0c7991736bc84d0a7f8e49c311c78a78def84fca36ff61c2f9887067e2c06b1b232711cb99282cd410527ddbe0671d2b9aff93e0848fa731a2014c3691c737ea + checksum: 10/72b6343777d4fe4af1bcc91331eb64705b33e871c9f8e2a0cd177269478a6f3282bf25aeaecdbb55fd5e031b67aabfede068e919fe69e473d07e5090dd76b381 languageName: node linkType: hard @@ -65,8 +81,8 @@ __metadata: linkType: hard "@codemirror/language@npm:^6.0.0": - version: 6.10.8 - resolution: "@codemirror/language@npm:6.10.8" + version: 6.11.1 + resolution: "@codemirror/language@npm:6.11.1" dependencies: "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.23.0" @@ -74,38 +90,38 @@ __metadata: "@lezer/highlight": "npm:^1.0.0" "@lezer/lr": "npm:^1.0.0" style-mod: "npm:^4.0.0" - checksum: 10/63b83b41d9f8475f757144cc204df08834bb14411c484aa265ffa3e93b7d8f696a21110df72101159a8675eda29018c6d08f864965bd4651b607a39f10ad32ed + checksum: 10/024969113d61ccb5d497b75a8a9875d43e1bfc8466de2819bb5db23f01b200937366800a812e8d33eb5e34e3a5d2aa22d0ff8205f34a5e8aeb4cd1d221bcaa78 languageName: node linkType: hard "@codemirror/lint@npm:^6.0.0": - version: 6.8.4 - resolution: "@codemirror/lint@npm:6.8.4" + version: 6.8.5 + resolution: "@codemirror/lint@npm:6.8.5" dependencies: "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.35.0" crelt: "npm:^1.0.5" - checksum: 10/401ead0591d88d31d1bf6527d4caba26e0deb7b49382dfbb8c712037d858047b0699fa2c15831a07db928194549eea9b942004fee42f334b34ff5973c7dbec58 + checksum: 10/9eddfea1dd0615431d57687c2a0d4de510d725aac6f6bbc2eba4bc934963371304dfa4c49398b3043372ef34cead3ebc0ec3f652632a87f5d8a458fa911a309a languageName: node linkType: hard "@codemirror/search@npm:^6.0.0": - version: 6.5.8 - resolution: "@codemirror/search@npm:6.5.8" + version: 6.5.11 + resolution: "@codemirror/search@npm:6.5.11" dependencies: "@codemirror/state": "npm:^6.0.0" "@codemirror/view": "npm:^6.0.0" crelt: "npm:^1.0.5" - checksum: 10/1389fa4e05da72b621ae10ff00d4ef0d23b08a3a7ac48f6e0b867429da7b80036bd7a6feef1a54f5b4c4af9fc4277f754a313a858fbfc12ccdfa48e9bf300cef + checksum: 10/d057f37cb369460b25625d7eb72f40636bf78ecd140608da53010cf3660f982a9e613826e38d85d87c9c2ff11e45c9482429987bfd4f29cbbd192f1ee3fd2695 languageName: node linkType: hard "@codemirror/state@npm:^6.0.0, @codemirror/state@npm:^6.1.1, @codemirror/state@npm:^6.4.0, @codemirror/state@npm:^6.5.0": - version: 6.5.1 - resolution: "@codemirror/state@npm:6.5.1" + version: 6.5.2 + resolution: "@codemirror/state@npm:6.5.2" dependencies: "@marijn/find-cluster-break": "npm:^1.0.0" - checksum: 10/117f21ba2ff5bc9f9b946ca9943279a29bb9461ec77fc2313cfd8908ed6eb7df2950d7c5b0ba0a0a23c3e0633c6bba56f8c105f97875665e0376a9e110d10a48 + checksum: 10/5ccd3acb0c0a5b88e83fb91be39099fceb9f44a5047cc41a75d53f160e736851f65c8de40950b90c6519e6d2828e12f468db0af658dde30e938896f1c39eec91 languageName: node linkType: hard @@ -121,200 +137,229 @@ __metadata: languageName: node linkType: hard -"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.27.0, @codemirror/view@npm:^6.35.0": - version: 6.36.2 - resolution: "@codemirror/view@npm:6.36.2" +"@codemirror/view@npm:^6.0.0, @codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.27.0, @codemirror/view@npm:^6.34.4, @codemirror/view@npm:^6.35.0": + version: 6.38.0 + resolution: "@codemirror/view@npm:6.38.0" dependencies: "@codemirror/state": "npm:^6.5.0" + crelt: "npm:^1.0.6" style-mod: "npm:^4.1.0" w3c-keyname: "npm:^2.2.4" - checksum: 10/9ef7fcf4f9d9b6e66645ae65da1bf0c90e08f6ba786de0373b9f3644632066b91b8ea20faf67bb81eb9adf310ae76888cc7fd0901e2bb4821193f5427455c137 + checksum: 10/30a2d103d0926a1677217d977578ae351a00e6c2777ea3eeadb24619f3477a8368668ccd51722dd3d05c84227b707b8938ce04283ad2ccb41bd00a00ef4bdbb0 languageName: node linkType: hard -"@esbuild/aix-ppc64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/aix-ppc64@npm:0.25.0" +"@emnapi/core@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/core@npm:1.4.3" + dependencies: + "@emnapi/wasi-threads": "npm:1.0.2" + tslib: "npm:^2.4.0" + checksum: 10/b511f66b897d2019835391544fdf11f4fa0ce06cc1181abfa17c7d4cf03aaaa4fc8a64fcd30bb3f901de488d0a6f370b53a8de2215a898f5a4ac98015265b3b7 + languageName: node + linkType: hard + +"@emnapi/runtime@npm:^1.4.3": + version: 1.4.3 + resolution: "@emnapi/runtime@npm:1.4.3" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/4f90852a1a5912982cc4e176b6420556971bcf6a85ee23e379e2455066d616219751367dcf43e6a6eaf41ea7e95ba9dc830665a52b5d979dfe074237d19578f8 + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.0.2": + version: 1.0.2 + resolution: "@emnapi/wasi-threads@npm:1.0.2" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10/e82941776665eb958c2084728191d6b15a94383449975c4621b67a1c8217e1c0ec11056a693906c76863cb96f782f8be500510ecec6874e3f5da35a8e7968cfd + languageName: node + linkType: hard + +"@esbuild/aix-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/aix-ppc64@npm:0.25.5" conditions: os=aix & cpu=ppc64 languageName: node linkType: hard -"@esbuild/android-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-arm64@npm:0.25.0" +"@esbuild/android-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm64@npm:0.25.5" conditions: os=android & cpu=arm64 languageName: node linkType: hard -"@esbuild/android-arm@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-arm@npm:0.25.0" +"@esbuild/android-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-arm@npm:0.25.5" conditions: os=android & cpu=arm languageName: node linkType: hard -"@esbuild/android-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/android-x64@npm:0.25.0" +"@esbuild/android-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/android-x64@npm:0.25.5" conditions: os=android & cpu=x64 languageName: node linkType: hard -"@esbuild/darwin-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/darwin-arm64@npm:0.25.0" +"@esbuild/darwin-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-arm64@npm:0.25.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@esbuild/darwin-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/darwin-x64@npm:0.25.0" +"@esbuild/darwin-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/darwin-x64@npm:0.25.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@esbuild/freebsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/freebsd-arm64@npm:0.25.0" +"@esbuild/freebsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-arm64@npm:0.25.5" conditions: os=freebsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/freebsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/freebsd-x64@npm:0.25.0" +"@esbuild/freebsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/freebsd-x64@npm:0.25.5" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@esbuild/linux-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-arm64@npm:0.25.0" +"@esbuild/linux-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm64@npm:0.25.5" conditions: os=linux & cpu=arm64 languageName: node linkType: hard -"@esbuild/linux-arm@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-arm@npm:0.25.0" +"@esbuild/linux-arm@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-arm@npm:0.25.5" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@esbuild/linux-ia32@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-ia32@npm:0.25.0" +"@esbuild/linux-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ia32@npm:0.25.5" conditions: os=linux & cpu=ia32 languageName: node linkType: hard -"@esbuild/linux-loong64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-loong64@npm:0.25.0" +"@esbuild/linux-loong64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-loong64@npm:0.25.5" conditions: os=linux & cpu=loong64 languageName: node linkType: hard -"@esbuild/linux-mips64el@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-mips64el@npm:0.25.0" +"@esbuild/linux-mips64el@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-mips64el@npm:0.25.5" conditions: os=linux & cpu=mips64el languageName: node linkType: hard -"@esbuild/linux-ppc64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-ppc64@npm:0.25.0" +"@esbuild/linux-ppc64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-ppc64@npm:0.25.5" conditions: os=linux & cpu=ppc64 languageName: node linkType: hard -"@esbuild/linux-riscv64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-riscv64@npm:0.25.0" +"@esbuild/linux-riscv64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-riscv64@npm:0.25.5" conditions: os=linux & cpu=riscv64 languageName: node linkType: hard -"@esbuild/linux-s390x@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-s390x@npm:0.25.0" +"@esbuild/linux-s390x@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-s390x@npm:0.25.5" conditions: os=linux & cpu=s390x languageName: node linkType: hard -"@esbuild/linux-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/linux-x64@npm:0.25.0" +"@esbuild/linux-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/linux-x64@npm:0.25.5" conditions: os=linux & cpu=x64 languageName: node linkType: hard -"@esbuild/netbsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/netbsd-arm64@npm:0.25.0" +"@esbuild/netbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-arm64@npm:0.25.5" conditions: os=netbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/netbsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/netbsd-x64@npm:0.25.0" +"@esbuild/netbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/netbsd-x64@npm:0.25.5" conditions: os=netbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/openbsd-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/openbsd-arm64@npm:0.25.0" +"@esbuild/openbsd-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-arm64@npm:0.25.5" conditions: os=openbsd & cpu=arm64 languageName: node linkType: hard -"@esbuild/openbsd-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/openbsd-x64@npm:0.25.0" +"@esbuild/openbsd-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/openbsd-x64@npm:0.25.5" conditions: os=openbsd & cpu=x64 languageName: node linkType: hard -"@esbuild/sunos-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/sunos-x64@npm:0.25.0" +"@esbuild/sunos-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/sunos-x64@npm:0.25.5" conditions: os=sunos & cpu=x64 languageName: node linkType: hard -"@esbuild/win32-arm64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-arm64@npm:0.25.0" +"@esbuild/win32-arm64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-arm64@npm:0.25.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@esbuild/win32-ia32@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-ia32@npm:0.25.0" +"@esbuild/win32-ia32@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-ia32@npm:0.25.5" conditions: os=win32 & cpu=ia32 languageName: node linkType: hard -"@esbuild/win32-x64@npm:0.25.0": - version: 0.25.0 - resolution: "@esbuild/win32-x64@npm:0.25.0" +"@esbuild/win32-x64@npm:0.25.5": + version: 0.25.5 + resolution: "@esbuild/win32-x64@npm:0.25.5" conditions: os=win32 & cpu=x64 languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": - version: 4.4.1 - resolution: "@eslint-community/eslint-utils@npm:4.4.1" +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.7.0": + version: 4.7.0 + resolution: "@eslint-community/eslint-utils@npm:4.7.0" dependencies: eslint-visitor-keys: "npm:^3.4.3" peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 10/ae92a11412674329b4bd38422518601ec9ceae28e251104d1cad83715da9d38e321f68c817c39b64e66d0af7d98df6f9a10ad2dc638911254b47fb8932df00ef + checksum: 10/43ed5d391526d9f5bbe452aef336389a473026fca92057cf97c576db11401ce9bcf8ef0bf72625bbaf6207ed8ba6bf0dcf4d7e809c24f08faa68a28533c491a7 languageName: node linkType: hard @@ -374,6 +419,195 @@ __metadata: languageName: node linkType: hard +"@img/sharp-darwin-arm64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-darwin-arm64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-darwin-arm64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-darwin-arm64": + optional: true + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-darwin-x64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-darwin-x64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-darwin-x64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-darwin-x64": + optional: true + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-arm64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-darwin-arm64@npm:1.1.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-x64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-darwin-x64@npm:1.1.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-arm64@npm:1.1.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-arm@npm:1.1.0" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-ppc64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-ppc64@npm:1.1.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-s390x@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-s390x@npm:1.1.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-x64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linux-x64@npm:1.1.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-arm64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linuxmusl-arm64@npm:1.1.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-x64@npm:1.1.0": + version: 1.1.0 + resolution: "@img/sharp-libvips-linuxmusl-x64@npm:1.1.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linux-arm64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linux-arm64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linux-arm64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linux-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-arm@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linux-arm@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linux-arm": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linux-arm": + optional: true + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-s390x@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linux-s390x@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linux-s390x": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linux-s390x": + optional: true + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-x64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linux-x64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linux-x64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linux-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-arm64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linuxmusl-arm64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-x64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-linuxmusl-x64@npm:0.34.2" + dependencies: + "@img/sharp-libvips-linuxmusl-x64": "npm:1.1.0" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-wasm32@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-wasm32@npm:0.34.2" + dependencies: + "@emnapi/runtime": "npm:^1.4.3" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@img/sharp-win32-arm64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-win32-arm64@npm:0.34.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-win32-ia32@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-win32-ia32@npm:0.34.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@img/sharp-win32-x64@npm:0.34.2": + version: 0.34.2 + resolution: "@img/sharp-win32-x64@npm:0.34.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -388,6 +622,15 @@ __metadata: languageName: node linkType: hard +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10/4412e9e6713c89c1e66d80bb0bb5a2a93192f10477623a27d08f228ba0316bb880affabc5bfe7f838f58a34d26c2c190da726e576cdfc18c49a72e89adabdcf5 + languageName: node + linkType: hard + "@lezer/common@npm:^1.0.0, @lezer/common@npm:^1.0.2, @lezer/common@npm:^1.1.0, @lezer/common@npm:^1.2.0": version: 1.2.3 resolution: "@lezer/common@npm:1.2.3" @@ -396,13 +639,13 @@ __metadata: linkType: hard "@lezer/css@npm:^1.1.7": - version: 1.1.9 - resolution: "@lezer/css@npm:1.1.9" + version: 1.2.1 + resolution: "@lezer/css@npm:1.2.1" dependencies: "@lezer/common": "npm:^1.2.0" "@lezer/highlight": "npm:^1.0.0" - "@lezer/lr": "npm:^1.0.0" - checksum: 10/bcc277bb6b806961ebfd03e98faf8e5870dd7da2eb565c43922ac378d926b49f479309b28cc824fd4e17baac2c8952966807d06fbe2a45d53e9a3f1518134729 + "@lezer/lr": "npm:^1.3.0" + checksum: 10/726ea0e0b4d10c0326cc62d562a63c0d74970dde2002fab8172681c63e3210ff39d0f629370ad498b70e503ab2e9f74dd342d7c9e402b98f315b556116c3551a languageName: node linkType: hard @@ -415,7 +658,7 @@ __metadata: languageName: node linkType: hard -"@lezer/lr@npm:^1.0.0": +"@lezer/lr@npm:^1.0.0, @lezer/lr@npm:^1.3.0": version: 1.4.2 resolution: "@lezer/lr@npm:1.4.2" dependencies: @@ -425,13 +668,13 @@ __metadata: linkType: hard "@lezer/sass@npm:^1.0.0": - version: 1.0.7 - resolution: "@lezer/sass@npm:1.0.7" + version: 1.1.0 + resolution: "@lezer/sass@npm:1.1.0" dependencies: "@lezer/common": "npm:^1.2.0" "@lezer/highlight": "npm:^1.0.0" "@lezer/lr": "npm:^1.0.0" - checksum: 10/a7531cbf0766d3875480c24ae8929dd56053d71f9eaef8815e6f468e2252e66e38236a3f89395463e4cee43230dc35351386bedc6138cf1a19a44a64ce58a372 + checksum: 10/2f42dfaf5a328d4626a0a8ff8cd5973b7f52e8112541281cf1cbb1970acdc52c7c9f55c71f635bcff75a6151a55f7653d277306a15494b23b652e87d16df9ce3 languageName: node linkType: hard @@ -457,7 +700,7 @@ __metadata: languageName: node linkType: hard -"@mdx-js/mdx@npm:^3.0.0": +"@mdx-js/mdx@npm:^3.0.0, @mdx-js/mdx@npm:^3.1.0": version: 3.1.0 resolution: "@mdx-js/mdx@npm:3.1.0" dependencies: @@ -501,25 +744,36 @@ __metadata: languageName: node linkType: hard -"@next/env@npm:14.2.26": - version: 14.2.26 - resolution: "@next/env@npm:14.2.26" - checksum: 10/0caa679cdf9367501daf1bff0e762b720613a3ee1689e5585bfb7c792fdd07c251bc1f7488919a296047eb1f2b82ceb13955b673143468cad338a87b7d98c196 - languageName: node - linkType: hard - -"@next/eslint-plugin-next@npm:14.2.23": - version: 14.2.23 - resolution: "@next/eslint-plugin-next@npm:14.2.23" +"@napi-rs/wasm-runtime@npm:^0.2.11": + version: 0.2.11 + resolution: "@napi-rs/wasm-runtime@npm:0.2.11" dependencies: - glob: "npm:10.3.10" - checksum: 10/e46513a7601bf682f1e60cc668188cf2c9f0471be73ffbbac69da240e9f91c6b9c3aad3e83a8da54c0ba8bce37cc6368bbafb04b74b385d5df0c36dde09a3217 + "@emnapi/core": "npm:^1.4.3" + "@emnapi/runtime": "npm:^1.4.3" + "@tybys/wasm-util": "npm:^0.9.0" + checksum: 10/e30fe3060474c5018e160231df0531d62b5e22f4736ecd49c04ca6cadacb2acf59b9205435794cd5b898e41e2e3ddb6523e93b97799bd1f4d0751557de6e38e4 languageName: node linkType: hard -"@next/mdx@npm:^15.1.4": - version: 15.1.6 - resolution: "@next/mdx@npm:15.1.6" +"@next/env@npm:15.3.4": + version: 15.3.4 + resolution: "@next/env@npm:15.3.4" + checksum: 10/40ea0bee2eca72dce6102d30ac50029309bf68a281585270e38f920ae47043f240352ad250058d462169a436dea3d8f78a935406ee61088bd4a614524b4a315b + languageName: node + linkType: hard + +"@next/eslint-plugin-next@npm:15.3.4": + version: 15.3.4 + resolution: "@next/eslint-plugin-next@npm:15.3.4" + dependencies: + fast-glob: "npm:3.3.1" + checksum: 10/8a473bd32a06f62c16f60f9c40b7b8149cf91170ce4c1546cda57e9c85ac8481c7ad3aa4a77e8c3c7000e80d3de809d2db7df6cb79e13fd258fff382729abf60 + languageName: node + linkType: hard + +"@next/mdx@npm:15.3.4": + version: 15.3.4 + resolution: "@next/mdx@npm:15.3.4" dependencies: source-map: "npm:^0.7.0" peerDependencies: @@ -530,69 +784,62 @@ __metadata: optional: true "@mdx-js/react": optional: true - checksum: 10/3b46e99934543df94bcb335dddab794db4fcaff09223343e9e00597d3df1e094f16dd619c433fb2fa7fff38c3da57b3118cbc010cdeb9790d0cf01e6c37016e8 + checksum: 10/07904beda049317e43857f9dfe659adb6e57c4417475de1d21a7605f8ace5d9aa992a06465d1a94fe4b62331901765b15659555e8aadedbd410f86df1bebd1bd languageName: node linkType: hard -"@next/swc-darwin-arm64@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-darwin-arm64@npm:14.2.26" +"@next/swc-darwin-arm64@npm:15.3.4": + version: 15.3.4 + resolution: "@next/swc-darwin-arm64@npm:15.3.4" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@next/swc-darwin-x64@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-darwin-x64@npm:14.2.26" +"@next/swc-darwin-x64@npm:15.3.4": + version: 15.3.4 + resolution: "@next/swc-darwin-x64@npm:15.3.4" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@next/swc-linux-arm64-gnu@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-linux-arm64-gnu@npm:14.2.26" +"@next/swc-linux-arm64-gnu@npm:15.3.4": + version: 15.3.4 + resolution: "@next/swc-linux-arm64-gnu@npm:15.3.4" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-arm64-musl@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-linux-arm64-musl@npm:14.2.26" +"@next/swc-linux-arm64-musl@npm:15.3.4": + version: 15.3.4 + resolution: "@next/swc-linux-arm64-musl@npm:15.3.4" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@next/swc-linux-x64-gnu@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-linux-x64-gnu@npm:14.2.26" +"@next/swc-linux-x64-gnu@npm:15.3.4": + version: 15.3.4 + resolution: "@next/swc-linux-x64-gnu@npm:15.3.4" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@next/swc-linux-x64-musl@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-linux-x64-musl@npm:14.2.26" +"@next/swc-linux-x64-musl@npm:15.3.4": + version: 15.3.4 + resolution: "@next/swc-linux-x64-musl@npm:15.3.4" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@next/swc-win32-arm64-msvc@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-win32-arm64-msvc@npm:14.2.26" +"@next/swc-win32-arm64-msvc@npm:15.3.4": + version: 15.3.4 + resolution: "@next/swc-win32-arm64-msvc@npm:15.3.4" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@next/swc-win32-ia32-msvc@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-win32-ia32-msvc@npm:14.2.26" - conditions: os=win32 & cpu=ia32 - languageName: node - linkType: hard - -"@next/swc-win32-x64-msvc@npm:14.2.26": - version: 14.2.26 - resolution: "@next/swc-win32-x64-msvc@npm:14.2.26" +"@next/swc-win32-x64-msvc@npm:15.3.4": + version: 15.3.4 + resolution: "@next/swc-win32-x64-msvc@npm:15.3.4" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -631,6 +878,28 @@ __metadata: languageName: node linkType: hard +"@npmcli/agent@npm:^3.0.0": + version: 3.0.0 + resolution: "@npmcli/agent@npm:3.0.0" + dependencies: + agent-base: "npm:^7.1.0" + http-proxy-agent: "npm:^7.0.0" + https-proxy-agent: "npm:^7.0.1" + lru-cache: "npm:^10.0.1" + socks-proxy-agent: "npm:^8.0.3" + checksum: 10/775c9a7eb1f88c195dfb3bce70c31d0fe2a12b28b754e25c08a3edb4bc4816bfedb7ac64ef1e730579d078ca19dacf11630e99f8f3c3e0fd7b23caa5fd6d30a6 + languageName: node + linkType: hard + +"@npmcli/fs@npm:^4.0.0": + version: 4.0.0 + resolution: "@npmcli/fs@npm:4.0.0" + dependencies: + semver: "npm:^7.3.5" + checksum: 10/405c4490e1ff11cf299775449a3c254a366a4b1ffc79d87159b0ee7d5558ac9f6a2f8c0735fd6ff3873cef014cb1a44a5f9127cb6a1b2dbc408718cca9365b5a + languageName: node + linkType: hard + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -645,97 +914,97 @@ __metadata: languageName: node linkType: hard -"@rushstack/eslint-patch@npm:^1.3.3": - version: 1.10.5 - resolution: "@rushstack/eslint-patch@npm:1.10.5" - checksum: 10/769d130dfb088c21e7ce72b552ea58c0d6d790cfe9fcadc4cd66e1282a0213a2c6b570d679723e0d3792a6b6ebfcbdeb5e785261d196017840853b8a5c57dfea +"@rushstack/eslint-patch@npm:^1.10.3": + version: 1.11.0 + resolution: "@rushstack/eslint-patch@npm:1.11.0" + checksum: 10/9bb3eb4a48a9a55e31d302b8b99f405e0f3e436fc3cda8c869fdd3fefd3ac398f5a353cceaa6c8cc5e5baf03ccd88d7965fbd25eb111f1f334415f95fa0f996d languageName: node linkType: hard -"@shikijs/core@npm:1.26.1": - version: 1.26.1 - resolution: "@shikijs/core@npm:1.26.1" +"@shikijs/core@npm:1.29.2": + version: 1.29.2 + resolution: "@shikijs/core@npm:1.29.2" dependencies: - "@shikijs/engine-javascript": "npm:1.26.1" - "@shikijs/engine-oniguruma": "npm:1.26.1" - "@shikijs/types": "npm:1.26.1" + "@shikijs/engine-javascript": "npm:1.29.2" + "@shikijs/engine-oniguruma": "npm:1.29.2" + "@shikijs/types": "npm:1.29.2" "@shikijs/vscode-textmate": "npm:^10.0.1" "@types/hast": "npm:^3.0.4" hast-util-to-html: "npm:^9.0.4" - checksum: 10/d70dd7e267da624bdc098f9f0295699d30d6bb0873a0c7f239f0664f253532af395208efe10cb0ad6f96b8c63fee439ce7ddbf5bd60b41149e2911fc3c55fc8f + checksum: 10/83dc5e86efc587d513268175ff43e8273567d2c6616d725bff15b08cf243d90f9371d6fa76ba49bb0e9823fc9947c8d8c650c81cfb19c3eb726178326f639a55 languageName: node linkType: hard -"@shikijs/engine-javascript@npm:1.26.1": - version: 1.26.1 - resolution: "@shikijs/engine-javascript@npm:1.26.1" +"@shikijs/engine-javascript@npm:1.29.2": + version: 1.29.2 + resolution: "@shikijs/engine-javascript@npm:1.29.2" dependencies: - "@shikijs/types": "npm:1.26.1" + "@shikijs/types": "npm:1.29.2" "@shikijs/vscode-textmate": "npm:^10.0.1" - oniguruma-to-es: "npm:0.10.0" - checksum: 10/fd7dac25fe4310bcd055af5163044fa598a65ec54376938f2ee70b8ab864a4d2f4bba2e76353d739ffcf071ffbc57b16147f47e5c9f950bf82f826cf88d3dd85 + oniguruma-to-es: "npm:^2.2.0" + checksum: 10/b49461ff7152650ffdbd77332d1c70e24a2ff1abe869e1038694b410194c6403fe5e8fce104fdd305d10c18702a50c1edbdb87172aa09f11340bc1203ed38488 languageName: node linkType: hard -"@shikijs/engine-oniguruma@npm:1.26.1": - version: 1.26.1 - resolution: "@shikijs/engine-oniguruma@npm:1.26.1" +"@shikijs/engine-oniguruma@npm:1.29.2": + version: 1.29.2 + resolution: "@shikijs/engine-oniguruma@npm:1.29.2" dependencies: - "@shikijs/types": "npm:1.26.1" + "@shikijs/types": "npm:1.29.2" "@shikijs/vscode-textmate": "npm:^10.0.1" - checksum: 10/17b3355fc226f58ef67d419c9e64a4dc99a63481c66f7ec55fdfb5035363605359414211e40ac8260db9c10c507e587dfac1061c0f57f111050e921e38cd58ef + checksum: 10/bb3e2c01da84d573251ebc289b1ecf815261024dea5bddb93ad56c3504a71cde3630db070be401ed3bbcd23a8a839ec78984a82317f9c9d0bba58daed935b781 languageName: node linkType: hard -"@shikijs/langs@npm:1.26.1": - version: 1.26.1 - resolution: "@shikijs/langs@npm:1.26.1" +"@shikijs/langs@npm:1.29.2": + version: 1.29.2 + resolution: "@shikijs/langs@npm:1.29.2" dependencies: - "@shikijs/types": "npm:1.26.1" - checksum: 10/b3909ffa30a89aa81e21da3c0af9388dfadab4f5ce9ce6f5a1cc3f7728e46702c02720123bad49dcd3f02e823c0ce9d533534164b0feb57856d2f8ee9504bce2 + "@shikijs/types": "npm:1.29.2" + checksum: 10/01f62d31c653c718a992918357e54d2d312c8da407997565fc19056fbf47f0fadc0f9f4b5fe1e1ba7b7d08e3984fb1f962159503ef0edd81fab5ee8bfdbf9080 languageName: node linkType: hard -"@shikijs/themes@npm:1.26.1": - version: 1.26.1 - resolution: "@shikijs/themes@npm:1.26.1" +"@shikijs/themes@npm:1.29.2": + version: 1.29.2 + resolution: "@shikijs/themes@npm:1.29.2" dependencies: - "@shikijs/types": "npm:1.26.1" - checksum: 10/5e2f5fe828f1b74dcc4027239768b3fe91567a5e07c3d014747627a7bd8a5ecf22460c59c20924172a96d99f4deed3e81e6f377e5f81239d6c6666d09e12fbd6 + "@shikijs/types": "npm:1.29.2" + checksum: 10/b81606dd882136e3fd751d0829133b5e66b10b8e32bd52ce16e7eac8755891c23e43f3ce06e65b97a75d2bc3b17e7fdb9115e9812679bb820ab163915868fd8b languageName: node linkType: hard -"@shikijs/types@npm:1.26.1": - version: 1.26.1 - resolution: "@shikijs/types@npm:1.26.1" +"@shikijs/types@npm:1.29.2": + version: 1.29.2 + resolution: "@shikijs/types@npm:1.29.2" dependencies: "@shikijs/vscode-textmate": "npm:^10.0.1" "@types/hast": "npm:^3.0.4" - checksum: 10/68ad9307424012cb833c02b7e0db4f0792d6ff9b633591318c76edb5a4ffb84da0de56dbe33b9b62ae810a878fdfd4f9ff6655a067997c664d9b0436266bcb16 + checksum: 10/579e64b6e8cb83023232b8060b08f51cff3909b199d0d1a0c58ed500c898dd34b74bf0457336fa2e6bee1005889e198d7d924347ad616eee30c6ae4c89a67ab8 languageName: node linkType: hard "@shikijs/vscode-textmate@npm:^10.0.1": - version: 10.0.1 - resolution: "@shikijs/vscode-textmate@npm:10.0.1" - checksum: 10/8bb005efbf472a9cac19bb5fb0bb1a2b612e128122e5a9d7b2bb2af674c29912db0e59c547ec458e5333f8f7ac7a8f054a24cb653f11dc20951e299933b416e4 + version: 10.0.2 + resolution: "@shikijs/vscode-textmate@npm:10.0.2" + checksum: 10/d924cba8a01cd9ca12f56ba097d628fdb81455abb85884c8d8a5ae85b628a37dd5907e7691019b97107bd6608c866adf91ba04a1c3bba391281c88e386c044ea languageName: node linkType: hard -"@storybook/components@npm:8.6.12": - version: 8.6.12 - resolution: "@storybook/components@npm:8.6.12" +"@storybook/components@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/components@npm:8.6.14" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/ccc6af275bdfbc66de8afb272f59b2b4b6b76bb2961903335cb62e7defae4a2368bd8f5a2008f8598dd8417e5368d824bce836ca96c3c6ff659dbf2f081ec0dd + checksum: 10/d3647505510313aa3c32fd1f8f202eda723ad99bd353b20aa929c5ecab4edc3c86ad06d0eac02f3c6d948e88f13f65ca5fa35ef27c079ef1b92abe8692f23699 languageName: node linkType: hard -"@storybook/core@npm:8.6.12": - version: 8.6.12 - resolution: "@storybook/core@npm:8.6.12" +"@storybook/core@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/core@npm:8.6.14" dependencies: - "@storybook/theming": "npm:8.6.12" + "@storybook/theming": "npm:8.6.14" better-opn: "npm:^3.0.2" browser-assert: "npm:^1.2.1" esbuild: "npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0" @@ -751,7 +1020,7 @@ __metadata: peerDependenciesMeta: prettier: optional: true - checksum: 10/78776f51b9eae00f9387421b33b646b1dc67ef833fd6272de03399daa7f0ffa248c65b5f24d5d2a9af923a029d06d84d5425e3455302ece542bf47c7a9ec0df6 + checksum: 10/8f8c811edd4ea8dcedcc63a79b3168dc83aa0401e3760990cb5995ea6beaac4026c6ccc1046182f41eed7c09333005f3348d8b42f89fc5dd5b2ce011a9d2a48f languageName: node linkType: hard @@ -762,92 +1031,91 @@ __metadata: languageName: node linkType: hard -"@storybook/manager-api@npm:8.6.12": - version: 8.6.12 - resolution: "@storybook/manager-api@npm:8.6.12" +"@storybook/manager-api@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/manager-api@npm:8.6.14" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/d1c44c6649a024c4007461c12a15337f5d13532dbaccc4c02f71bd99599fb973e2574eb8f1bc2d93e05da24e4ae43fa47ec637a7c4cccf5ffc67045cafbf087c + checksum: 10/4544b317050b81574f1cd6f911dcb99ee2adbd7190555209171a7dd2233cd331165fa11c16a5977ebe58eeaf26c86bbfcb23f701cfd79a10f0d034dae65197bd languageName: node linkType: hard -"@storybook/preview-api@npm:8.6.12": - version: 8.6.12 - resolution: "@storybook/preview-api@npm:8.6.12" +"@storybook/preview-api@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/preview-api@npm:8.6.14" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/d24f11e4e54e9e51297b0f87e1d462b3f14a974b4681f31d93b62b0706ce5b5ed4ffaaac521ec049dcb0e08e7aa7590f2e039aee4bbe9f85033d69474d982f23 + checksum: 10/9b77288f2f627a7c70cfd3e88bdc4348c1425fab6b333ed77efb913e45881bcdf2ca67f1174e47fe978a7993c2a653fb8accf518ba51441cfb9450145101e9d8 languageName: node linkType: hard -"@storybook/react-dom-shim@npm:8.6.12": - version: 8.6.12 - resolution: "@storybook/react-dom-shim@npm:8.6.12" +"@storybook/react-dom-shim@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/react-dom-shim@npm:8.6.14" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.6.12 - checksum: 10/7677b4fae978209af239471f9eb609db4318815bd4249a0f48b9875482d9ae910b93fbe4db5d7f794ecc2a1249edf40da26af9de673c941c48fccc4007819c96 + storybook: ^8.6.14 + checksum: 10/d14d970b98dc8266d4df80225538fb537449c15877f0f54465dfe52242f0c3f041c975824cc2894f72a3a8023fdffa0a281d90325b95297858e3684913b3cc15 languageName: node linkType: hard "@storybook/react@npm:^8.6.8": - version: 8.6.12 - resolution: "@storybook/react@npm:8.6.12" + version: 8.6.14 + resolution: "@storybook/react@npm:8.6.14" dependencies: - "@storybook/components": "npm:8.6.12" + "@storybook/components": "npm:8.6.14" "@storybook/global": "npm:^5.0.0" - "@storybook/manager-api": "npm:8.6.12" - "@storybook/preview-api": "npm:8.6.12" - "@storybook/react-dom-shim": "npm:8.6.12" - "@storybook/theming": "npm:8.6.12" + "@storybook/manager-api": "npm:8.6.14" + "@storybook/preview-api": "npm:8.6.14" + "@storybook/react-dom-shim": "npm:8.6.14" + "@storybook/theming": "npm:8.6.14" peerDependencies: - "@storybook/test": 8.6.12 + "@storybook/test": 8.6.14 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.6.12 + storybook: ^8.6.14 typescript: ">= 4.2.x" peerDependenciesMeta: "@storybook/test": optional: true typescript: optional: true - checksum: 10/d8258c82743906f48a872a781f3e5a63e9ce3fda2ba3b911e959cf62ebda43989b23746257d97905addb7142ac7e53d0089dc178bcbeea48ed4d37d025dd047b + checksum: 10/a8710dcb80da9df4a78cfb3560a8c0c31c6f6c04902aa95446d4e40f6a9179770ead6f9a0a06fa44d00677cd1cd92eb60fdc57f433035ec722275847139671a4 languageName: node linkType: hard -"@storybook/theming@npm:8.6.12": - version: 8.6.12 - resolution: "@storybook/theming@npm:8.6.12" +"@storybook/theming@npm:8.6.14": + version: 8.6.14 + resolution: "@storybook/theming@npm:8.6.14" peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - checksum: 10/c811d9dbb9eaaa680b922111fca126a2985f2238dfb01c1cd23184323eea12899dc9f079063ac42c5e63b0c83de326bd9cc17241e4060ff04e860c57a55fb8b9 + checksum: 10/6936ea3348968fe598ad47421c11a78c6ee2ce62336ea1ce9cb8257e9faa2553d3ac3e443f8a36d35a41b0d60eb169231516649c710582ec68fdead4f23ffc0e languageName: node linkType: hard -"@swc/counter@npm:^0.1.3": +"@swc/counter@npm:0.1.3": version: 0.1.3 resolution: "@swc/counter@npm:0.1.3" checksum: 10/df8f9cfba9904d3d60f511664c70d23bb323b3a0803ec9890f60133954173047ba9bdeabce28cd70ba89ccd3fd6c71c7b0bd58be85f611e1ffbe5d5c18616598 languageName: node linkType: hard -"@swc/helpers@npm:0.5.5": - version: 0.5.5 - resolution: "@swc/helpers@npm:0.5.5" +"@swc/helpers@npm:0.5.15": + version: 0.5.15 + resolution: "@swc/helpers@npm:0.5.15" dependencies: - "@swc/counter": "npm:^0.1.3" - tslib: "npm:^2.4.0" - checksum: 10/1c5ef04f642542212df28c669438f3e0f459dcde7b448a5b1fcafb2e9e4f13e76d8428535a270e91ed123dd2a21189dbed34086b88a8cf68baf84984d6d0e39b + tslib: "npm:^2.8.0" + checksum: 10/e3f32c6deeecfb0fa3f22edff03a7b358e7ce16d27b0f1c8b5cdc3042c5c4ce4da6eac0b781ab7cc4f54696ece657467d56734fb26883439fb00017385364c4c languageName: node linkType: hard -"@types/acorn@npm:^4.0.0": - version: 4.0.6 - resolution: "@types/acorn@npm:4.0.6" +"@tybys/wasm-util@npm:^0.9.0": + version: 0.9.0 + resolution: "@tybys/wasm-util@npm:0.9.0" dependencies: - "@types/estree": "npm:*" - checksum: 10/e00671d5055d06b07feccb8c2841467a4bdd1ab95a29e191d51cacc08c496e1ba1f54edeefab274bb2ba51cb45b0aaaa662a63897650e9d02e9997ad82124ae4 + tslib: "npm:^2.4.0" + checksum: 10/aa58e64753a420ad1eefaf7bacef3dda61d74f9336925943d9244132d5b48d9242f734f1e707fd5ccfa6dd1d8ec8e6debc234b4dedb3a5b0d8486d1f373350b2 languageName: node linkType: hard @@ -870,9 +1138,9 @@ __metadata: linkType: hard "@types/estree@npm:*, @types/estree@npm:^1.0.0": - version: 1.0.6 - resolution: "@types/estree@npm:1.0.6" - checksum: 10/9d35d475095199c23e05b431bcdd1f6fec7380612aed068b14b2a08aa70494de8a9026765a5a91b1073f636fb0368f6d8973f518a31391d519e20c59388ed88d + version: 1.0.8 + resolution: "@types/estree@npm:1.0.8" + checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 languageName: node linkType: hard @@ -892,7 +1160,7 @@ __metadata: languageName: node linkType: hard -"@types/mdast@npm:^4.0.0": +"@types/mdast@npm:^4.0.0, @types/mdast@npm:^4.0.4": version: 4.0.4 resolution: "@types/mdast@npm:4.0.4" dependencies: @@ -909,44 +1177,36 @@ __metadata: linkType: hard "@types/ms@npm:*": - version: 0.7.34 - resolution: "@types/ms@npm:0.7.34" - checksum: 10/f38d36e7b6edecd9badc9cf50474159e9da5fa6965a75186cceaf883278611b9df6669dc3a3cc122b7938d317b68a9e3d573d316fcb35d1be47ec9e468c6bd8a + version: 2.1.0 + resolution: "@types/ms@npm:2.1.0" + checksum: 10/532d2ebb91937ccc4a89389715e5b47d4c66e708d15942fe6cc25add6dc37b2be058230a327dd50f43f89b8b6d5d52b74685a9e8f70516edfc9bdd6be910eff4 languageName: node linkType: hard "@types/node@npm:^20": - version: 20.17.30 - resolution: "@types/node@npm:20.17.30" + version: 20.19.0 + resolution: "@types/node@npm:20.19.0" dependencies: - undici-types: "npm:~6.19.2" - checksum: 10/69fd3b177417be77b459e8f1dd4e78c85c686167086920fbf35a9fda301709bbeee6a87ad2591fb1ddd96c65e725ec6bb527a06496626a1c94367d1361048f8d + undici-types: "npm:~6.21.0" + checksum: 10/76cc44487faa0bf5302c84e5317de4b9727ea4e4b86d59d18d25435f4ccd7e6c584614dea061256f24a097c25a1d82dac1cd134357b42ae28006ba113c97f490 languageName: node linkType: hard -"@types/prop-types@npm:*": - version: 15.7.14 - resolution: "@types/prop-types@npm:15.7.14" - checksum: 10/d0c5407b9ccc3dd5fae0ccf9b1007e7622ba5e6f1c18399b4f24dff33619d469da4b9fa918a374f19dc0d9fe6a013362aab0b844b606cfc10676efba3f5f736d - languageName: node - linkType: hard - -"@types/react-dom@npm:^18.0.0": - version: 18.3.7 - resolution: "@types/react-dom@npm:18.3.7" +"@types/react-dom@npm:19.1.6": + version: 19.1.6 + resolution: "@types/react-dom@npm:19.1.6" peerDependencies: - "@types/react": ^18.0.0 - checksum: 10/317569219366d487a3103ba1e5e47154e95a002915fdcf73a44162c48fe49c3a57fcf7f57fc6979e70d447112681e6b13c6c3c1df289db8b544df4aab2d318f3 + "@types/react": ^19.0.0 + checksum: 10/b5b20b7f0797f34c5a11915b74dcf8b3b7a9da9fea90279975ce6f150ca5d31bb069dbb0838638a5e9e168098aa4bb4a6f61d078efa1bbb55d7f0bdfe47bb142 languageName: node linkType: hard -"@types/react@npm:^18.0.0": - version: 18.3.21 - resolution: "@types/react@npm:18.3.21" +"@types/react@npm:19.1.8": + version: 19.1.8 + resolution: "@types/react@npm:19.1.8" dependencies: - "@types/prop-types": "npm:*" csstype: "npm:^3.0.2" - checksum: 10/89adc2fe391fd63b620db0aaa10b2be89fad338039415fd748e60c962e47bf2b0f1897cb5226f181eda963f37a1c8ac1bf0b3b29a0e35313bacd0355e5d6c736 + checksum: 10/a3e6fe0f60f22828ef887f30993aa147b71532d7b1219dd00d246277eb7a9ca01ec533096237fa21ca1bccb3653373b4e8e59e5ae59f9c793058384bbc1f4d5c languageName: node linkType: hard @@ -965,120 +1225,144 @@ __metadata: linkType: hard "@typescript-eslint/eslint-plugin@npm:^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": - version: 8.19.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.19.1" + version: 8.34.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.34.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.19.1" - "@typescript-eslint/type-utils": "npm:8.19.1" - "@typescript-eslint/utils": "npm:8.19.1" - "@typescript-eslint/visitor-keys": "npm:8.19.1" + "@typescript-eslint/scope-manager": "npm:8.34.0" + "@typescript-eslint/type-utils": "npm:8.34.0" + "@typescript-eslint/utils": "npm:8.34.0" + "@typescript-eslint/visitor-keys": "npm:8.34.0" graphemer: "npm:^1.4.0" - ignore: "npm:^5.3.1" + ignore: "npm:^7.0.0" natural-compare: "npm:^1.4.0" - ts-api-utils: "npm:^2.0.0" + ts-api-utils: "npm:^2.1.0" peerDependencies: - "@typescript-eslint/parser": ^8.0.0 || ^8.0.0-alpha.0 + "@typescript-eslint/parser": ^8.34.0 eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10/c9a6d3181ec01068075b85ad3ac454910b4452281d60c775cc7229827f6d6a076b7336f5f07a7ad89bf08b3224f6a49aa20342b9438702393bee0aa7315d23b2 + typescript: ">=4.8.4 <5.9.0" + checksum: 10/224f9e8a596e3c37fade2f2a1a9efce2fad652a768710693458e2b7c7f88c3a0e7bbbbc46d34d839c9373861fac542de6b9a7e132e36e2819b63840b9529e605 languageName: node linkType: hard "@typescript-eslint/parser@npm:^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0": - version: 8.19.1 - resolution: "@typescript-eslint/parser@npm:8.19.1" + version: 8.34.0 + resolution: "@typescript-eslint/parser@npm:8.34.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.19.1" - "@typescript-eslint/types": "npm:8.19.1" - "@typescript-eslint/typescript-estree": "npm:8.19.1" - "@typescript-eslint/visitor-keys": "npm:8.19.1" + "@typescript-eslint/scope-manager": "npm:8.34.0" + "@typescript-eslint/types": "npm:8.34.0" + "@typescript-eslint/typescript-estree": "npm:8.34.0" + "@typescript-eslint/visitor-keys": "npm:8.34.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10/da3db63ff655cf0fb91745ba8e52d853386f601cf6106d36f4541efcb9e2c6c3b82c6743b15680eff9eafeccaf31c9b26191a955e66ae19de9172f67335463ab + typescript: ">=4.8.4 <5.9.0" + checksum: 10/b4c03ff2f09fd800a8f28c24289d24e2f4bfb4745c122f5f496bf832b06f0f37b1ab31ce8d7590ff1f83253de3306d145ef7b3c7b853a4ae716cb7ff443d1c27 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.19.1": - version: 8.19.1 - resolution: "@typescript-eslint/scope-manager@npm:8.19.1" +"@typescript-eslint/project-service@npm:8.34.0": + version: 8.34.0 + resolution: "@typescript-eslint/project-service@npm:8.34.0" dependencies: - "@typescript-eslint/types": "npm:8.19.1" - "@typescript-eslint/visitor-keys": "npm:8.19.1" - checksum: 10/6ffc78b15367f211eb6650459ca2bb6bfe4c1fa95a3474adc08ee9a20c250b2e0e02fd99be36bd3dad74967ecd9349e792b5d818d85735cba40f1b5c236074d1 - languageName: node - linkType: hard - -"@typescript-eslint/type-utils@npm:8.19.1": - version: 8.19.1 - resolution: "@typescript-eslint/type-utils@npm:8.19.1" - dependencies: - "@typescript-eslint/typescript-estree": "npm:8.19.1" - "@typescript-eslint/utils": "npm:8.19.1" + "@typescript-eslint/tsconfig-utils": "npm:^8.34.0" + "@typescript-eslint/types": "npm:^8.34.0" debug: "npm:^4.3.4" - ts-api-utils: "npm:^2.0.0" + peerDependencies: + typescript: ">=4.8.4 <5.9.0" + checksum: 10/04763896215c208c6b29e0b4f66ee0621878cd88fb6d9008c543db57f1d6b5d7fcc88f048c9a66ba2ed797f68e563c350e1b65403349ef75a4bc419072cef3c8 + languageName: node + linkType: hard + +"@typescript-eslint/scope-manager@npm:8.34.0": + version: 8.34.0 + resolution: "@typescript-eslint/scope-manager@npm:8.34.0" + dependencies: + "@typescript-eslint/types": "npm:8.34.0" + "@typescript-eslint/visitor-keys": "npm:8.34.0" + checksum: 10/fec7bb94fb3848bdf5ab9cfaf634e56aec3ed9bc4d546f65d83bb6511452e5a4b9eed5d09f54efceb9fa3b23a451d409735359237e8c0d51233d6537e5449fa7 + languageName: node + linkType: hard + +"@typescript-eslint/tsconfig-utils@npm:8.34.0, @typescript-eslint/tsconfig-utils@npm:^8.34.0": + version: 8.34.0 + resolution: "@typescript-eslint/tsconfig-utils@npm:8.34.0" + peerDependencies: + typescript: ">=4.8.4 <5.9.0" + checksum: 10/cbbca9526bd9c0309c77f9436f68c2c06712779a593a17757f1f7558ece27d9f40db2b37ebf12bd9e19cf227479083b7973c502436a0954a08406d8a598910ba + languageName: node + linkType: hard + +"@typescript-eslint/type-utils@npm:8.34.0": + version: 8.34.0 + resolution: "@typescript-eslint/type-utils@npm:8.34.0" + dependencies: + "@typescript-eslint/typescript-estree": "npm:8.34.0" + "@typescript-eslint/utils": "npm:8.34.0" + debug: "npm:^4.3.4" + ts-api-utils: "npm:^2.1.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10/123ecda88b057d6a4b68226701f435661440a420fda88cba60b49d7fb3e4f49483164ff174f259e28c0beabb0ed04500462a20faefd78331ba202bf54b01e3ef + typescript: ">=4.8.4 <5.9.0" + checksum: 10/e7c565868b18d66ce5de016455c5ba2dc625a845e05ad563bfdf08b1753faa11d9aef22b9dc5071c57b6e73932748505715e7b47993757f1bc244d4d6f70d688 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.19.1": - version: 8.19.1 - resolution: "@typescript-eslint/types@npm:8.19.1" - checksum: 10/5833a5f8fdac4a490dd3906a0243a0713fbf138fabb451870c70b0b089c539a9624b467b0913ddc0a225a8284342e7fd31cd506dec53c1a6d8f3c8c8902b9cae +"@typescript-eslint/types@npm:8.34.0, @typescript-eslint/types@npm:^8.34.0": + version: 8.34.0 + resolution: "@typescript-eslint/types@npm:8.34.0" + checksum: 10/da4dcee51e78139bdeb5832df836528c519a22c2e39b7737ae660afe024576030165424079f423a131ad56e2dca8f033943d6b48a54b4f4d296a6f7f83f5b494 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.19.1": - version: 8.19.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.19.1" +"@typescript-eslint/typescript-estree@npm:8.34.0": + version: 8.34.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.34.0" dependencies: - "@typescript-eslint/types": "npm:8.19.1" - "@typescript-eslint/visitor-keys": "npm:8.19.1" + "@typescript-eslint/project-service": "npm:8.34.0" + "@typescript-eslint/tsconfig-utils": "npm:8.34.0" + "@typescript-eslint/types": "npm:8.34.0" + "@typescript-eslint/visitor-keys": "npm:8.34.0" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" minimatch: "npm:^9.0.4" semver: "npm:^7.6.0" - ts-api-utils: "npm:^2.0.0" + ts-api-utils: "npm:^2.1.0" peerDependencies: - typescript: ">=4.8.4 <5.8.0" - checksum: 10/5de467452d5ef1a380d441b06cd0134652a0c98cdb4ce31b93eb589f7dc75ef60364d03fd80ca0a48d0c8b268f7258d4f6528b16fe1b89442d60a4bc960fe5f5 + typescript: ">=4.8.4 <5.9.0" + checksum: 10/26817d4c948253eb6a8f49fcd7a8f74c4ffeae7943aef9e1cb90d1b7adbc8e0f66605b0b318dc6eee3eda212882e278a300776b26fe4e2319712cd9822a3a4e4 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.19.1": - version: 8.19.1 - resolution: "@typescript-eslint/utils@npm:8.19.1" +"@typescript-eslint/utils@npm:8.34.0": + version: 8.34.0 + resolution: "@typescript-eslint/utils@npm:8.34.0" dependencies: - "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.19.1" - "@typescript-eslint/types": "npm:8.19.1" - "@typescript-eslint/typescript-estree": "npm:8.19.1" + "@eslint-community/eslint-utils": "npm:^4.7.0" + "@typescript-eslint/scope-manager": "npm:8.34.0" + "@typescript-eslint/types": "npm:8.34.0" + "@typescript-eslint/typescript-estree": "npm:8.34.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: ">=4.8.4 <5.8.0" - checksum: 10/bb92116a53fe143ee87e830941afb21d4222a64ca3f2b6dac5c2d9984f981408e60e52b04c32d95208896075ac222fb4ee631c5b0c4826b87d4bd8091c421ab1 + typescript: ">=4.8.4 <5.9.0" + checksum: 10/c51d2015e8076dd2a9d8255746889130aaf298cf9ff8f73114dcf7148f34536d47d883880eec7e3d89ec3f746c2d3f2b749e8fef5e8ad9914132deb5c013efbd languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.19.1": - version: 8.19.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.19.1" +"@typescript-eslint/visitor-keys@npm:8.34.0": + version: 8.34.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.34.0" dependencies: - "@typescript-eslint/types": "npm:8.19.1" + "@typescript-eslint/types": "npm:8.34.0" eslint-visitor-keys: "npm:^4.2.0" - checksum: 10/510eb196e7b7d59d3981d672a75454615159e931fe78e2a64b09607c3cfa45110709b0eb5ac3dd271d757a0d98cf4868ad2f45bf9193f96e9efec3efa92a19c1 + checksum: 10/8a591cb9f922b6fd92107ebdf255425cf7ecd56281d032d944fb38e6be319e6cca7dc49bab6ad1d46390d2ca023c3413c03775e638ec5fd70172150debf7636a languageName: node linkType: hard -"@uiw/codemirror-extensions-basic-setup@npm:4.23.7": - version: 4.23.7 - resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.23.7" +"@uiw/codemirror-extensions-basic-setup@npm:4.23.13": + version: 4.23.13 + resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.23.13" dependencies: "@codemirror/autocomplete": "npm:^6.0.0" "@codemirror/commands": "npm:^6.0.0" @@ -1095,13 +1379,13 @@ __metadata: "@codemirror/search": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 10/7b8cbb9ccc931bc1a6909d009e653f78797e4b851aa9fb8e11f90ae1cea233e643a1951ad4ad9e10123ef166808acee1acff24732ea9fc15cd77164f6b179b91 + checksum: 10/35fd1894f9f7da8f94fa077a70821f92118597e2e2b12782b254b0844f06c1855508421c4cb47de7099a972ef706218c08203116aa93da4e8e1585c8d234015d languageName: node linkType: hard "@uiw/codemirror-themes@npm:^4.23.7": - version: 4.23.12 - resolution: "@uiw/codemirror-themes@npm:4.23.12" + version: 4.23.13 + resolution: "@uiw/codemirror-themes@npm:4.23.13" dependencies: "@codemirror/language": "npm:^6.0.0" "@codemirror/state": "npm:^6.0.0" @@ -1110,19 +1394,19 @@ __metadata: "@codemirror/language": ">=6.0.0" "@codemirror/state": ">=6.0.0" "@codemirror/view": ">=6.0.0" - checksum: 10/472121efadf2b9eb110030f06d657cb9693861e1ca360c81c7b0d7aa4533e6e6791737dfd14bcbe496bcb818d33f4cf6a18caf504ec628807e273441f969ef83 + checksum: 10/8c168ed1aa6185c4cc92b66f873e38f6bb50778f1ccadcc99db04cbe97c928e7b924a2f41cb40c4b26328489038d986fe9360605e1668e6c0af2ba931b79523e languageName: node linkType: hard "@uiw/react-codemirror@npm:^4.23.7": - version: 4.23.7 - resolution: "@uiw/react-codemirror@npm:4.23.7" + version: 4.23.13 + resolution: "@uiw/react-codemirror@npm:4.23.13" dependencies: "@babel/runtime": "npm:^7.18.6" "@codemirror/commands": "npm:^6.1.0" "@codemirror/state": "npm:^6.1.1" "@codemirror/theme-one-dark": "npm:^6.0.0" - "@uiw/codemirror-extensions-basic-setup": "npm:4.23.7" + "@uiw/codemirror-extensions-basic-setup": "npm:4.23.13" codemirror: "npm:^6.0.0" peerDependencies: "@babel/runtime": ">=7.11.0" @@ -1132,14 +1416,142 @@ __metadata: codemirror: ">=6.0.0" react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 10/dc6f1fd2f1863120e29ea331b2e279054bf508f00656d3fed97779f17818ae00b6cf9d74d3b0996800174d444b59702da74ca88c303db563daad85c0824fc952 + checksum: 10/51777d7eb313be0716d3597f829e6ee9982ab2dc3e36dc5219f25cdf680b82a6c0a0951d9adaca85b9c829da92f7971aa6e65bdd50e7610972d89463fe2587a1 languageName: node linkType: hard "@ungap/structured-clone@npm:^1.0.0, @ungap/structured-clone@npm:^1.2.0": - version: 1.2.1 - resolution: "@ungap/structured-clone@npm:1.2.1" - checksum: 10/6770f71e8183311b2871601ddb02d62a26373be7cf2950cb546a345a2305c75b502e36ce80166120aa2f5f1ea1562141684651ebbfcc711c58acd32035d3e545 + version: 1.3.0 + resolution: "@ungap/structured-clone@npm:1.3.0" + checksum: 10/80d6910946f2b1552a2406650051c91bbd1f24a6bf854354203d84fe2714b3e8ce4618f49cc3410494173a1c1e8e9777372fe68dce74bd45faf0a7a1a6ccf448 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-arm64@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-darwin-arm64@npm:1.7.13" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-darwin-x64@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-darwin-x64@npm:1.7.13" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-freebsd-x64@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-freebsd-x64@npm:1.7.13" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-arm-gnueabihf@npm:1.7.13" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm-musleabihf@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-arm-musleabihf@npm:1.7.13" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-gnu@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-arm64-gnu@npm:1.7.13" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-arm64-musl@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-arm64-musl@npm:1.7.13" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-ppc64-gnu@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-ppc64-gnu@npm:1.7.13" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-gnu@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-riscv64-gnu@npm:1.7.13" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-riscv64-musl@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-riscv64-musl@npm:1.7.13" + conditions: os=linux & cpu=riscv64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-s390x-gnu@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-s390x-gnu@npm:1.7.13" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-gnu@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-x64-gnu@npm:1.7.13" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@unrs/resolver-binding-linux-x64-musl@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-linux-x64-musl@npm:1.7.13" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@unrs/resolver-binding-wasm32-wasi@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-wasm32-wasi@npm:1.7.13" + dependencies: + "@napi-rs/wasm-runtime": "npm:^0.2.11" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-arm64-msvc@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-win32-arm64-msvc@npm:1.7.13" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-ia32-msvc@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-win32-ia32-msvc@npm:1.7.13" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@unrs/resolver-binding-win32-x64-msvc@npm:1.7.13": + version: 1.7.13 + resolution: "@unrs/resolver-binding-win32-x64-msvc@npm:1.7.13" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"abbrev@npm:^3.0.0": + version: 3.0.1 + resolution: "abbrev@npm:3.0.1" + checksum: 10/ebd2c149dda6f543b66ce3779ea612151bb3aa9d0824f169773ee9876f1ca5a4e0adbcccc7eed048c04da7998e1825e2aa76fcca92d9e67dea50ac2b0a58dc2e languageName: node linkType: hard @@ -1153,11 +1565,18 @@ __metadata: linkType: hard "acorn@npm:^8.0.0, acorn@npm:^8.9.0": - version: 8.14.0 - resolution: "acorn@npm:8.14.0" + version: 8.15.0 + resolution: "acorn@npm:8.15.0" bin: acorn: bin/acorn - checksum: 10/6df29c35556782ca9e632db461a7f97947772c6c1d5438a81f0c873a3da3a792487e83e404d1c6c25f70513e91aa18745f6eafb1fcc3a43ecd1920b21dd173d2 + checksum: 10/77f2de5051a631cf1729c090e5759148459cdb76b5f5c70f890503d629cf5052357b0ce783c0f976dd8a93c5150f59f6d18df1def3f502396a20f81282482fa4 + languageName: node + linkType: hard + +"agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": + version: 7.1.3 + resolution: "agent-base@npm:7.1.3" + checksum: 10/3db6d8d4651f2aa1a9e4af35b96ab11a7607af57a24f3bc721a387eaa3b5f674e901f0a648b0caefd48f3fd117c7761b79a3b55854e2aebaa96c3f32cf76af84 languageName: node linkType: hard @@ -1203,6 +1622,16 @@ __metadata: languageName: node linkType: hard +"anymatch@npm:~3.1.2": + version: 3.1.3 + resolution: "anymatch@npm:3.1.3" + dependencies: + normalize-path: "npm:^3.0.0" + picomatch: "npm:^2.0.4" + checksum: 10/3e044fd6d1d26545f235a9fe4d7a534e2029d8e59fa7fd9f2a6eb21230f6b5380ea1eaf55136e60cbf8e613544b3b766e7a6fa2102e2a3a117505466e3025dc2 + languageName: node + linkType: hard + "argparse@npm:^2.0.1": version: 2.0.1 resolution: "argparse@npm:2.0.1" @@ -1228,16 +1657,18 @@ __metadata: linkType: hard "array-includes@npm:^3.1.6, array-includes@npm:^3.1.8": - version: 3.1.8 - resolution: "array-includes@npm:3.1.8" + version: 3.1.9 + resolution: "array-includes@npm:3.1.9" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" - es-object-atoms: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.4" - is-string: "npm:^1.0.7" - checksum: 10/290b206c9451f181fb2b1f79a3bf1c0b66bb259791290ffbada760c79b284eef6f5ae2aeb4bcff450ebc9690edd25732c4c73a3c2b340fcc0f4563aed83bf488 + es-abstract: "npm:^1.24.0" + es-object-atoms: "npm:^1.1.1" + get-intrinsic: "npm:^1.3.0" + is-string: "npm:^1.1.1" + math-intrinsics: "npm:^1.1.0" + checksum: 10/8bfe9a58df74f326b4a76b04ee05c13d871759e888b4ee8f013145297cf5eb3c02cfa216067ebdaac5d74eb9763ac5cad77cdf2773b8ab475833701e032173aa languageName: node linkType: hard @@ -1256,16 +1687,17 @@ __metadata: linkType: hard "array.prototype.findlastindex@npm:^1.2.5": - version: 1.2.5 - resolution: "array.prototype.findlastindex@npm:1.2.5" + version: 1.2.6 + resolution: "array.prototype.findlastindex@npm:1.2.6" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-abstract: "npm:^1.23.2" + es-abstract: "npm:^1.23.9" es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" - es-shim-unscopables: "npm:^1.0.2" - checksum: 10/7c5c821f357cd53ab6cc305de8086430dd8d7a2485db87b13f843e868055e9582b1fd338f02338f67fc3a1603ceaf9610dd2a470b0b506f9d18934780f95b246 + es-object-atoms: "npm:^1.1.1" + es-shim-unscopables: "npm:^1.1.0" + checksum: 10/5ddb6420e820bef6ddfdcc08ce780d0fd5e627e97457919c27e32359916de5a11ce12f7c55073555e503856618eaaa70845d6ca11dcba724766f38eb1c22f7a2 languageName: node linkType: hard @@ -1346,6 +1778,13 @@ __metadata: languageName: node linkType: hard +"async-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-function@npm:1.0.0" + checksum: 10/1a09379937d846f0ce7614e75071c12826945d4e417db634156bf0e4673c495989302f52186dfa9767a1d9181794554717badd193ca2bbab046ef1da741d8efd + languageName: node + linkType: hard + "available-typed-arrays@npm:^1.0.7": version: 1.0.7 resolution: "available-typed-arrays@npm:1.0.7" @@ -1356,9 +1795,9 @@ __metadata: linkType: hard "axe-core@npm:^4.10.0": - version: 4.10.2 - resolution: "axe-core@npm:4.10.2" - checksum: 10/a69423b2ff16c15922c4ea7cf9cc5112728a2817bbe0f2cc212248d648885ffd1ba554e3a341dfc289cd9e67fc0d06f333b5c6837c5c38ca6652507381216fc1 + version: 4.10.3 + resolution: "axe-core@npm:4.10.3" + checksum: 10/9ff51ad0fd0fdec5c0247ea74e8ace5990b54c7f01f8fa3e5cd8ba98b0db24d8ebd7bab4a9bd4d75c28c4edcd1eac455b44c8c6c258c6a98f3d2f88bc60af4cc languageName: node linkType: hard @@ -1392,26 +1831,33 @@ __metadata: languageName: node linkType: hard +"binary-extensions@npm:^2.0.0": + version: 2.3.0 + resolution: "binary-extensions@npm:2.3.0" + checksum: 10/bcad01494e8a9283abf18c1b967af65ee79b0c6a9e6fcfafebfe91dbe6e0fc7272bafb73389e198b310516ae04f7ad17d79aacf6cb4c0d5d5202a7e2e52c7d98 + languageName: node + linkType: hard + "brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" + version: 1.1.12 + resolution: "brace-expansion@npm:1.1.12" dependencies: balanced-match: "npm:^1.0.0" concat-map: "npm:0.0.1" - checksum: 10/faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + checksum: 10/12cb6d6310629e3048cadb003e1aca4d8c9bb5c67c3c321bafdd7e7a50155de081f78ea3e0ed92ecc75a9015e784f301efc8132383132f4f7904ad1ac529c562 languageName: node linkType: hard "brace-expansion@npm:^2.0.1": - version: 2.0.1 - resolution: "brace-expansion@npm:2.0.1" + version: 2.0.2 + resolution: "brace-expansion@npm:2.0.2" dependencies: balanced-match: "npm:^1.0.0" - checksum: 10/a61e7cd2e8a8505e9f0036b3b6108ba5e926b4b55089eeb5550cd04a471fe216c96d4fe7e4c7f995c728c554ae20ddfc4244cad10aef255e72b62930afd233d1 + checksum: 10/01dff195e3646bc4b0d27b63d9bab84d2ebc06121ff5013ad6e5356daa5a9d6b60fa26cf73c74797f2dc3fbec112af13578d51f75228c1112b26c790a87b0488 languageName: node linkType: hard -"braces@npm:^3.0.3": +"braces@npm:^3.0.3, braces@npm:~3.0.2": version: 3.0.3 resolution: "braces@npm:3.0.3" dependencies: @@ -1436,6 +1882,26 @@ __metadata: languageName: node linkType: hard +"cacache@npm:^19.0.1": + version: 19.0.1 + resolution: "cacache@npm:19.0.1" + dependencies: + "@npmcli/fs": "npm:^4.0.0" + fs-minipass: "npm:^3.0.0" + glob: "npm:^10.2.2" + lru-cache: "npm:^10.0.1" + minipass: "npm:^7.0.3" + minipass-collect: "npm:^2.0.1" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + p-map: "npm:^7.0.2" + ssri: "npm:^12.0.0" + tar: "npm:^7.4.3" + unique-filename: "npm:^4.0.0" + checksum: 10/ea026b27b13656330c2bbaa462a88181dcaa0435c1c2e705db89b31d9bdf7126049d6d0445ba746dca21454a0cfdf1d6f47fd39d34c8c8435296b30bc5738a13 + languageName: node + linkType: hard + "call-bind-apply-helpers@npm:^1.0.0, call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": version: 1.0.2 resolution: "call-bind-apply-helpers@npm:1.0.2" @@ -1476,9 +1942,9 @@ __metadata: linkType: hard "caniuse-lite@npm:^1.0.30001579": - version: 1.0.30001690 - resolution: "caniuse-lite@npm:1.0.30001690" - checksum: 10/9fb4659eb09a298601b9593739072c481e2f5cc524bd0530e5e0f002e66246da5e866669854dfc0d53195ee36b201dab02f7933a7cdf60ccba7adb2d4a304caf + version: 1.0.30001722 + resolution: "caniuse-lite@npm:1.0.30001722" + checksum: 10/60ad52c891221c894085d450c7308f94768702bed4f0b4b99199e3c3c5926b22d7c7c05f474fcdb484befbd43d1975f8529c8ad8f66770f5c32c5342716ecd0b languageName: node linkType: hard @@ -1487,24 +1953,30 @@ __metadata: resolution: "canon-docs@workspace:." dependencies: "@codemirror/lang-sass": "npm:^6.0.2" + "@codemirror/view": "npm:^6.34.4" "@lezer/highlight": "npm:^1.2.1" "@mdx-js/loader": "npm:^3.1.0" "@mdx-js/react": "npm:^3.1.0" - "@next/mdx": "npm:^15.1.4" + "@next/mdx": "npm:15.3.4" "@storybook/react": "npm:^8.6.8" "@types/mdx": "npm:^2.0.13" "@types/node": "npm:^20" - "@types/react": "npm:^18.0.0" - "@types/react-dom": "npm:^18.0.0" + "@types/react": "npm:19.1.8" + "@types/react-dom": "npm:19.1.6" "@uiw/codemirror-themes": "npm:^4.23.7" "@uiw/react-codemirror": "npm:^4.23.7" + chokidar: "npm:^3.6.0" + concurrently: "npm:^8.2.2" eslint: "npm:^8" - eslint-config-next: "npm:14.2.23" + eslint-config-next: "npm:15.3.4" + html-react-parser: "npm:^5.2.5" lightningcss: "npm:^1.28.2" motion: "npm:^12.4.1" - next: "npm:14.2.26" - react: "npm:^18.0.2" - react-dom: "npm:^18.0.2" + next: "npm:15.3.4" + next-mdx-remote-client: "npm:^2.1.2" + prop-types: "npm:^15.8.1" + react: "npm:19.1.0" + react-dom: "npm:19.1.0" react-frame-component: "npm:^5.2.7" shiki: "npm:^1.26.1" storybook: "npm:^8.6.8" @@ -1519,7 +1991,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^4.0.0": +"chalk@npm:^4.0.0, chalk@npm:^4.1.2": version: 4.1.2 resolution: "chalk@npm:4.1.2" dependencies: @@ -1557,6 +2029,32 @@ __metadata: languageName: node linkType: hard +"chokidar@npm:^3.6.0": + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" + dependencies: + anymatch: "npm:~3.1.2" + braces: "npm:~3.0.2" + fsevents: "npm:~2.3.2" + glob-parent: "npm:~5.1.2" + is-binary-path: "npm:~2.1.0" + is-glob: "npm:~4.0.1" + normalize-path: "npm:~3.0.0" + readdirp: "npm:~3.6.0" + dependenciesMeta: + fsevents: + optional: true + checksum: 10/c327fb07704443f8d15f7b4a7ce93b2f0bc0e6cea07ec28a7570aa22cd51fcf0379df589403976ea956c369f25aa82d84561947e227cd925902e1751371658df + languageName: node + linkType: hard + +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10/b63cb1f73d171d140a2ed8154ee6566c8ab775d3196b0e03a2a94b5f6a0ce7777ee5685ca56849403c8d17bd457a6540672f9a60696a6137c7a409097495b82c + languageName: node + linkType: hard + "client-only@npm:0.0.1": version: 0.0.1 resolution: "client-only@npm:0.0.1" @@ -1564,6 +2062,17 @@ __metadata: languageName: node linkType: hard +"cliui@npm:^8.0.1": + version: 8.0.1 + resolution: "cliui@npm:8.0.1" + dependencies: + string-width: "npm:^4.2.0" + strip-ansi: "npm:^6.0.1" + wrap-ansi: "npm:^7.0.0" + checksum: 10/eaa5561aeb3135c2cddf7a3b3f562fc4238ff3b3fc666869ef2adf264be0f372136702f16add9299087fb1907c2e4ec5dbfe83bd24bce815c70a80c6c1a2e950 + languageName: node + linkType: hard + "codemirror@npm:^6.0.0": version: 6.0.1 resolution: "codemirror@npm:6.0.1" @@ -1595,13 +2104,33 @@ __metadata: languageName: node linkType: hard -"color-name@npm:~1.1.4": +"color-name@npm:^1.0.0, color-name@npm:~1.1.4": version: 1.1.4 resolution: "color-name@npm:1.1.4" checksum: 10/b0445859521eb4021cd0fb0cc1a75cecf67fceecae89b63f62b201cca8d345baf8b952c966862a9d9a2632987d4f6581f0ec8d957dfacece86f0a7919316f610 languageName: node linkType: hard +"color-string@npm:^1.9.0": + version: 1.9.1 + resolution: "color-string@npm:1.9.1" + dependencies: + color-name: "npm:^1.0.0" + simple-swizzle: "npm:^0.2.2" + checksum: 10/72aa0b81ee71b3f4fb1ac9cd839cdbd7a011a7d318ef58e6cb13b3708dca75c7e45029697260488709f1b1c7ac4e35489a87e528156c1e365917d1c4ccb9b9cd + languageName: node + linkType: hard + +"color@npm:^4.2.3": + version: 4.2.3 + resolution: "color@npm:4.2.3" + dependencies: + color-convert: "npm:^2.0.1" + color-string: "npm:^1.9.0" + checksum: 10/b23f5e500a79ea22428db43d1a70642d983405c0dd1f95ef59dbdb9ba66afbb4773b334fa0b75bb10b0552fd7534c6b28d4db0a8b528f91975976e70973c0152 + languageName: node + linkType: hard + "comma-separated-tokens@npm:^2.0.0": version: 2.0.3 resolution: "comma-separated-tokens@npm:2.0.3" @@ -1616,14 +2145,34 @@ __metadata: languageName: node linkType: hard -"crelt@npm:^1.0.5": +"concurrently@npm:^8.2.2": + version: 8.2.2 + resolution: "concurrently@npm:8.2.2" + dependencies: + chalk: "npm:^4.1.2" + date-fns: "npm:^2.30.0" + lodash: "npm:^4.17.21" + rxjs: "npm:^7.8.1" + shell-quote: "npm:^1.8.1" + spawn-command: "npm:0.0.2" + supports-color: "npm:^8.1.1" + tree-kill: "npm:^1.2.2" + yargs: "npm:^17.7.2" + bin: + conc: dist/bin/concurrently.js + concurrently: dist/bin/concurrently.js + checksum: 10/dcb1aa69d9c611a7bda9d4fc0fe1e388f971d1744acec7e0d52dffa2ef55743f1266ec9292f414c5789b9f61734b3fce772bd005d4de9564a949fb121b97bae1 + languageName: node + linkType: hard + +"crelt@npm:^1.0.5, crelt@npm:^1.0.6": version: 1.0.6 resolution: "crelt@npm:1.0.6" checksum: 10/5ed326ca6bd243b1dba6b943f665b21c2c04be03271824bc48f20dba324b0f8233e221f8c67312526d24af2b1243c023dc05a41bd8bd05d1a479fd2c72fb39c3 languageName: node linkType: hard -"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.2": +"cross-spawn@npm:^7.0.2, cross-spawn@npm:^7.0.6": version: 7.0.6 resolution: "cross-spawn@npm:7.0.6" dependencies: @@ -1681,6 +2230,27 @@ __metadata: languageName: node linkType: hard +"date-fns@npm:^2.30.0": + version: 2.30.0 + resolution: "date-fns@npm:2.30.0" + dependencies: + "@babel/runtime": "npm:^7.21.0" + checksum: 10/70b3e8ea7aaaaeaa2cd80bd889622a4bcb5d8028b4de9162cbcda359db06e16ff6e9309e54eead5341e71031818497f19aaf9839c87d1aba1e27bb4796e758a9 + languageName: node + linkType: hard + +"debug@npm:4, debug@npm:^4.0.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.4.0": + version: 4.4.1 + resolution: "debug@npm:4.4.1" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10/8e2709b2144f03c7950f8804d01ccb3786373df01e406a0f66928e47001cf2d336cbed9ee137261d4f90d68d8679468c755e3548ed83ddacdc82b194d2468afe + languageName: node + linkType: hard + "debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" @@ -1690,24 +2260,12 @@ __metadata: languageName: node linkType: hard -"debug@npm:^4.0.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.4, debug@npm:^4.3.7": - version: 4.4.0 - resolution: "debug@npm:4.4.0" - dependencies: - ms: "npm:^2.1.3" - peerDependenciesMeta: - supports-color: - optional: true - checksum: 10/1847944c2e3c2c732514b93d11886575625686056cd765336212dc15de2d2b29612b6cd80e1afba767bb8e1803b778caf9973e98169ef1a24a7a7009e1820367 - languageName: node - linkType: hard - "decode-named-character-reference@npm:^1.0.0": - version: 1.0.2 - resolution: "decode-named-character-reference@npm:1.0.2" + version: 1.1.0 + resolution: "decode-named-character-reference@npm:1.1.0" dependencies: character-entities: "npm:^2.0.0" - checksum: 10/f4c71d3b93105f20076052f9cb1523a22a9c796b8296cd35eef1ca54239c78d182c136a848b83ff8da2071e3ae2b1d300bf29d00650a6d6e675438cc31b11d78 + checksum: 10/102970fde2d011f307d3789776e68defd75ba4ade1a34951affd1fabb86cd32026fd809f2658c2b600d839a57b6b6a84e2b3a45166d38c8625d66ca11cd702b8 languageName: node linkType: hard @@ -1754,10 +2312,10 @@ __metadata: languageName: node linkType: hard -"detect-libc@npm:^2.0.3": - version: 2.0.3 - resolution: "detect-libc@npm:2.0.3" - checksum: 10/b4ea018d623e077bd395f168a9e81db77370dde36a5b01d067f2ad7989924a81d31cb547ff764acb2aa25d50bb7fdde0b0a93bec02212b0cb430621623246d39 +"detect-libc@npm:^2.0.3, detect-libc@npm:^2.0.4": + version: 2.0.4 + resolution: "detect-libc@npm:2.0.4" + checksum: 10/136e995f8c5ffbc515955b0175d441b967defd3d5f2268e89fa695e9c7170d8bed17993e31a34b04f0fad33d844a3a598e0fd519a8e9be3cad5f67662d96fee0 languageName: node linkType: hard @@ -1788,6 +2346,44 @@ __metadata: languageName: node linkType: hard +"dom-serializer@npm:^2.0.0": + version: 2.0.0 + resolution: "dom-serializer@npm:2.0.0" + dependencies: + domelementtype: "npm:^2.3.0" + domhandler: "npm:^5.0.2" + entities: "npm:^4.2.0" + checksum: 10/e3bf9027a64450bca0a72297ecdc1e3abb7a2912268a9f3f5d33a2e29c1e2c3502c6e9f860fc6625940bfe0cfb57a44953262b9e94df76872fdfb8151097eeb3 + languageName: node + linkType: hard + +"domelementtype@npm:^2.3.0": + version: 2.3.0 + resolution: "domelementtype@npm:2.3.0" + checksum: 10/ee837a318ff702622f383409d1f5b25dd1024b692ef64d3096ff702e26339f8e345820f29a68bcdcea8cfee3531776b3382651232fbeae95612d6f0a75efb4f6 + languageName: node + linkType: hard + +"domhandler@npm:5.0.3, domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": + version: 5.0.3 + resolution: "domhandler@npm:5.0.3" + dependencies: + domelementtype: "npm:^2.3.0" + checksum: 10/809b805a50a9c6884a29f38aec0a4e1b4537f40e1c861950ed47d10b049febe6b79ab72adaeeebb3cc8fc1cd33f34e97048a72a9265103426d93efafa78d3e96 + languageName: node + linkType: hard + +"domutils@npm:^3.2.1": + version: 3.2.2 + resolution: "domutils@npm:3.2.2" + dependencies: + dom-serializer: "npm:^2.0.0" + domelementtype: "npm:^2.3.0" + domhandler: "npm:^5.0.3" + checksum: 10/2e08842151aa406f50fe5e6d494f4ec73c2373199fa00d1f77b56ec604e566b7f226312ae35ab8160bb7f27a27c7285d574c8044779053e499282ca9198be210 + languageName: node + linkType: hard + "dunder-proto@npm:^1.0.0, dunder-proto@npm:^1.0.1": version: 1.0.1 resolution: "dunder-proto@npm:1.0.1" @@ -1827,36 +2423,63 @@ __metadata: languageName: node linkType: hard -"enhanced-resolve@npm:^5.15.0": - version: 5.18.0 - resolution: "enhanced-resolve@npm:5.18.0" +"encoding@npm:^0.1.13": + version: 0.1.13 + resolution: "encoding@npm:0.1.13" dependencies: - graceful-fs: "npm:^4.2.4" - tapable: "npm:^2.2.0" - checksum: 10/e88463ef97b68d40d0da0cd0c572e23f43dba0be622d6d44eae5cafed05f0c5dac43e463a83a86c4f70186d029357f82b56d9e1e47e8fc91dce3d6602f8bd6ce + iconv-lite: "npm:^0.6.2" + checksum: 10/bb98632f8ffa823996e508ce6a58ffcf5856330fde839ae42c9e1f436cc3b5cc651d4aeae72222916545428e54fd0f6aa8862fd8d25bdbcc4589f1e3f3715e7f languageName: node linkType: hard -"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9": - version: 1.23.9 - resolution: "es-abstract@npm:1.23.9" +"entities@npm:^4.2.0": + version: 4.5.0 + resolution: "entities@npm:4.5.0" + checksum: 10/ede2a35c9bce1aeccd055a1b445d41c75a14a2bb1cd22e242f20cf04d236cdcd7f9c859eb83f76885327bfae0c25bf03303665ee1ce3d47c5927b98b0e3e3d48 + languageName: node + linkType: hard + +"entities@npm:^6.0.0": + version: 6.0.1 + resolution: "entities@npm:6.0.1" + checksum: 10/62af1307202884349d2867f0aac5c60d8b57102ea0b0e768b16246099512c28e239254ad772d6834e7e14cb1b6f153fc3d0c031934e3183b086c86d3838d874a + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10/65b5df55a8bab92229ab2b40dad3b387fad24613263d103a97f91c9fe43ceb21965cd3392b1ccb5d77088021e525c4e0481adb309625d0cb94ade1d1fb8dc17e + languageName: node + linkType: hard + +"err-code@npm:^2.0.2": + version: 2.0.3 + resolution: "err-code@npm:2.0.3" + checksum: 10/1d20d825cdcce8d811bfbe86340f4755c02655a7feb2f13f8c880566d9d72a3f6c92c192a6867632e490d6da67b678271f46e01044996a6443e870331100dfdd + languageName: node + linkType: hard + +"es-abstract@npm:^1.17.5, es-abstract@npm:^1.23.2, es-abstract@npm:^1.23.3, es-abstract@npm:^1.23.5, es-abstract@npm:^1.23.6, es-abstract@npm:^1.23.9, es-abstract@npm:^1.24.0": + version: 1.24.0 + resolution: "es-abstract@npm:1.24.0" dependencies: array-buffer-byte-length: "npm:^1.0.2" arraybuffer.prototype.slice: "npm:^1.0.4" available-typed-arrays: "npm:^1.0.7" call-bind: "npm:^1.0.8" - call-bound: "npm:^1.0.3" + call-bound: "npm:^1.0.4" data-view-buffer: "npm:^1.0.2" data-view-byte-length: "npm:^1.0.2" data-view-byte-offset: "npm:^1.0.1" es-define-property: "npm:^1.0.1" es-errors: "npm:^1.3.0" - es-object-atoms: "npm:^1.0.0" + es-object-atoms: "npm:^1.1.1" es-set-tostringtag: "npm:^2.1.0" es-to-primitive: "npm:^1.3.0" function.prototype.name: "npm:^1.1.8" - get-intrinsic: "npm:^1.2.7" - get-proto: "npm:^1.0.0" + get-intrinsic: "npm:^1.3.0" + get-proto: "npm:^1.0.1" get-symbol-description: "npm:^1.1.0" globalthis: "npm:^1.0.4" gopd: "npm:^1.2.0" @@ -1868,21 +2491,24 @@ __metadata: is-array-buffer: "npm:^3.0.5" is-callable: "npm:^1.2.7" is-data-view: "npm:^1.0.2" + is-negative-zero: "npm:^2.0.3" is-regex: "npm:^1.2.1" + is-set: "npm:^2.0.3" is-shared-array-buffer: "npm:^1.0.4" is-string: "npm:^1.1.1" is-typed-array: "npm:^1.1.15" - is-weakref: "npm:^1.1.0" + is-weakref: "npm:^1.1.1" math-intrinsics: "npm:^1.1.0" - object-inspect: "npm:^1.13.3" + object-inspect: "npm:^1.13.4" object-keys: "npm:^1.1.1" object.assign: "npm:^4.1.7" own-keys: "npm:^1.0.1" - regexp.prototype.flags: "npm:^1.5.3" + regexp.prototype.flags: "npm:^1.5.4" safe-array-concat: "npm:^1.1.3" safe-push-apply: "npm:^1.0.0" safe-regex-test: "npm:^1.1.0" set-proto: "npm:^1.0.0" + stop-iteration-iterator: "npm:^1.1.0" string.prototype.trim: "npm:^1.2.10" string.prototype.trimend: "npm:^1.0.9" string.prototype.trimstart: "npm:^1.0.8" @@ -1891,8 +2517,8 @@ __metadata: typed-array-byte-offset: "npm:^1.0.4" typed-array-length: "npm:^1.0.7" unbox-primitive: "npm:^1.1.0" - which-typed-array: "npm:^1.1.18" - checksum: 10/31a321966d760d88fc2ed984104841b42f4f24fc322b246002b9be0af162e03803ee41fcc3cf8be89e07a27ba3033168f877dd983703cb81422ffe5322a27582 + which-typed-array: "npm:^1.1.19" + checksum: 10/64e07a886f7439cf5ccfc100f9716e6173e10af6071a50a5031afbdde474a3dbc9619d5965da54e55f8908746a9134a46be02af8c732d574b7b81ed3124e2daf languageName: node linkType: hard @@ -1955,12 +2581,12 @@ __metadata: languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.2": - version: 1.0.2 - resolution: "es-shim-unscopables@npm:1.0.2" +"es-shim-unscopables@npm:^1.0.2, es-shim-unscopables@npm:^1.1.0": + version: 1.1.0 + resolution: "es-shim-unscopables@npm:1.1.0" dependencies: - hasown: "npm:^2.0.0" - checksum: 10/6d3bf91f658a27cc7217cd32b407a0d714393a84d125ad576319b9e83a893bea165cf41270c29e9ceaa56d3cf41608945d7e2a2c31fd51c0009b0c31402b91c7 + hasown: "npm:^2.0.2" + checksum: 10/c351f586c30bbabc62355be49564b2435468b52c3532b8a1663672e3d10dc300197e69c247869dd173e56d86423ab95fc0c10b0939cdae597094e0fdca078cba languageName: node linkType: hard @@ -2011,34 +2637,34 @@ __metadata: linkType: hard "esbuild@npm:^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0": - version: 0.25.0 - resolution: "esbuild@npm:0.25.0" + version: 0.25.5 + resolution: "esbuild@npm:0.25.5" dependencies: - "@esbuild/aix-ppc64": "npm:0.25.0" - "@esbuild/android-arm": "npm:0.25.0" - "@esbuild/android-arm64": "npm:0.25.0" - "@esbuild/android-x64": "npm:0.25.0" - "@esbuild/darwin-arm64": "npm:0.25.0" - "@esbuild/darwin-x64": "npm:0.25.0" - "@esbuild/freebsd-arm64": "npm:0.25.0" - "@esbuild/freebsd-x64": "npm:0.25.0" - "@esbuild/linux-arm": "npm:0.25.0" - "@esbuild/linux-arm64": "npm:0.25.0" - "@esbuild/linux-ia32": "npm:0.25.0" - "@esbuild/linux-loong64": "npm:0.25.0" - "@esbuild/linux-mips64el": "npm:0.25.0" - "@esbuild/linux-ppc64": "npm:0.25.0" - "@esbuild/linux-riscv64": "npm:0.25.0" - "@esbuild/linux-s390x": "npm:0.25.0" - "@esbuild/linux-x64": "npm:0.25.0" - "@esbuild/netbsd-arm64": "npm:0.25.0" - "@esbuild/netbsd-x64": "npm:0.25.0" - "@esbuild/openbsd-arm64": "npm:0.25.0" - "@esbuild/openbsd-x64": "npm:0.25.0" - "@esbuild/sunos-x64": "npm:0.25.0" - "@esbuild/win32-arm64": "npm:0.25.0" - "@esbuild/win32-ia32": "npm:0.25.0" - "@esbuild/win32-x64": "npm:0.25.0" + "@esbuild/aix-ppc64": "npm:0.25.5" + "@esbuild/android-arm": "npm:0.25.5" + "@esbuild/android-arm64": "npm:0.25.5" + "@esbuild/android-x64": "npm:0.25.5" + "@esbuild/darwin-arm64": "npm:0.25.5" + "@esbuild/darwin-x64": "npm:0.25.5" + "@esbuild/freebsd-arm64": "npm:0.25.5" + "@esbuild/freebsd-x64": "npm:0.25.5" + "@esbuild/linux-arm": "npm:0.25.5" + "@esbuild/linux-arm64": "npm:0.25.5" + "@esbuild/linux-ia32": "npm:0.25.5" + "@esbuild/linux-loong64": "npm:0.25.5" + "@esbuild/linux-mips64el": "npm:0.25.5" + "@esbuild/linux-ppc64": "npm:0.25.5" + "@esbuild/linux-riscv64": "npm:0.25.5" + "@esbuild/linux-s390x": "npm:0.25.5" + "@esbuild/linux-x64": "npm:0.25.5" + "@esbuild/netbsd-arm64": "npm:0.25.5" + "@esbuild/netbsd-x64": "npm:0.25.5" + "@esbuild/openbsd-arm64": "npm:0.25.5" + "@esbuild/openbsd-x64": "npm:0.25.5" + "@esbuild/sunos-x64": "npm:0.25.5" + "@esbuild/win32-arm64": "npm:0.25.5" + "@esbuild/win32-ia32": "npm:0.25.5" + "@esbuild/win32-x64": "npm:0.25.5" dependenciesMeta: "@esbuild/aix-ppc64": optional: true @@ -2092,7 +2718,14 @@ __metadata: optional: true bin: esbuild: bin/esbuild - checksum: 10/451daf6a442df29ec5d528587caa4ce783d41ff4acb93252da5a852b8d36c22e9f84d17f6721d4fbef9a1ba9855bc9fe1f167dd732c11665fe53032f2b89f114 + checksum: 10/0fa4c3b42c6ddf1a008e75a4bb3dcab08ce22ac0b31dd59dc01f7fe8e21380bfaec07a2fe3730a7cf430da5a30142d016714b358666325a4733547afa42be405 + languageName: node + linkType: hard + +"escalade@npm:^3.1.1": + version: 3.2.0 + resolution: "escalade@npm:3.2.0" + checksum: 10/9d7169e3965b2f9ae46971afa392f6e5a25545ea30f2e2dd99c9b0a95a3f52b5653681a84f5b2911a413ddad2d7a93d3514165072f349b5ffc59c75a899970d6 languageName: node linkType: hard @@ -2103,27 +2736,27 @@ __metadata: languageName: node linkType: hard -"eslint-config-next@npm:14.2.23": - version: 14.2.23 - resolution: "eslint-config-next@npm:14.2.23" +"eslint-config-next@npm:15.3.4": + version: 15.3.4 + resolution: "eslint-config-next@npm:15.3.4" dependencies: - "@next/eslint-plugin-next": "npm:14.2.23" - "@rushstack/eslint-patch": "npm:^1.3.3" + "@next/eslint-plugin-next": "npm:15.3.4" + "@rushstack/eslint-patch": "npm:^1.10.3" "@typescript-eslint/eslint-plugin": "npm:^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" "@typescript-eslint/parser": "npm:^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0" eslint-import-resolver-node: "npm:^0.3.6" eslint-import-resolver-typescript: "npm:^3.5.2" - eslint-plugin-import: "npm:^2.28.1" - eslint-plugin-jsx-a11y: "npm:^6.7.1" - eslint-plugin-react: "npm:^7.33.2" - eslint-plugin-react-hooks: "npm:^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + eslint-plugin-import: "npm:^2.31.0" + eslint-plugin-jsx-a11y: "npm:^6.10.0" + eslint-plugin-react: "npm:^7.37.0" + eslint-plugin-react-hooks: "npm:^5.0.0" peerDependencies: - eslint: ^7.23.0 || ^8.0.0 + eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 typescript: ">=3.3.1" peerDependenciesMeta: typescript: optional: true - checksum: 10/ee23822e91c155cb0531c786cf11573b8914bc7dfa3b506c45c1d13d4b0c1b515764bd2744daa9c36bddf3bb7cfff434fa6bd169540a2fb933a336df78e7d850 + checksum: 10/6c21254d3383b9158ff5f3b2881cc702bee3d2635b4326757965945691f6e65e25fdfef4f2964382fb4b2f52d9f03b929cb71d267709727df7365e7da80c8c3a languageName: node linkType: hard @@ -2139,17 +2772,16 @@ __metadata: linkType: hard "eslint-import-resolver-typescript@npm:^3.5.2": - version: 3.7.0 - resolution: "eslint-import-resolver-typescript@npm:3.7.0" + version: 3.10.1 + resolution: "eslint-import-resolver-typescript@npm:3.10.1" dependencies: "@nolyfill/is-core-module": "npm:1.0.39" - debug: "npm:^4.3.7" - enhanced-resolve: "npm:^5.15.0" - fast-glob: "npm:^3.3.2" - get-tsconfig: "npm:^4.7.5" - is-bun-module: "npm:^1.0.2" - is-glob: "npm:^4.0.3" - stable-hash: "npm:^0.0.4" + debug: "npm:^4.4.0" + get-tsconfig: "npm:^4.10.0" + is-bun-module: "npm:^2.0.0" + stable-hash: "npm:^0.0.5" + tinyglobby: "npm:^0.2.13" + unrs-resolver: "npm:^1.6.2" peerDependencies: eslint: "*" eslint-plugin-import: "*" @@ -2159,7 +2791,7 @@ __metadata: optional: true eslint-plugin-import-x: optional: true - checksum: 10/8158730c11e562c56ed9bf7236dc75bce35b6992dc32c39ac2f4177ab77fca97b95999850204a6458054243607b54aee88c028a61fed4184f24f425fa1afff01 + checksum: 10/b8d6a9b2045c70f043f722f78c9e65bc0283126f0ad92c8f07473f7647d77f7b1562f765a472f17e06b81897b407091c0ec9f2e4592b158c9fd92d0b0c33de89 languageName: node linkType: hard @@ -2175,7 +2807,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-import@npm:^2.28.1": +"eslint-plugin-import@npm:^2.31.0": version: 2.31.0 resolution: "eslint-plugin-import@npm:2.31.0" dependencies: @@ -2204,7 +2836,7 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-jsx-a11y@npm:^6.7.1": +"eslint-plugin-jsx-a11y@npm:^6.10.0": version: 6.10.2 resolution: "eslint-plugin-jsx-a11y@npm:6.10.2" dependencies: @@ -2229,18 +2861,18 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-hooks@npm:^4.5.0 || 5.0.0-canary-7118f5dd7-20230705": - version: 5.0.0-canary-7118f5dd7-20230705 - resolution: "eslint-plugin-react-hooks@npm:5.0.0-canary-7118f5dd7-20230705" +"eslint-plugin-react-hooks@npm:^5.0.0": + version: 5.2.0 + resolution: "eslint-plugin-react-hooks@npm:5.2.0" peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 - checksum: 10/0e0e80c21552998b7af2b92a74aec5e862b33f6f16c3e1303d42b5821d68b7ba11c2037bd73e3581fc7d97d9a2e64dd19e202d47d6885f53e33aac87c048d641 + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + checksum: 10/ebb79e9cf69ae06e3a7876536653c5e556b5fd8cd9dc49577f10a6e728360e7b6f5ce91f4339b33e93b26e3bb23805418f8b5e75db80baddd617b1dffe73bed1 languageName: node linkType: hard -"eslint-plugin-react@npm:^7.33.2": - version: 7.37.3 - resolution: "eslint-plugin-react@npm:7.37.3" +"eslint-plugin-react@npm:^7.37.0": + version: 7.37.5 + resolution: "eslint-plugin-react@npm:7.37.5" dependencies: array-includes: "npm:^3.1.8" array.prototype.findlast: "npm:^1.2.5" @@ -2252,7 +2884,7 @@ __metadata: hasown: "npm:^2.0.2" jsx-ast-utils: "npm:^2.4.1 || ^3.0.0" minimatch: "npm:^3.1.2" - object.entries: "npm:^1.1.8" + object.entries: "npm:^1.1.9" object.fromentries: "npm:^2.0.8" object.values: "npm:^1.2.1" prop-types: "npm:^15.8.1" @@ -2262,7 +2894,7 @@ __metadata: string.prototype.repeat: "npm:^1.0.0" peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 - checksum: 10/30042b95c440a962157192f67369d8c9171f7c73e992695e5674c9d28c3cfe4098488eca86dfa7c433d4c8a91243cbafdc80c7e42d2c1720a427ddb36e65457e + checksum: 10/ee1bd4e0ec64f29109d5a625bb703d179c82e0159c86c3f1b52fc1209d2994625a137dae303c333fb308a2e38315e44066d5204998177e31974382f9fda25d5c languageName: node linkType: hard @@ -2284,9 +2916,9 @@ __metadata: linkType: hard "eslint-visitor-keys@npm:^4.2.0": - version: 4.2.0 - resolution: "eslint-visitor-keys@npm:4.2.0" - checksum: 10/9651b3356b01760e586b4c631c5268c0e1a85236e3292bf754f0472f465bf9a856c0ddc261fceace155334118c0151778effafbab981413dbf9288349343fa25 + version: 4.2.1 + resolution: "eslint-visitor-keys@npm:4.2.1" + checksum: 10/3ee00fc6a7002d4b0ffd9dc99e13a6a7882c557329e6c25ab254220d71e5c9c4f89dca4695352949ea678eb1f3ba912a18ef8aac0a7fe094196fd92f441bfce2 languageName: node linkType: hard @@ -2459,6 +3091,13 @@ __metadata: languageName: node linkType: hard +"exponential-backoff@npm:^3.1.1": + version: 3.1.2 + resolution: "exponential-backoff@npm:3.1.2" + checksum: 10/ca2f01f1aa4dafd3f3917bd531ab5be08c6f5f4b2389d2e974f903de3cbeb50b9633374353516b6afd70905775e33aba11afab1232d3acf0aa2963b98a611c51 + languageName: node + linkType: hard + "extend@npm:^3.0.0": version: 3.0.2 resolution: "extend@npm:3.0.2" @@ -2473,6 +3112,19 @@ __metadata: languageName: node linkType: hard +"fast-glob@npm:3.3.1": + version: 3.3.1 + resolution: "fast-glob@npm:3.3.1" + dependencies: + "@nodelib/fs.stat": "npm:^2.0.2" + "@nodelib/fs.walk": "npm:^1.2.3" + glob-parent: "npm:^5.1.2" + merge2: "npm:^1.3.0" + micromatch: "npm:^4.0.4" + checksum: 10/51bcd15472879dfe51d4b01c5b70bbc7652724d39cdd082ba11276dbd7d84db0f6b33757e1938af8b2768a4bf485d9be0c89153beae24ee8331d6dcc7550379f + languageName: node + linkType: hard + "fast-glob@npm:^3.3.2": version: 3.3.3 resolution: "fast-glob@npm:3.3.3" @@ -2501,11 +3153,23 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.18.0 - resolution: "fastq@npm:1.18.0" + version: 1.19.1 + resolution: "fastq@npm:1.19.1" dependencies: reusify: "npm:^1.0.4" - checksum: 10/c5b501333dc8f5d188d828ea162aad03ff5a81aed185b6d4a5078aaeae0a42babc34296d7af13ebce86401cccd93c9b7b3cbf61280821c5f20af233378b42fbb + checksum: 10/75679dc226316341c4f2a6b618571f51eac96779906faecd8921b984e844d6ae42fabb2df69b1071327d398d5716693ea9c9c8941f64ac9e89ec2032ce59d730 + languageName: node + linkType: hard + +"fdir@npm:^6.4.4": + version: 6.4.6 + resolution: "fdir@npm:6.4.6" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10/c186ba387e7b75ccf874a098d9bc5fe0af0e9c52fc56f8eac8e80aa4edb65532684bf2bf769894ff90f53bf221d6136692052d31f07a9952807acae6cbe7ee50 languageName: node linkType: hard @@ -2549,9 +3213,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.3.2 - resolution: "flatted@npm:3.3.2" - checksum: 10/ac3c159742e01d0e860a861164bcfd35bb567ccbebb8a0dd041e61cf3c64a435b917dd1e7ed1c380c2ebca85735fb16644485ec33665bc6aafc3b316aa1eed44 + version: 3.3.3 + resolution: "flatted@npm:3.3.3" + checksum: 10/8c96c02fbeadcf4e8ffd0fa24983241e27698b0781295622591fc13585e2f226609d95e422bcf2ef044146ffacb6b68b1f20871454eddf75ab3caa6ee5f4a1fe languageName: node linkType: hard @@ -2565,21 +3229,21 @@ __metadata: linkType: hard "foreground-child@npm:^3.1.0": - version: 3.3.0 - resolution: "foreground-child@npm:3.3.0" + version: 3.3.1 + resolution: "foreground-child@npm:3.3.1" dependencies: - cross-spawn: "npm:^7.0.0" + cross-spawn: "npm:^7.0.6" signal-exit: "npm:^4.0.1" - checksum: 10/e3a60480f3a09b12273ce2c5fcb9514d98dd0e528f58656a1b04680225f918d60a2f81f6a368f2f3b937fcee9cfc0cbf16f1ad9a0bc6a3a6e103a84c9a90087e + checksum: 10/427b33f997a98073c0424e5c07169264a62cda806d8d2ded159b5b903fdfc8f0a1457e06b5fc35506497acb3f1e353f025edee796300209ac6231e80edece835 languageName: node linkType: hard -"framer-motion@npm:^12.5.0": - version: 12.5.0 - resolution: "framer-motion@npm:12.5.0" +"framer-motion@npm:^12.17.0": + version: 12.17.0 + resolution: "framer-motion@npm:12.17.0" dependencies: - motion-dom: "npm:^12.5.0" - motion-utils: "npm:^12.5.0" + motion-dom: "npm:^12.17.0" + motion-utils: "npm:^12.12.1" tslib: "npm:^2.4.0" peerDependencies: "@emotion/is-prop-valid": "*" @@ -2592,7 +3256,16 @@ __metadata: optional: true react-dom: optional: true - checksum: 10/6659e0b704d3216dafdcb11175e3c5f55d536469ddd8ad62b37d00bc7e893d914989791c018cfdfa17b3142b655f0d85226adc94ed390c1524312c3653b8c75f + checksum: 10/803b57cb7ec7200938c9425392a66839c96bf5a800ff14b38d9e689a47341678c53ce54765f68f0a186cfad6c1270b2ad46a75aeff67b2a2e2f3b846852d792c + languageName: node + linkType: hard + +"fs-minipass@npm:^3.0.0": + version: 3.0.3 + resolution: "fs-minipass@npm:3.0.3" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10/af143246cf6884fe26fa281621d45cfe111d34b30535a475bfa38dafe343dadb466c047a924ffc7d6b7b18265df4110224ce3803806dbb07173bf2087b648d7f languageName: node linkType: hard @@ -2603,6 +3276,25 @@ __metadata: languageName: node linkType: hard +"fsevents@npm:~2.3.2": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 10/4c1ade961ded57cdbfbb5cac5106ec17bc8bccd62e16343c569a0ceeca83b9dfef87550b4dc5cbb89642da412b20c5071f304c8c464b80415446e8e155a038c0 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + "function-bind@npm:^1.1.2": version: 1.1.2 resolution: "function-bind@npm:1.1.2" @@ -2631,6 +3323,13 @@ __metadata: languageName: node linkType: hard +"get-caller-file@npm:^2.0.5": + version: 2.0.5 + resolution: "get-caller-file@npm:2.0.5" + checksum: 10/b9769a836d2a98c3ee734a88ba712e62703f1df31b94b784762c433c27a386dd6029ff55c2a920c392e33657d80191edbf18c61487e198844844516f843496b9 + languageName: node + linkType: hard + "get-intrinsic@npm:^1.2.4, get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.2.6, get-intrinsic@npm:^1.2.7, get-intrinsic@npm:^1.3.0": version: 1.3.0 resolution: "get-intrinsic@npm:1.3.0" @@ -2670,16 +3369,16 @@ __metadata: languageName: node linkType: hard -"get-tsconfig@npm:^4.7.5": - version: 4.8.1 - resolution: "get-tsconfig@npm:4.8.1" +"get-tsconfig@npm:^4.10.0": + version: 4.10.1 + resolution: "get-tsconfig@npm:4.10.1" dependencies: resolve-pkg-maps: "npm:^1.0.0" - checksum: 10/3fb5a8ad57b9633eaea085d81661e9e5c9f78b35d8f8689eaf8b8b45a2a3ebf3b3422266d4d7df765e308cc1e6231648d114803ab3d018332e29916f2c1de036 + checksum: 10/04d63f47fdecaefbd1f73ec02949be4ec4db7d6d9fbc8d4e81f9a4bb1c6f876e48943712f2f9236643d3e4d61d9a7b06da08564d08b034631ebe3f5605bef237 languageName: node linkType: hard -"glob-parent@npm:^5.1.2": +"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2": version: 5.1.2 resolution: "glob-parent@npm:5.1.2" dependencies: @@ -2697,18 +3396,19 @@ __metadata: languageName: node linkType: hard -"glob@npm:10.3.10": - version: 10.3.10 - resolution: "glob@npm:10.3.10" +"glob@npm:^10.2.2": + version: 10.4.5 + resolution: "glob@npm:10.4.5" dependencies: foreground-child: "npm:^3.1.0" - jackspeak: "npm:^2.3.5" - minimatch: "npm:^9.0.1" - minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry: "npm:^1.10.1" + jackspeak: "npm:^3.1.2" + minimatch: "npm:^9.0.4" + minipass: "npm:^7.1.2" + package-json-from-dist: "npm:^1.0.0" + path-scurry: "npm:^1.11.1" bin: glob: dist/esm/bin.mjs - checksum: 10/38bdb2c9ce75eb5ed168f309d4ed05b0798f640b637034800a6bf306f39d35409bf278b0eaaffaec07591085d3acb7184a201eae791468f0f617771c2486a6a8 + checksum: 10/698dfe11828b7efd0514cd11e573eaed26b2dff611f0400907281ce3eab0c1e56143ef9b35adc7c77ecc71fba74717b510c7c223d34ca8a98ec81777b293d4ac languageName: node linkType: hard @@ -2752,7 +3452,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.4": +"graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10/bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 @@ -2814,7 +3514,7 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0, hasown@npm:^2.0.2": +"hasown@npm:^2.0.2": version: 2.0.2 resolution: "hasown@npm:2.0.2" dependencies: @@ -2824,8 +3524,8 @@ __metadata: linkType: hard "hast-util-to-estree@npm:^3.0.0": - version: 3.1.1 - resolution: "hast-util-to-estree@npm:3.1.1" + version: 3.1.3 + resolution: "hast-util-to-estree@npm:3.1.3" dependencies: "@types/estree": "npm:^1.0.0" "@types/estree-jsx": "npm:^1.0.0" @@ -2838,18 +3538,18 @@ __metadata: mdast-util-mdx-expression: "npm:^2.0.0" mdast-util-mdx-jsx: "npm:^3.0.0" mdast-util-mdxjs-esm: "npm:^2.0.0" - property-information: "npm:^6.0.0" + property-information: "npm:^7.0.0" space-separated-tokens: "npm:^2.0.0" - style-to-object: "npm:^1.0.0" + style-to-js: "npm:^1.0.0" unist-util-position: "npm:^5.0.0" zwitch: "npm:^2.0.0" - checksum: 10/f72b0d72d6f3e1d55a876e175716b78bf93b8246fac8dd6db6b46c03b0288d03f40644606f36c00e8f12829a6bef0e7a73b405825b651a94b41f0bc5b53b92b4 + checksum: 10/efe69c8af68f021d853e70916c6e940765be519aec8703765898c1c3814424b0470f70c0272cf4ac06dcaf6d6f3cc781ebf034701ed240a33ac691d1f5eaf65b languageName: node linkType: hard "hast-util-to-html@npm:^9.0.4": - version: 9.0.4 - resolution: "hast-util-to-html@npm:9.0.4" + version: 9.0.5 + resolution: "hast-util-to-html@npm:9.0.5" dependencies: "@types/hast": "npm:^3.0.0" "@types/unist": "npm:^3.0.0" @@ -2858,17 +3558,17 @@ __metadata: hast-util-whitespace: "npm:^3.0.0" html-void-elements: "npm:^3.0.0" mdast-util-to-hast: "npm:^13.0.0" - property-information: "npm:^6.0.0" + property-information: "npm:^7.0.0" space-separated-tokens: "npm:^2.0.0" stringify-entities: "npm:^4.0.0" zwitch: "npm:^2.0.4" - checksum: 10/a0b4ed9058e57fa2ca010d10c077fda78d2ab2af99f5bd09fe4b9948970025ac4a2a1a03ec7e2e0f3b0444066b1b35d602fa3e9fbd9b7fc9cdd35d0cafa909ca + checksum: 10/4278e5246f43adf7a30bf3b87db4a4e628b5362b8c149eb4360bf7e0f731f81fa31e4e844e8090d1dd5f739d0884678f8165b28f97c14139e4da4f945f9ff5f7 languageName: node linkType: hard "hast-util-to-jsx-runtime@npm:^2.0.0": - version: 2.3.2 - resolution: "hast-util-to-jsx-runtime@npm:2.3.2" + version: 2.3.6 + resolution: "hast-util-to-jsx-runtime@npm:2.3.6" dependencies: "@types/estree": "npm:^1.0.0" "@types/hast": "npm:^3.0.0" @@ -2880,12 +3580,12 @@ __metadata: mdast-util-mdx-expression: "npm:^2.0.0" mdast-util-mdx-jsx: "npm:^3.0.0" mdast-util-mdxjs-esm: "npm:^2.0.0" - property-information: "npm:^6.0.0" + property-information: "npm:^7.0.0" space-separated-tokens: "npm:^2.0.0" - style-to-object: "npm:^1.0.0" + style-to-js: "npm:^1.0.0" unist-util-position: "npm:^5.0.0" vfile-message: "npm:^4.0.0" - checksum: 10/3d72f83e2d8c29adc6576d2c6b41479902fd51fac8cfb2b67c35fd68fcb9c25c274699442e4dee901a7ab926a0ff6851713ed5d92448ac09ae0f10daf293476c + checksum: 10/111bd69f482952c7591cb4e1d3face25f1c18849b310a4d6cacc91e2d2cbc965d455fad35c059b8f0cfd762e933b826a7090b6f3098dece08307a6569de8f1d8 languageName: node linkType: hard @@ -2898,6 +3598,34 @@ __metadata: languageName: node linkType: hard +"html-dom-parser@npm:5.1.1": + version: 5.1.1 + resolution: "html-dom-parser@npm:5.1.1" + dependencies: + domhandler: "npm:5.0.3" + htmlparser2: "npm:10.0.0" + checksum: 10/85bbaa8699d40d54fd64f5472088199178a6c3dd6a907358ac476d9c511cb8ab10bff1469a785411e8b831a73ac08348392e56076eab6d100a3ec19dccc722ad + languageName: node + linkType: hard + +"html-react-parser@npm:^5.2.5": + version: 5.2.5 + resolution: "html-react-parser@npm:5.2.5" + dependencies: + domhandler: "npm:5.0.3" + html-dom-parser: "npm:5.1.1" + react-property: "npm:2.0.2" + style-to-js: "npm:1.1.16" + 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/22852dc4826d3be9506e238e37a05c23b432675aac33f22bd5741caa195a32e99de99d2b99037fda532f198afbcdeacfc0b27627d6e529143a98c8f191e99c52 + languageName: node + linkType: hard + "html-void-elements@npm:^3.0.0": version: 3.0.0 resolution: "html-void-elements@npm:3.0.0" @@ -2905,20 +3633,75 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^5.2.0, ignore@npm:^5.3.1": +"htmlparser2@npm:10.0.0": + version: 10.0.0 + resolution: "htmlparser2@npm:10.0.0" + dependencies: + domelementtype: "npm:^2.3.0" + domhandler: "npm:^5.0.3" + domutils: "npm:^3.2.1" + entities: "npm:^6.0.0" + checksum: 10/768870f0e020dca19dc45df206cb6ac466c5dba6566c8fca4ca880347eed409f9977028d08644ac516bca8628ac9c7ded5a3847dc3ee1c043f049abf9e817154 + languageName: node + linkType: hard + +"http-cache-semantics@npm:^4.1.1": + version: 4.2.0 + resolution: "http-cache-semantics@npm:4.2.0" + checksum: 10/4efd2dfcfeea9d5e88c84af450b9980be8a43c2c8179508b1c57c7b4421c855f3e8efe92fa53e0b3f4a43c85824ada930eabbc306d1b3beab750b6dcc5187693 + languageName: node + linkType: hard + +"http-proxy-agent@npm:^7.0.0": + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" + dependencies: + agent-base: "npm:^7.1.0" + debug: "npm:^4.3.4" + checksum: 10/d062acfa0cb82beeb558f1043c6ba770ea892b5fb7b28654dbc70ea2aeea55226dd34c02a294f6c1ca179a5aa483c4ea641846821b182edbd9cc5d89b54c6848 + languageName: node + linkType: hard + +"https-proxy-agent@npm:^7.0.1": + version: 7.0.6 + resolution: "https-proxy-agent@npm:7.0.6" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:4" + checksum: 10/784b628cbd55b25542a9d85033bdfd03d4eda630fb8b3c9477959367f3be95dc476ed2ecbb9836c359c7c698027fc7b45723a302324433590f45d6c1706e8c13 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.6.2": + version: 0.6.3 + resolution: "iconv-lite@npm:0.6.3" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10/24e3292dd3dadaa81d065c6f8c41b274a47098150d444b96e5f53b4638a9a71482921ea6a91a1f59bb71d9796de25e04afd05919fa64c360347ba65d3766f10f + languageName: node + linkType: hard + +"ignore@npm:^5.2.0": version: 5.3.2 resolution: "ignore@npm:5.3.2" checksum: 10/cceb6a457000f8f6a50e1196429750d782afce5680dd878aa4221bd79972d68b3a55b4b1458fc682be978f4d3c6a249046aa0880637367216444ab7b014cfc98 languageName: node linkType: hard +"ignore@npm:^7.0.0": + version: 7.0.5 + resolution: "ignore@npm:7.0.5" + checksum: 10/f134b96a4de0af419196f52c529d5c6120c4456ff8a6b5a14ceaaa399f883e15d58d2ce651c9b69b9388491d4669dda47285d307e827de9304a53a1824801bc6 + languageName: node + linkType: hard + "import-fresh@npm:^3.2.1": - version: 3.3.0 - resolution: "import-fresh@npm:3.3.0" + version: 3.3.1 + resolution: "import-fresh@npm:3.3.1" dependencies: parent-module: "npm:^1.0.0" resolve-from: "npm:^4.0.0" - checksum: 10/2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa + checksum: 10/a06b19461b4879cc654d46f8a6244eb55eb053437afd4cbb6613cad6be203811849ed3e4ea038783092879487299fda24af932b86bdfff67c9055ba3612b8c87 languageName: node linkType: hard @@ -2964,6 +3747,16 @@ __metadata: languageName: node linkType: hard +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 10/1ed81e06721af012306329b31f532b5e24e00cb537be18ddc905a84f19fe8f83a09a1699862bf3a1ec4b9dea93c55a3fa5faf8b5ea380431469df540f38b092c + languageName: node + linkType: hard + "is-alphabetical@npm:^2.0.0": version: 2.0.1 resolution: "is-alphabetical@npm:2.0.1" @@ -3002,15 +3795,23 @@ __metadata: languageName: node linkType: hard +"is-arrayish@npm:^0.3.1": + version: 0.3.2 + resolution: "is-arrayish@npm:0.3.2" + checksum: 10/81a78d518ebd8b834523e25d102684ee0f7e98637136d3bdc93fd09636350fa06f1d8ca997ea28143d4d13cb1b69c0824f082db0ac13e1ab3311c10ffea60ade + languageName: node + linkType: hard + "is-async-function@npm:^2.0.0": - version: 2.1.0 - resolution: "is-async-function@npm:2.1.0" + version: 2.1.1 + resolution: "is-async-function@npm:2.1.1" dependencies: + async-function: "npm:^1.0.0" call-bound: "npm:^1.0.3" get-proto: "npm:^1.0.1" has-tostringtag: "npm:^1.0.2" safe-regex-test: "npm:^1.1.0" - checksum: 10/865f0e915b7d9aa5577327e7550bf77a4bb2b7bca497d32564e1d32dbe0ccb7eca1c9c56dd679b6dd2bd7feddb91574e773922276871a5958e53ae8473db4742 + checksum: 10/7c2ac7efdf671e03265e74a043bcb1c0a32e226bc2a42dfc5ec8644667df668bbe14b91c08e6c1414f392f8cf86cd1d489b3af97756e2c7a49dd1ba63fd40ca6 languageName: node linkType: hard @@ -3023,22 +3824,31 @@ __metadata: languageName: node linkType: hard -"is-boolean-object@npm:^1.2.1": - version: 1.2.1 - resolution: "is-boolean-object@npm:1.2.1" +"is-binary-path@npm:~2.1.0": + version: 2.1.0 + resolution: "is-binary-path@npm:2.1.0" dependencies: - call-bound: "npm:^1.0.2" - has-tostringtag: "npm:^1.0.2" - checksum: 10/5a15524635c9334ebbd668f20a6cbf023adceed5725ec96a50056d21ae65f52759d04a8fa7d7febf00ff3bc4e6d3837638eb84be572f287bcfd15f8b8facde43 + binary-extensions: "npm:^2.0.0" + checksum: 10/078e51b4f956c2c5fd2b26bb2672c3ccf7e1faff38e0ebdba45612265f4e3d9fc3127a1fa8370bbf09eab61339203c3d3b7af5662cbf8be4030f8fac37745b0e languageName: node linkType: hard -"is-bun-module@npm:^1.0.2": - version: 1.3.0 - resolution: "is-bun-module@npm:1.3.0" +"is-boolean-object@npm:^1.2.1": + version: 1.2.2 + resolution: "is-boolean-object@npm:1.2.2" dependencies: - semver: "npm:^7.6.3" - checksum: 10/b23d9ec7b4d4bfd89e4e72b5cd52e1bc153facad59fdd7394c656f8859a78740ef35996a2066240a32f39cc9a9da4b4eb69e68df3c71755a61ebbaf56d3daef0 + call-bound: "npm:^1.0.3" + has-tostringtag: "npm:^1.0.2" + checksum: 10/051fa95fdb99d7fbf653165a7e6b2cba5d2eb62f7ffa81e793a790f3fb5366c91c1b7b6af6820aa2937dd86c73aa3ca9d9ca98f500988457b1c59692c52ba911 + languageName: node + linkType: hard + +"is-bun-module@npm:^2.0.0": + version: 2.0.0 + resolution: "is-bun-module@npm:2.0.0" + dependencies: + semver: "npm:^7.7.1" + checksum: 10/cded5a1a58368b847872d08617975d620ad94426d76a932f3e08d55b4574d199e0a62a4fb024fa2dc444200b71719eb0bffc5d3d1e1cc82e29b293bb8d66a990 languageName: node linkType: hard @@ -3130,7 +3940,7 @@ __metadata: languageName: node linkType: hard -"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3": +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.1, is-glob@npm:^4.0.3, is-glob@npm:~4.0.1": version: 4.0.3 resolution: "is-glob@npm:4.0.3" dependencies: @@ -3153,6 +3963,13 @@ __metadata: languageName: node linkType: hard +"is-negative-zero@npm:^2.0.3": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: 10/8fe5cffd8d4fb2ec7b49d657e1691889778d037494c6f40f4d1a524cadd658b4b53ad7b6b73a59bcb4b143ae9a3d15829af864b2c0f9d65ac1e678c4c80f17e5 + languageName: node + linkType: hard + "is-number-object@npm:^1.1.1": version: 1.1.1 resolution: "is-number-object@npm:1.1.1" @@ -3212,7 +4029,7 @@ __metadata: languageName: node linkType: hard -"is-string@npm:^1.0.7, is-string@npm:^1.1.1": +"is-string@npm:^1.1.1": version: 1.1.1 resolution: "is-string@npm:1.1.1" dependencies: @@ -3249,12 +4066,12 @@ __metadata: languageName: node linkType: hard -"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.0": - version: 1.1.0 - resolution: "is-weakref@npm:1.1.0" +"is-weakref@npm:^1.0.2, is-weakref@npm:^1.1.1": + version: 1.1.1 + resolution: "is-weakref@npm:1.1.1" dependencies: - call-bound: "npm:^1.0.2" - checksum: 10/89e627cc1763ea110574bb408fcf060ede47e70437d9278858bc939e3b3f7e4b7c558610b733da5f2ad6084d9f12b9c714b011ccf3fa771ec87e221c22bed910 + call-bound: "npm:^1.0.3" + checksum: 10/543506fd8259038b371bb083aac25b16cb4fd8b12fc58053aa3d45ac28dfd001cd5c6dffbba7aeea4213c74732d46b6cb2cfb5b412eed11f2db524f3f97d09a0 languageName: node linkType: hard @@ -3291,6 +4108,13 @@ __metadata: languageName: node linkType: hard +"isexe@npm:^3.1.1": + version: 3.1.1 + resolution: "isexe@npm:3.1.1" + checksum: 10/7fe1931ee4e88eb5aa524cd3ceb8c882537bc3a81b02e438b240e47012eef49c86904d0f0e593ea7c3a9996d18d0f1f3be8d3eaa92333977b0c3a9d353d5563e + languageName: node + linkType: hard + "iterator.prototype@npm:^1.1.4": version: 1.1.5 resolution: "iterator.prototype@npm:1.1.5" @@ -3305,20 +4129,20 @@ __metadata: languageName: node linkType: hard -"jackspeak@npm:^2.3.5": - version: 2.3.6 - resolution: "jackspeak@npm:2.3.6" +"jackspeak@npm:^3.1.2": + version: 3.4.3 + resolution: "jackspeak@npm:3.4.3" dependencies: "@isaacs/cliui": "npm:^8.0.2" "@pkgjs/parseargs": "npm:^0.11.0" dependenciesMeta: "@pkgjs/parseargs": optional: true - checksum: 10/6e6490d676af8c94a7b5b29b8fd5629f21346911ebe2e32931c2a54210134408171c24cee1a109df2ec19894ad04a429402a8438cbf5cc2794585d35428ace76 + checksum: 10/96f8786eaab98e4bf5b2a5d6d9588ea46c4d06bbc4f2eb861fdd7b6b182b16f71d8a70e79820f335d52653b16d4843b29dd9cdcf38ae80406756db9199497cf3 languageName: node linkType: hard -"js-tokens@npm:^3.0.0 || ^4.0.0": +"js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": version: 4.0.0 resolution: "js-tokens@npm:4.0.0" checksum: 10/af37d0d913fb56aec6dc0074c163cc71cd23c0b8aad5c2350747b6721d37ba118af35abdd8b33c47ec2800de07dedb16a527ca9c530ee004093e04958bd0cbf2 @@ -3336,6 +4160,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 10/bebe7ae829bbd586ce8cbe83501dd8cb8c282c8902a8aeeed0a073a89dc37e8103b1244f3c6acd60278bcbfe12d93a3f83c9ac396868a3b3bbc3c5e5e3b648ef + languageName: node + linkType: hard + "jsdoc-type-pratt-parser@npm:^4.0.0": version: 4.1.0 resolution: "jsdoc-type-pratt-parser@npm:4.1.0" @@ -3422,91 +4253,91 @@ __metadata: languageName: node linkType: hard -"lightningcss-darwin-arm64@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-darwin-arm64@npm:1.29.3" +"lightningcss-darwin-arm64@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-darwin-arm64@npm:1.30.1" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"lightningcss-darwin-x64@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-darwin-x64@npm:1.29.3" +"lightningcss-darwin-x64@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-darwin-x64@npm:1.30.1" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"lightningcss-freebsd-x64@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-freebsd-x64@npm:1.29.3" +"lightningcss-freebsd-x64@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-freebsd-x64@npm:1.30.1" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"lightningcss-linux-arm-gnueabihf@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-linux-arm-gnueabihf@npm:1.29.3" +"lightningcss-linux-arm-gnueabihf@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.30.1" conditions: os=linux & cpu=arm languageName: node linkType: hard -"lightningcss-linux-arm64-gnu@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-linux-arm64-gnu@npm:1.29.3" +"lightningcss-linux-arm64-gnu@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-arm64-gnu@npm:1.30.1" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-arm64-musl@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-linux-arm64-musl@npm:1.29.3" +"lightningcss-linux-arm64-musl@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-arm64-musl@npm:1.30.1" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"lightningcss-linux-x64-gnu@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-linux-x64-gnu@npm:1.29.3" +"lightningcss-linux-x64-gnu@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-x64-gnu@npm:1.30.1" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"lightningcss-linux-x64-musl@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-linux-x64-musl@npm:1.29.3" +"lightningcss-linux-x64-musl@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-linux-x64-musl@npm:1.30.1" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"lightningcss-win32-arm64-msvc@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-win32-arm64-msvc@npm:1.29.3" +"lightningcss-win32-arm64-msvc@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-win32-arm64-msvc@npm:1.30.1" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"lightningcss-win32-x64-msvc@npm:1.29.3": - version: 1.29.3 - resolution: "lightningcss-win32-x64-msvc@npm:1.29.3" +"lightningcss-win32-x64-msvc@npm:1.30.1": + version: 1.30.1 + resolution: "lightningcss-win32-x64-msvc@npm:1.30.1" conditions: os=win32 & cpu=x64 languageName: node linkType: hard "lightningcss@npm:^1.28.2": - version: 1.29.3 - resolution: "lightningcss@npm:1.29.3" + version: 1.30.1 + resolution: "lightningcss@npm:1.30.1" dependencies: detect-libc: "npm:^2.0.3" - lightningcss-darwin-arm64: "npm:1.29.3" - lightningcss-darwin-x64: "npm:1.29.3" - lightningcss-freebsd-x64: "npm:1.29.3" - lightningcss-linux-arm-gnueabihf: "npm:1.29.3" - lightningcss-linux-arm64-gnu: "npm:1.29.3" - lightningcss-linux-arm64-musl: "npm:1.29.3" - lightningcss-linux-x64-gnu: "npm:1.29.3" - lightningcss-linux-x64-musl: "npm:1.29.3" - lightningcss-win32-arm64-msvc: "npm:1.29.3" - lightningcss-win32-x64-msvc: "npm:1.29.3" + lightningcss-darwin-arm64: "npm:1.30.1" + lightningcss-darwin-x64: "npm:1.30.1" + lightningcss-freebsd-x64: "npm:1.30.1" + lightningcss-linux-arm-gnueabihf: "npm:1.30.1" + lightningcss-linux-arm64-gnu: "npm:1.30.1" + lightningcss-linux-arm64-musl: "npm:1.30.1" + lightningcss-linux-x64-gnu: "npm:1.30.1" + lightningcss-linux-x64-musl: "npm:1.30.1" + lightningcss-win32-arm64-msvc: "npm:1.30.1" + lightningcss-win32-x64-msvc: "npm:1.30.1" dependenciesMeta: lightningcss-darwin-arm64: optional: true @@ -3528,7 +4359,7 @@ __metadata: optional: true lightningcss-win32-x64-msvc: optional: true - checksum: 10/90933a666975f8e4f2b1bed1ec698a0072f96d2cd118e358932456a46105d62b72b701e4a5da5bd66f0b6e3beac2c65d0be2306acdf3f30603d86143502cce88 + checksum: 10/6c921135216cc498dfcb87e35dffe8432e99306cbd58009c598b1daf20c81cc14535abbd4c1066e5d1faf4080ed44a2995e8ecc343633db4897a2d041b76fb05 languageName: node linkType: hard @@ -3548,6 +4379,13 @@ __metadata: languageName: node linkType: hard +"lodash@npm:^4.17.21": + version: 4.17.21 + resolution: "lodash@npm:4.17.21" + checksum: 10/c08619c038846ea6ac754abd6dd29d2568aa705feb69339e836dfa8d8b09abbb2f859371e86863eda41848221f9af43714491467b5b0299122431e202bb0c532 + languageName: node + linkType: hard + "longest-streak@npm:^3.0.0": version: 3.1.0 resolution: "longest-streak@npm:3.1.0" @@ -3555,7 +4393,7 @@ __metadata: languageName: node linkType: hard -"loose-envify@npm:^1.1.0, loose-envify@npm:^1.4.0": +"loose-envify@npm:^1.4.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" dependencies: @@ -3566,13 +4404,32 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.2.0": +"lru-cache@npm:^10.0.1, lru-cache@npm:^10.2.0": version: 10.4.3 resolution: "lru-cache@npm:10.4.3" checksum: 10/e6e90267360476720fa8e83cc168aa2bf0311f3f2eea20a6ba78b90a885ae72071d9db132f40fda4129c803e7dcec3a6b6a6fbb44ca90b081630b810b5d6a41a languageName: node linkType: hard +"make-fetch-happen@npm:^14.0.3": + version: 14.0.3 + resolution: "make-fetch-happen@npm:14.0.3" + dependencies: + "@npmcli/agent": "npm:^3.0.0" + cacache: "npm:^19.0.1" + http-cache-semantics: "npm:^4.1.1" + minipass: "npm:^7.0.2" + minipass-fetch: "npm:^4.0.0" + minipass-flush: "npm:^1.0.5" + minipass-pipeline: "npm:^1.2.4" + negotiator: "npm:^1.0.0" + proc-log: "npm:^5.0.0" + promise-retry: "npm:^2.0.1" + ssri: "npm:^12.0.0" + checksum: 10/fce0385840b6d86b735053dfe941edc2dd6468fda80fe74da1eeff10cbd82a75760f406194f2bc2fa85b99545b2bc1f84c08ddf994b21830775ba2d1a87e8bdf + languageName: node + linkType: hard + "markdown-extensions@npm:^2.0.0": version: 2.0.0 resolution: "markdown-extensions@npm:2.0.0" @@ -3622,8 +4479,8 @@ __metadata: linkType: hard "mdast-util-mdx-jsx@npm:^3.0.0": - version: 3.1.3 - resolution: "mdast-util-mdx-jsx@npm:3.1.3" + version: 3.2.0 + resolution: "mdast-util-mdx-jsx@npm:3.2.0" dependencies: "@types/estree-jsx": "npm:^1.0.0" "@types/hast": "npm:^3.0.0" @@ -3637,7 +4494,7 @@ __metadata: stringify-entities: "npm:^4.0.0" unist-util-stringify-position: "npm:^4.0.0" vfile-message: "npm:^4.0.0" - checksum: 10/6c14f271f1380fd512038247f45887b7aa71bbf4acd8881651a317b61706b114f2582f62f7777d0eacd42c4a7b979802825c2a2fd8bb7c46a1ab931ccb1ddf3e + checksum: 10/62cd650a522e5d72ea6afd6d4a557fc86525b802d097a29a2fbe17d22e7b97c502a580611873e4d685777fe77c6ff8d39fb6e37d026b3acbc86c3b24927f4ad9 languageName: node linkType: hard @@ -3654,7 +4511,7 @@ __metadata: languageName: node linkType: hard -"mdast-util-mdxjs-esm@npm:^2.0.0": +"mdast-util-mdxjs-esm@npm:^2.0.0, mdast-util-mdxjs-esm@npm:^2.0.1": version: 2.0.1 resolution: "mdast-util-mdxjs-esm@npm:2.0.1" dependencies: @@ -3729,8 +4586,8 @@ __metadata: linkType: hard "micromark-core-commonmark@npm:^2.0.0": - version: 2.0.2 - resolution: "micromark-core-commonmark@npm:2.0.2" + version: 2.0.3 + resolution: "micromark-core-commonmark@npm:2.0.3" dependencies: decode-named-character-reference: "npm:^1.0.0" devlop: "npm:^1.0.0" @@ -3748,13 +4605,13 @@ __metadata: micromark-util-subtokenize: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/eafa6b9cd6fd9f51efa7795824af9a765e24a4519855a5b6dfcb0f619a93d90599d39a261f626bfcc1dfa64f22430f7a677a83cb6ce4bd8e4eeabc892610c016 + checksum: 10/2b98b9eba1463850ebd8f338f966bd2113dafe764b490ebee3dccab3764d3c48b53fe67673297530e56bf54f58de27dfd1952ed79c5b4e32047cb7f29bd807f2 languageName: node linkType: hard "micromark-extension-mdx-expression@npm:^3.0.0": - version: 3.0.0 - resolution: "micromark-extension-mdx-expression@npm:3.0.0" + version: 3.0.1 + resolution: "micromark-extension-mdx-expression@npm:3.0.1" dependencies: "@types/estree": "npm:^1.0.0" devlop: "npm:^1.0.0" @@ -3764,15 +4621,14 @@ __metadata: micromark-util-events-to-acorn: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/a5592160319d4617362f6b72a6fc44b5570466afa07419d44bcfdd9398a77a5693d7c5f8da7b3ff4682edf6209d4781835f5d2e3166fdf6bba37db456fd2d091 + checksum: 10/a185e1787fe6d49d0e435690affd4b83ce319f88a08c57d2460d37d5c0a75ea64aa49a4a116b6d37f91389dc04351e1826aa834519a9f25fc31e1424962c6eb7 languageName: node linkType: hard "micromark-extension-mdx-jsx@npm:^3.0.0": - version: 3.0.1 - resolution: "micromark-extension-mdx-jsx@npm:3.0.1" + version: 3.0.2 + resolution: "micromark-extension-mdx-jsx@npm:3.0.2" dependencies: - "@types/acorn": "npm:^4.0.0" "@types/estree": "npm:^1.0.0" devlop: "npm:^1.0.0" estree-util-is-identifier-name: "npm:^3.0.0" @@ -3783,7 +4639,7 @@ __metadata: micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" vfile-message: "npm:^4.0.0" - checksum: 10/2cc0277d91c3c85d52e88755d17d021b5eab6fa03a578a9965f9d3d2c184dbc1accce63e7f8437a092ceeb602840ef451d4dce6dc9e8c13df0bc76e741080a89 + checksum: 10/a85cdb7c972fbb2cc8f0a64adc808b2b62bc2d79dbdd31fcd3208ff15aafa0198b002022840b2c65b5bff6f2a8c2c4a59a32a89f3482e6e183114b476e98e25c languageName: node linkType: hard @@ -3853,8 +4709,8 @@ __metadata: linkType: hard "micromark-factory-mdx-expression@npm:^2.0.0": - version: 2.0.2 - resolution: "micromark-factory-mdx-expression@npm:2.0.2" + version: 2.0.3 + resolution: "micromark-factory-mdx-expression@npm:2.0.3" dependencies: "@types/estree": "npm:^1.0.0" devlop: "npm:^1.0.0" @@ -3865,7 +4721,7 @@ __metadata: micromark-util-types: "npm:^2.0.0" unist-util-position-from-estree: "npm:^2.0.0" vfile-message: "npm:^4.0.0" - checksum: 10/d5285fa98018f14a058c7cd4a961aacedd2d3c4f4fddd4c58c16f1e640d1284a8f581f4d00fa3e18c06ed302ce23bca23f6a01edd66064c23c9057e65385a62d + checksum: 10/afadae88a18f31afa564747101e076011c56457454b30294ae55aeea7efee8626ddc3bad0f0f43649008f89b8784782b5adec143fdf477fb352354d76f08db55 languageName: node linkType: hard @@ -3972,10 +4828,9 @@ __metadata: linkType: hard "micromark-util-events-to-acorn@npm:^2.0.0": - version: 2.0.2 - resolution: "micromark-util-events-to-acorn@npm:2.0.2" + version: 2.0.3 + resolution: "micromark-util-events-to-acorn@npm:2.0.3" dependencies: - "@types/acorn": "npm:^4.0.0" "@types/estree": "npm:^1.0.0" "@types/unist": "npm:^3.0.0" devlop: "npm:^1.0.0" @@ -3983,7 +4838,7 @@ __metadata: micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" vfile-message: "npm:^4.0.0" - checksum: 10/475367e716c4d24f2a57464a7f2c8aa507ae36c05b7767fd652895525f3f0a1179ea3219cabccc0f3038bb5e4f9cce5390d530dc56decaa5f1786bda42739810 + checksum: 10/0d87e49b897636dc0e84b4bd06b6fa9e6abcd40ab90c9431e36737c85c444d3db1e4f9b8f51433422b1bedc46f086890ce96671b5a795230c6b7b09cb53d9aba languageName: node linkType: hard @@ -4024,14 +4879,14 @@ __metadata: linkType: hard "micromark-util-subtokenize@npm:^2.0.0": - version: 2.0.3 - resolution: "micromark-util-subtokenize@npm:2.0.3" + version: 2.1.0 + resolution: "micromark-util-subtokenize@npm:2.1.0" dependencies: devlop: "npm:^1.0.0" micromark-util-chunked: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/57b26f129f46424a4670bb47c50f13c7309bb1bc557c02150a788d1634337c1bb25a3523af3d6dffc29aaec873b3bd88fd931bfff34e64284e6436e23873ca22 + checksum: 10/5f18c70cb952a414a4d161f5d6a5254d33c7dfcd56577e592ef2e172a0414058d3531a3554f43538f14e243592fffbc2e68ddaf6a41c54577b3ba7beb555d3dc languageName: node linkType: hard @@ -4043,15 +4898,15 @@ __metadata: linkType: hard "micromark-util-types@npm:^2.0.0": - version: 2.0.1 - resolution: "micromark-util-types@npm:2.0.1" - checksum: 10/69c5e18e6ba4e12473d6fe5f1a7cc113ac1d4bfc23c7ad57b16a5e4bfd09ef48b7c17a40c39d43996f2078ad898efd3f1945007c14f395abd55f2af03d413acd + version: 2.0.2 + resolution: "micromark-util-types@npm:2.0.2" + checksum: 10/a9eb067bd9384eab61942285d53738aa22f3fef4819eaf20249bec6ec13f1e4da2800230fd0ceb7e705108987aa9062fe3e9a8e5e48aa60180db80b9489dc3e2 languageName: node linkType: hard "micromark@npm:^4.0.0": - version: 4.0.1 - resolution: "micromark@npm:4.0.1" + version: 4.0.2 + resolution: "micromark@npm:4.0.2" dependencies: "@types/debug": "npm:^4.0.0" debug: "npm:^4.0.0" @@ -4070,11 +4925,11 @@ __metadata: micromark-util-subtokenize: "npm:^2.0.0" micromark-util-symbol: "npm:^2.0.0" micromark-util-types: "npm:^2.0.0" - checksum: 10/b948b1b239e589826bdaf2835daa9e88873e23d4b9148cd22109a86d4af55b96345cf9fc9059b6b19ae828f64d55e66f376ca3aeb4af3d2b0241560125f5dae6 + checksum: 10/1b85e49c8f71013df2d07a59e477deb72cd325d41cc15f35b2aa52b8b7a93fed45498ce3e18ed34464a9afa9ba8a9210b2509454b2a2d16ac06c7429f562bfac languageName: node linkType: hard -"micromatch@npm:^4.0.8": +"micromatch@npm:^4.0.4, micromatch@npm:^4.0.8": version: 4.0.8 resolution: "micromatch@npm:4.0.8" dependencies: @@ -4093,7 +4948,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.1, minimatch@npm:^9.0.4": +"minimatch@npm:^9.0.4": version: 9.0.5 resolution: "minimatch@npm:9.0.5" dependencies: @@ -4109,34 +4964,112 @@ __metadata: languageName: node linkType: hard -"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0": +"minipass-collect@npm:^2.0.1": + version: 2.0.1 + resolution: "minipass-collect@npm:2.0.1" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10/b251bceea62090f67a6cced7a446a36f4cd61ee2d5cea9aee7fff79ba8030e416327a1c5aa2908dc22629d06214b46d88fdab8c51ac76bacbf5703851b5ad342 + languageName: node + linkType: hard + +"minipass-fetch@npm:^4.0.0": + version: 4.0.1 + resolution: "minipass-fetch@npm:4.0.1" + dependencies: + encoding: "npm:^0.1.13" + minipass: "npm:^7.0.3" + minipass-sized: "npm:^1.0.3" + minizlib: "npm:^3.0.1" + dependenciesMeta: + encoding: + optional: true + checksum: 10/7ddfebdbb87d9866e7b5f7eead5a9e3d9d507992af932a11d275551f60006cf7d9178e66d586dbb910894f3e3458d27c0ddf93c76e94d49d0a54a541ddc1263d + languageName: node + linkType: hard + +"minipass-flush@npm:^1.0.5": + version: 1.0.5 + resolution: "minipass-flush@npm:1.0.5" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10/56269a0b22bad756a08a94b1ffc36b7c9c5de0735a4dd1ab2b06c066d795cfd1f0ac44a0fcae13eece5589b908ecddc867f04c745c7009be0b566421ea0944cf + languageName: node + linkType: hard + +"minipass-pipeline@npm:^1.2.4": + version: 1.2.4 + resolution: "minipass-pipeline@npm:1.2.4" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10/b14240dac0d29823c3d5911c286069e36d0b81173d7bdf07a7e4a91ecdef92cdff4baaf31ea3746f1c61e0957f652e641223970870e2353593f382112257971b + languageName: node + linkType: hard + +"minipass-sized@npm:^1.0.3": + version: 1.0.3 + resolution: "minipass-sized@npm:1.0.3" + dependencies: + minipass: "npm:^3.0.0" + checksum: 10/40982d8d836a52b0f37049a0a7e5d0f089637298e6d9b45df9c115d4f0520682a78258905e5c8b180fb41b593b0a82cc1361d2c74b45f7ada66334f84d1ecfdd + languageName: node + linkType: hard + +"minipass@npm:^3.0.0": + version: 3.3.6 + resolution: "minipass@npm:3.3.6" + dependencies: + yallist: "npm:^4.0.0" + checksum: 10/a5c6ef069f70d9a524d3428af39f2b117ff8cd84172e19b754e7264a33df460873e6eb3d6e55758531580970de50ae950c496256bb4ad3691a2974cddff189f0 + languageName: node + linkType: hard + +"minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": version: 7.1.2 resolution: "minipass@npm:7.1.2" checksum: 10/c25f0ee8196d8e6036661104bacd743785b2599a21de5c516b32b3fa2b83113ac89a2358465bc04956baab37ffb956ae43be679b2262bf7be15fce467ccd7950 languageName: node linkType: hard -"motion-dom@npm:^12.5.0": - version: 12.5.0 - resolution: "motion-dom@npm:12.5.0" +"minizlib@npm:^3.0.1": + version: 3.0.2 + resolution: "minizlib@npm:3.0.2" dependencies: - motion-utils: "npm:^12.5.0" - checksum: 10/289e3d5567053e9b84223df9b482bb9180732c0cb6276e7982a73ddad0f76e47f8e0f69e4cdf93d7a689ad021fce837fa8a19c8b61bf56d71bdfc0e590bc3e7e + minipass: "npm:^7.1.2" + checksum: 10/c075bed1594f68dcc8c35122333520112daefd4d070e5d0a228bd4cf5580e9eed3981b96c0ae1d62488e204e80fd27b2b9d0068ca9a5ef3993e9565faf63ca41 languageName: node linkType: hard -"motion-utils@npm:^12.5.0": - version: 12.5.0 - resolution: "motion-utils@npm:12.5.0" - checksum: 10/f2d754a9e1c4cd829f0703ce47bbeb3e9967994a9cb35e759f34de16af6c520a4959b04ff6998211ca67dc7bfe0002d9b2465858167b1971b0403f63289f97fc +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10/16fd79c28645759505914561e249b9a1f5fe3362279ad95487a4501e4467abeb714fd35b95307326b8fd03f3c7719065ef11a6f97b7285d7888306d1bd2232ba + languageName: node + linkType: hard + +"motion-dom@npm:^12.17.0": + version: 12.17.0 + resolution: "motion-dom@npm:12.17.0" + dependencies: + motion-utils: "npm:^12.12.1" + checksum: 10/54b482d643ca12d895e8a0860809b2b53f2e7c2981d12f3d1230f5bd6154cb59df6ab81a690681df7a526da283aaf76acbf351b148e2b805ad5f8ce97156e061 + languageName: node + linkType: hard + +"motion-utils@npm:^12.12.1": + version: 12.12.1 + resolution: "motion-utils@npm:12.12.1" + checksum: 10/679503df10a1cd7ad58f9ed2f864acb5ecbadf380a668874f0cc6bdc1155278bac0cce73e3f703df19532f2bd922e3500fde179e8f76386e9651f8b1bd0cfe6d languageName: node linkType: hard "motion@npm:^12.4.1": - version: 12.5.0 - resolution: "motion@npm:12.5.0" + version: 12.17.0 + resolution: "motion@npm:12.17.0" dependencies: - framer-motion: "npm:^12.5.0" + framer-motion: "npm:^12.17.0" tslib: "npm:^2.4.0" peerDependencies: "@emotion/is-prop-valid": "*" @@ -4149,7 +5082,7 @@ __metadata: optional: true react-dom: optional: true - checksum: 10/15910d37a14b91236c27c8cc6d12ae157cd1e6b55700fc58a0d271954236fae8e676b1ac9f705cb770c235892925fc6bbdb1f612dfb4018a5d4c0171964f5b3a + checksum: 10/4fde3c4f39fa872cb27a41ddf39dcf20a9a066428ce07cf7455e2a4779d916a47cb3141e8c4c970f9d7b8e8818b822f3eeb86761d61904a18383b82426f5f3ca languageName: node linkType: hard @@ -4161,11 +5094,20 @@ __metadata: linkType: hard "nanoid@npm:^3.3.6": - version: 3.3.8 - resolution: "nanoid@npm:3.3.8" + version: 3.3.11 + resolution: "nanoid@npm:3.3.11" bin: nanoid: bin/nanoid.cjs - checksum: 10/2d1766606cf0d6f47b6f0fdab91761bb81609b2e3d367027aff45e6ee7006f660fb7e7781f4a34799fe6734f1268eeed2e37a5fdee809ade0c2d4eb11b0f9c40 + checksum: 10/73b5afe5975a307aaa3c95dfe3334c52cdf9ae71518176895229b8d65ab0d1c0417dd081426134eb7571c055720428ea5d57c645138161e7d10df80815527c48 + languageName: node + linkType: hard + +"napi-postinstall@npm:^0.2.2": + version: 0.2.4 + resolution: "napi-postinstall@npm:0.2.4" + bin: + napi-postinstall: lib/cli.js + checksum: 10/286785f884b872102fb284847ecc693101f70126b1fc7a97e19293929ce7f08802b41f89398015cce0797070ea3ce6871939a3c1e693c04cf594f7939dbe8cfb languageName: node linkType: hard @@ -4176,31 +5118,57 @@ __metadata: languageName: node linkType: hard -"next@npm:14.2.26": - version: 14.2.26 - resolution: "next@npm:14.2.26" +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10/b5734e87295324fabf868e36fb97c84b7d7f3156ec5f4ee5bf6e488079c11054f818290fc33804cef7b1ee21f55eeb14caea83e7dafae6492a409b3e573153e5 + languageName: node + linkType: hard + +"next-mdx-remote-client@npm:^2.1.2": + version: 2.1.2 + resolution: "next-mdx-remote-client@npm:2.1.2" dependencies: - "@next/env": "npm:14.2.26" - "@next/swc-darwin-arm64": "npm:14.2.26" - "@next/swc-darwin-x64": "npm:14.2.26" - "@next/swc-linux-arm64-gnu": "npm:14.2.26" - "@next/swc-linux-arm64-musl": "npm:14.2.26" - "@next/swc-linux-x64-gnu": "npm:14.2.26" - "@next/swc-linux-x64-musl": "npm:14.2.26" - "@next/swc-win32-arm64-msvc": "npm:14.2.26" - "@next/swc-win32-ia32-msvc": "npm:14.2.26" - "@next/swc-win32-x64-msvc": "npm:14.2.26" - "@swc/helpers": "npm:0.5.5" + "@babel/code-frame": "npm:^7.27.1" + "@mdx-js/mdx": "npm:^3.1.0" + "@mdx-js/react": "npm:^3.1.0" + remark-mdx-remove-esm: "npm:^1.1.0" + serialize-error: "npm:^12.0.0" + vfile: "npm:^6.0.3" + vfile-matter: "npm:^5.0.1" + peerDependencies: + react: ^19.1.0 + react-dom: ^19.1.0 + checksum: 10/610e95bff6c1dcdb4d1fefc9333ac748f1899cbca1ea551e784cd1e8cfd077c14d6bb8ab27826886f354cc3b9cf700fe25810263f996c53f824a2cfdbc5a064f + languageName: node + linkType: hard + +"next@npm:15.3.4": + version: 15.3.4 + resolution: "next@npm:15.3.4" + dependencies: + "@next/env": "npm:15.3.4" + "@next/swc-darwin-arm64": "npm:15.3.4" + "@next/swc-darwin-x64": "npm:15.3.4" + "@next/swc-linux-arm64-gnu": "npm:15.3.4" + "@next/swc-linux-arm64-musl": "npm:15.3.4" + "@next/swc-linux-x64-gnu": "npm:15.3.4" + "@next/swc-linux-x64-musl": "npm:15.3.4" + "@next/swc-win32-arm64-msvc": "npm:15.3.4" + "@next/swc-win32-x64-msvc": "npm:15.3.4" + "@swc/counter": "npm:0.1.3" + "@swc/helpers": "npm:0.5.15" busboy: "npm:1.6.0" caniuse-lite: "npm:^1.0.30001579" - graceful-fs: "npm:^4.2.11" postcss: "npm:8.4.31" - styled-jsx: "npm:5.1.1" + sharp: "npm:^0.34.1" + styled-jsx: "npm:5.1.6" peerDependencies: "@opentelemetry/api": ^1.1.0 "@playwright/test": ^1.41.2 - react: ^18.2.0 - react-dom: ^18.2.0 + babel-plugin-react-compiler: "*" + react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 + react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0 sass: ^1.3.0 dependenciesMeta: "@next/swc-darwin-arm64": @@ -4217,20 +5185,60 @@ __metadata: optional: true "@next/swc-win32-arm64-msvc": optional: true - "@next/swc-win32-ia32-msvc": - optional: true "@next/swc-win32-x64-msvc": optional: true + sharp: + optional: true peerDependenciesMeta: "@opentelemetry/api": optional: true "@playwright/test": optional: true + babel-plugin-react-compiler: + optional: true sass: optional: true bin: next: dist/bin/next - checksum: 10/9bd8b2ef40076b251d036c6d3a3b435095ff941bab7166ebc3c75bd832c1812eb368f8dae1e56ef4bf600a81d0ad8190d778d610aa062ffa7c4c4f126cae7f13 + checksum: 10/bcc781ca5abba6a29408431f81b57598708871796fe4c70d1187cc92ca4905467a6a3cde32840cb7911099d54a93c1543c130e4dea2b59dbf9753f5850a8efdf + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 11.2.0 + resolution: "node-gyp@npm:11.2.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + graceful-fs: "npm:^4.2.6" + make-fetch-happen: "npm:^14.0.3" + nopt: "npm:^8.0.0" + proc-log: "npm:^5.0.0" + semver: "npm:^7.3.5" + tar: "npm:^7.4.3" + tinyglobby: "npm:^0.2.12" + which: "npm:^5.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10/806fd8e3adc9157e17bf0d4a2c899cf6b98a0bbe9f453f630094ce791866271f6cddcaf2133e6513715d934fcba2014d287c7053d5d7934937b3a34d5a3d84ad + languageName: node + linkType: hard + +"nopt@npm:^8.0.0": + version: 8.1.0 + resolution: "nopt@npm:8.1.0" + dependencies: + abbrev: "npm:^3.0.0" + bin: + nopt: bin/nopt.js + checksum: 10/26ab456c51a96f02a9e5aa8d1b80ef3219f2070f3f3528a040e32fb735b1e651e17bdf0f1476988d3a46d498f35c65ed662d122f340d38ce4a7e71dd7b20c4bc + languageName: node + linkType: hard + +"normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": + version: 3.0.0 + resolution: "normalize-path@npm:3.0.0" + checksum: 10/88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20 languageName: node linkType: hard @@ -4241,10 +5249,10 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.3": - version: 1.13.3 - resolution: "object-inspect@npm:1.13.3" - checksum: 10/14cb973d8381c69e14d7f1c8c75044eb4caf04c6dabcf40ca5c2ce42dc2073ae0bb2a9939eeca142b0c05215afaa1cd5534adb7c8879c32cba2576e045ed8368 +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10/aa13b1190ad3e366f6c83ad8a16ed37a19ed57d267385aa4bfdccda833d7b90465c057ff6c55d035a6b2e52c1a2295582b294217a0a3a1ae7abdd6877ef781fb languageName: node linkType: hard @@ -4269,14 +5277,15 @@ __metadata: languageName: node linkType: hard -"object.entries@npm:^1.1.8": - version: 1.1.8 - resolution: "object.entries@npm:1.1.8" +"object.entries@npm:^1.1.9": + version: 1.1.9 + resolution: "object.entries@npm:1.1.9" dependencies: - call-bind: "npm:^1.0.7" + call-bind: "npm:^1.0.8" + call-bound: "npm:^1.0.4" define-properties: "npm:^1.2.1" - es-object-atoms: "npm:^1.0.0" - checksum: 10/2301918fbd1ee697cf6ff7cd94f060c738c0a7d92b22fd24c7c250e9b593642c9707ad2c44d339303c1439c5967d8964251cdfc855f7f6ec55db2dd79e8dc2a7 + es-object-atoms: "npm:^1.1.1" + checksum: 10/24163ab1e1e013796693fc5f5d349e8b3ac0b6a34a7edb6c17d3dd45c6a8854145780c57d302a82512c1582f63720f4b4779d6c1cfba12cbb1420b978802d8a3 languageName: node linkType: hard @@ -4324,14 +5333,14 @@ __metadata: languageName: node linkType: hard -"oniguruma-to-es@npm:0.10.0": - version: 0.10.0 - resolution: "oniguruma-to-es@npm:0.10.0" +"oniguruma-to-es@npm:^2.2.0": + version: 2.3.0 + resolution: "oniguruma-to-es@npm:2.3.0" dependencies: emoji-regex-xs: "npm:^1.0.0" regex: "npm:^5.1.1" regex-recursion: "npm:^5.1.1" - checksum: 10/09756001a74218b26d18940bea3ebb00d1949aa7ac142def3a94a4d256371fea169f52088ea32a6a23ca21338be56427fd9f0264907cee663e7ab147152638f7 + checksum: 10/7ac89fe04791650c21a146e58c985de394597e0ab3eb7d7c46699d09f87d6aca63d9f2470f1473c5adfa16961c360df6858e6a24b2429ebd7c73620ca68aec98 languageName: node linkType: hard @@ -4389,6 +5398,20 @@ __metadata: languageName: node linkType: hard +"p-map@npm:^7.0.2": + version: 7.0.3 + resolution: "p-map@npm:7.0.3" + checksum: 10/2ef48ccfc6dd387253d71bf502604f7893ed62090b2c9d73387f10006c342606b05233da0e4f29388227b61eb5aeface6197e166520c465c234552eeab2fe633 + languageName: node + linkType: hard + +"package-json-from-dist@npm:^1.0.0": + version: 1.0.1 + resolution: "package-json-from-dist@npm:1.0.1" + checksum: 10/58ee9538f2f762988433da00e26acc788036914d57c71c246bf0be1b60cdbd77dd60b6a3e1a30465f0b248aeb80079e0b34cb6050b1dfa18c06953bb1cbc7602 + languageName: node + linkType: hard + "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -4441,7 +5464,7 @@ __metadata: languageName: node linkType: hard -"path-scurry@npm:^1.10.1": +"path-scurry@npm:^1.11.1": version: 1.11.1 resolution: "path-scurry@npm:1.11.1" dependencies: @@ -4451,24 +5474,31 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0": +"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1": version: 1.1.1 resolution: "picocolors@npm:1.1.1" checksum: 10/e1cf46bf84886c79055fdfa9dcb3e4711ad259949e3565154b004b260cd356c5d54b31a1437ce9782624bf766272fe6b0154f5f0c744fb7af5d454d2b60db045 languageName: node linkType: hard -"picomatch@npm:^2.3.1": +"picomatch@npm:^2.0.4, picomatch@npm:^2.2.1, picomatch@npm:^2.3.1": version: 2.3.1 resolution: "picomatch@npm:2.3.1" checksum: 10/60c2595003b05e4535394d1da94850f5372c9427ca4413b71210f437f7b2ca091dbd611c45e8b37d10036fa8eade25c1b8951654f9d3973bfa66a2ff4d3b08bc languageName: node linkType: hard +"picomatch@npm:^4.0.2": + version: 4.0.2 + resolution: "picomatch@npm:4.0.2" + checksum: 10/ce617b8da36797d09c0baacb96ca8a44460452c89362d7cb8f70ca46b4158ba8bc3606912de7c818eb4a939f7f9015cef3c766ec8a0c6bfc725fdc078e39c717 + languageName: node + linkType: hard + "possible-typed-array-names@npm:^1.0.0": - version: 1.0.0 - resolution: "possible-typed-array-names@npm:1.0.0" - checksum: 10/8ed3e96dfeea1c5880c1f4c9cb707e5fb26e8be22f14f82ef92df20fd2004e635c62ba47fbe8f2bb63bfd80dac1474be2fb39798da8c2feba2815435d1f749af + version: 1.1.0 + resolution: "possible-typed-array-names@npm:1.1.0" + checksum: 10/2f44137b8d3dd35f4a7ba7469eec1cd9cfbb46ec164b93a5bc1f4c3d68599c9910ee3b91da1d28b4560e9cc8414c3cd56fedc07259c67e52cc774476270d3302 languageName: node linkType: hard @@ -4490,6 +5520,13 @@ __metadata: languageName: node linkType: hard +"proc-log@npm:^5.0.0": + version: 5.0.0 + resolution: "proc-log@npm:5.0.0" + checksum: 10/35610bdb0177d3ab5d35f8827a429fb1dc2518d9e639f2151ac9007f01a061c30e0c635a970c9b00c39102216160f6ec54b62377c92fac3b7bfc2ad4b98d195c + languageName: node + linkType: hard + "process@npm:^0.11.10": version: 0.11.10 resolution: "process@npm:0.11.10" @@ -4497,6 +5534,16 @@ __metadata: languageName: node linkType: hard +"promise-retry@npm:^2.0.1": + version: 2.0.1 + resolution: "promise-retry@npm:2.0.1" + dependencies: + err-code: "npm:^2.0.2" + retry: "npm:^0.12.0" + checksum: 10/96e1a82453c6c96eef53a37a1d6134c9f2482f94068f98a59145d0986ca4e497bf110a410adf73857e588165eab3899f0ebcf7b3890c1b3ce802abc0d65967d4 + languageName: node + linkType: hard + "prop-types@npm:^15.8.1": version: 15.8.1 resolution: "prop-types@npm:15.8.1" @@ -4508,10 +5555,10 @@ __metadata: languageName: node linkType: hard -"property-information@npm:^6.0.0": - version: 6.5.0 - resolution: "property-information@npm:6.5.0" - checksum: 10/fced94f3a09bf651ad1824d1bdc8980428e3e480e6d01e98df6babe2cc9d45a1c52eee9a7736d2006958f9b394eb5964dedd37e23038086ddc143fc2fd5e426c +"property-information@npm:^7.0.0": + version: 7.1.0 + resolution: "property-information@npm:7.1.0" + checksum: 10/896d38a52ad7170de73f832d277c69e76a9605d941ebb3f0d6e56271414a7fdf95ff6d2819e68036b8a0c7d2d4d88bf1d4a5765c032cb19c2343567ee3a14b15 languageName: node linkType: hard @@ -4529,15 +5576,14 @@ __metadata: languageName: node linkType: hard -"react-dom@npm:^18.0.2": - version: 18.3.1 - resolution: "react-dom@npm:18.3.1" +"react-dom@npm:19.1.0": + version: 19.1.0 + resolution: "react-dom@npm:19.1.0" dependencies: - loose-envify: "npm:^1.1.0" - scheduler: "npm:^0.23.2" + scheduler: "npm:^0.26.0" peerDependencies: - react: ^18.3.1 - checksum: 10/3f4b73a3aa083091173b29812b10394dd06f4ac06aff410b74702cfb3aa29d7b0ced208aab92d5272919b612e5cda21aeb1d54191848cf6e46e9e354f3541f81 + react: ^19.1.0 + checksum: 10/c5b58605862c7b0bb044416b01c73647bb8e89717fb5d7a2c279b11815fb7b49b619fe685c404e59f55eb52c66831236cc565c25ee1c2d042739f4a2cc538aa2 languageName: node linkType: hard @@ -4559,25 +5605,39 @@ __metadata: languageName: node linkType: hard -"react@npm:^18.0.2": - version: 18.3.1 - resolution: "react@npm:18.3.1" +"react-property@npm:2.0.2": + version: 2.0.2 + resolution: "react-property@npm:2.0.2" + checksum: 10/3a4bc1951b2b7992cb8a2d3f12016dd0920d1c06eb58b456204a6ae1210401d62baece098d3200ed8a0513dde247a5d96ffdb24f354e32ce5a9b26fbd8552668 + languageName: node + linkType: hard + +"react@npm:19.1.0": + version: 19.1.0 + resolution: "react@npm:19.1.0" + checksum: 10/d0180689826fd9de87e839c365f6f361c561daea397d61d724687cae88f432a307d1c0f53a0ee95ddbe3352c10dac41d7ff1ad85530fb24951b27a39e5398db4 + languageName: node + linkType: hard + +"readdirp@npm:~3.6.0": + version: 3.6.0 + resolution: "readdirp@npm:3.6.0" dependencies: - loose-envify: "npm:^1.1.0" - checksum: 10/261137d3f3993eaa2368a83110466fc0e558bc2c7f7ae7ca52d94f03aac945f45146bd85e5f481044db1758a1dbb57879e2fcdd33924e2dde1bdc550ce73f7bf + picomatch: "npm:^2.2.1" + checksum: 10/196b30ef6ccf9b6e18c4e1724b7334f72a093d011a99f3b5920470f0b3406a51770867b3e1ae9711f227ef7a7065982f6ee2ce316746b2cb42c88efe44297fe7 languageName: node linkType: hard "recast@npm:^0.23.5": - version: 0.23.9 - resolution: "recast@npm:0.23.9" + version: 0.23.11 + resolution: "recast@npm:0.23.11" dependencies: ast-types: "npm:^0.16.1" esprima: "npm:~4.0.0" source-map: "npm:~0.6.1" tiny-invariant: "npm:^1.3.3" tslib: "npm:^2.0.1" - checksum: 10/d60584be179d81a82fbe58b5bbe009aa42831ee114a21a3e3a22bda91334e0b8a1a4610dca8ecb7f9ea1426da4febc08134d3003085ad6ecee478d1808eb8796 + checksum: 10/a622b7848efe13a59a40c9a1a3a8178433eae1048780e04d7392406e2d67fc29e3efa84b3aa8cfda28fd58989f4b59fa968bed295b739987a666bd11cc57a5b2 languageName: node linkType: hard @@ -4645,13 +5705,6 @@ __metadata: languageName: node linkType: hard -"regenerator-runtime@npm:^0.14.0": - version: 0.14.1 - resolution: "regenerator-runtime@npm:0.14.1" - checksum: 10/5db3161abb311eef8c45bcf6565f4f378f785900ed3945acf740a9888c792f75b98ecb77f0775f3bf95502ff423529d23e94f41d80c8256e8fa05ed4b07cf471 - languageName: node - linkType: hard - "regex-recursion@npm:^5.1.1": version: 5.1.1 resolution: "regex-recursion@npm:5.1.1" @@ -4678,7 +5731,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.3": +"regexp.prototype.flags@npm:^1.5.3, regexp.prototype.flags@npm:^1.5.4": version: 1.5.4 resolution: "regexp.prototype.flags@npm:1.5.4" dependencies: @@ -4703,6 +5756,19 @@ __metadata: languageName: node linkType: hard +"remark-mdx-remove-esm@npm:^1.1.0": + version: 1.2.0 + resolution: "remark-mdx-remove-esm@npm:1.2.0" + dependencies: + "@types/mdast": "npm:^4.0.4" + mdast-util-mdxjs-esm: "npm:^2.0.1" + unist-util-remove: "npm:^4.0.0" + peerDependencies: + unified: ^11 + checksum: 10/0a1155e08395ab73f877948455fc04d7457864f7556617efabecae7ea1b441cec2ca7ee9672e16a6cd56f2a16c57a4778f901e77d19052d1dd245de5bdf4618f + languageName: node + linkType: hard + "remark-mdx@npm:^3.0.0": version: 3.1.0 resolution: "remark-mdx@npm:3.1.0" @@ -4726,15 +5792,22 @@ __metadata: linkType: hard "remark-rehype@npm:^11.0.0": - version: 11.1.1 - resolution: "remark-rehype@npm:11.1.1" + version: 11.1.2 + resolution: "remark-rehype@npm:11.1.2" dependencies: "@types/hast": "npm:^3.0.0" "@types/mdast": "npm:^4.0.0" mdast-util-to-hast: "npm:^13.0.0" unified: "npm:^11.0.0" vfile: "npm:^6.0.0" - checksum: 10/39404bd19c57b2b69660be7e3d587ddb2240495845d42fad3bcc506c9c132d07abacb0a20182b73c530857b2da0c463ad5658382b448243ce432152ab49af08d + checksum: 10/b5374a0bf08398431c92740d0cd9b20aea9df44cee12326820ddcc1b7ee642706604006461ea9799554c347e7caf31e7432132a03b97c508e1f77d29c423bd86 + languageName: node + linkType: hard + +"require-directory@npm:^2.1.1": + version: 2.1.1 + resolution: "require-directory@npm:2.1.1" + checksum: 10/a72468e2589270d91f06c7d36ec97a88db53ae5d6fe3787fadc943f0b0276b10347f89b363b2a82285f650bdcc135ad4a257c61bdd4d00d6df1fa24875b0ddaf languageName: node linkType: hard @@ -4804,10 +5877,17 @@ __metadata: languageName: node linkType: hard +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10/1f914879f97e7ee931ad05fe3afa629bd55270fc6cf1c1e589b6a99fab96d15daad0fa1a52a00c729ec0078045fe3e399bd4fd0c93bcc906957bdc17f89cb8e6 + languageName: node + linkType: hard + "reusify@npm:^1.0.4": - version: 1.0.4 - resolution: "reusify@npm:1.0.4" - checksum: 10/14222c9e1d3f9ae01480c50d96057228a8524706db79cdeb5a2ce5bb7070dd9f409a6f84a02cbef8cdc80d39aef86f2dd03d155188a1300c599b05437dcd2ffb + version: 1.1.0 + resolution: "reusify@npm:1.1.0" + checksum: 10/af47851b547e8a8dc89af144fceee17b80d5beaf5e6f57ed086432d79943434ff67ca526e92275be6f54b6189f6920a24eace75c2657eed32d02c400312b21ec languageName: node linkType: hard @@ -4831,6 +5911,15 @@ __metadata: languageName: node linkType: hard +"rxjs@npm:^7.8.1": + version: 7.8.2 + resolution: "rxjs@npm:7.8.2" + dependencies: + tslib: "npm:^2.1.0" + checksum: 10/03dff09191356b2b87d94fbc1e97c4e9eb3c09d4452399dddd451b09c2f1ba8d56925a40af114282d7bc0c6fe7514a2236ca09f903cf70e4bbf156650dddb49d + languageName: node + linkType: hard + "safe-array-concat@npm:^1.1.3": version: 1.1.3 resolution: "safe-array-concat@npm:1.1.3" @@ -4865,12 +5954,17 @@ __metadata: languageName: node linkType: hard -"scheduler@npm:^0.23.2": - version: 0.23.2 - resolution: "scheduler@npm:0.23.2" - dependencies: - loose-envify: "npm:^1.1.0" - checksum: 10/e8d68b89d18d5b028223edf090092846868a765a591944760942b77ea1f69b17235f7e956696efbb62c8130ab90af7e0949bfb8eba7896335507317236966bc9 +"safer-buffer@npm:>= 2.1.2 < 3.0.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10/7eaf7a0cf37cc27b42fb3ef6a9b1df6e93a1c6d98c6c6702b02fe262d5fcbd89db63320793b99b21cb5348097d0a53de81bd5f4e8b86e20cc9412e3f1cfb4e83 + languageName: node + linkType: hard + +"scheduler@npm:^0.26.0": + version: 0.26.0 + resolution: "scheduler@npm:0.26.0" + checksum: 10/1ecf2e5d7de1a7a132796834afe14a2d589ba7e437615bd8c06f3e0786a3ac3434655e67aac8755d9b14e05754c177e49c064261de2673aaa3c926bc98caa002 languageName: node linkType: hard @@ -4883,12 +5977,21 @@ __metadata: languageName: node linkType: hard -"semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.6.3": - version: 7.6.3 - resolution: "semver@npm:7.6.3" +"semver@npm:^7.3.5, semver@npm:^7.6.0, semver@npm:^7.6.2, semver@npm:^7.7.1, semver@npm:^7.7.2": + version: 7.7.2 + resolution: "semver@npm:7.7.2" bin: semver: bin/semver.js - checksum: 10/36b1fbe1a2b6f873559cd57b238f1094a053dbfd997ceeb8757d79d1d2089c56d1321b9f1069ce263dc64cfa922fa1d2ad566b39426fe1ac6c723c1487589e10 + checksum: 10/7a24cffcaa13f53c09ce55e05efe25cd41328730b2308678624f8b9f5fc3093fc4d189f47950f0b811ff8f3c3039c24a2c36717ba7961615c682045bf03e1dda + languageName: node + linkType: hard + +"serialize-error@npm:^12.0.0": + version: 12.0.0 + resolution: "serialize-error@npm:12.0.0" + dependencies: + type-fest: "npm:^4.31.0" + checksum: 10/733ddb9a2bd86515d18ef43f6bcb1f55a9d9b900944420e5606725668e64b752e5da971071d8fe1562961a926796257d2edb9fad828ec90a35cc6c32a75449bb languageName: node linkType: hard @@ -4929,6 +6032,81 @@ __metadata: languageName: node linkType: hard +"sharp@npm:^0.34.1": + version: 0.34.2 + resolution: "sharp@npm:0.34.2" + dependencies: + "@img/sharp-darwin-arm64": "npm:0.34.2" + "@img/sharp-darwin-x64": "npm:0.34.2" + "@img/sharp-libvips-darwin-arm64": "npm:1.1.0" + "@img/sharp-libvips-darwin-x64": "npm:1.1.0" + "@img/sharp-libvips-linux-arm": "npm:1.1.0" + "@img/sharp-libvips-linux-arm64": "npm:1.1.0" + "@img/sharp-libvips-linux-ppc64": "npm:1.1.0" + "@img/sharp-libvips-linux-s390x": "npm:1.1.0" + "@img/sharp-libvips-linux-x64": "npm:1.1.0" + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.1.0" + "@img/sharp-libvips-linuxmusl-x64": "npm:1.1.0" + "@img/sharp-linux-arm": "npm:0.34.2" + "@img/sharp-linux-arm64": "npm:0.34.2" + "@img/sharp-linux-s390x": "npm:0.34.2" + "@img/sharp-linux-x64": "npm:0.34.2" + "@img/sharp-linuxmusl-arm64": "npm:0.34.2" + "@img/sharp-linuxmusl-x64": "npm:0.34.2" + "@img/sharp-wasm32": "npm:0.34.2" + "@img/sharp-win32-arm64": "npm:0.34.2" + "@img/sharp-win32-ia32": "npm:0.34.2" + "@img/sharp-win32-x64": "npm:0.34.2" + color: "npm:^4.2.3" + detect-libc: "npm:^2.0.4" + semver: "npm:^7.7.2" + dependenciesMeta: + "@img/sharp-darwin-arm64": + optional: true + "@img/sharp-darwin-x64": + optional: true + "@img/sharp-libvips-darwin-arm64": + optional: true + "@img/sharp-libvips-darwin-x64": + optional: true + "@img/sharp-libvips-linux-arm": + optional: true + "@img/sharp-libvips-linux-arm64": + optional: true + "@img/sharp-libvips-linux-ppc64": + optional: true + "@img/sharp-libvips-linux-s390x": + optional: true + "@img/sharp-libvips-linux-x64": + optional: true + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + "@img/sharp-libvips-linuxmusl-x64": + optional: true + "@img/sharp-linux-arm": + optional: true + "@img/sharp-linux-arm64": + optional: true + "@img/sharp-linux-s390x": + optional: true + "@img/sharp-linux-x64": + optional: true + "@img/sharp-linuxmusl-arm64": + optional: true + "@img/sharp-linuxmusl-x64": + optional: true + "@img/sharp-wasm32": + optional: true + "@img/sharp-win32-arm64": + optional: true + "@img/sharp-win32-ia32": + optional: true + "@img/sharp-win32-x64": + optional: true + checksum: 10/8c7a6f20d58849a6e33bc69c4525f471d57eb3dea0072331b55ab12bae4b8bd8b99b65264aeaec38e54d52d692db13e3261f6e7bc29430b39b507c409838cbb0 + languageName: node + linkType: hard + "shebang-command@npm:^2.0.0": version: 2.0.0 resolution: "shebang-command@npm:2.0.0" @@ -4945,19 +6123,26 @@ __metadata: languageName: node linkType: hard +"shell-quote@npm:^1.8.1": + version: 1.8.3 + resolution: "shell-quote@npm:1.8.3" + checksum: 10/5473e354637c2bd698911224129c9a8961697486cff1fb221f234d71c153fc377674029b0223d1d3c953a68d451d79366abfe53d1a0b46ee1f28eb9ade928f4c + languageName: node + linkType: hard + "shiki@npm:^1.26.1": - version: 1.26.1 - resolution: "shiki@npm:1.26.1" + version: 1.29.2 + resolution: "shiki@npm:1.29.2" dependencies: - "@shikijs/core": "npm:1.26.1" - "@shikijs/engine-javascript": "npm:1.26.1" - "@shikijs/engine-oniguruma": "npm:1.26.1" - "@shikijs/langs": "npm:1.26.1" - "@shikijs/themes": "npm:1.26.1" - "@shikijs/types": "npm:1.26.1" + "@shikijs/core": "npm:1.29.2" + "@shikijs/engine-javascript": "npm:1.29.2" + "@shikijs/engine-oniguruma": "npm:1.29.2" + "@shikijs/langs": "npm:1.29.2" + "@shikijs/themes": "npm:1.29.2" + "@shikijs/types": "npm:1.29.2" "@shikijs/vscode-textmate": "npm:^10.0.1" "@types/hast": "npm:^3.0.4" - checksum: 10/10b54241b2c58b0af228dbd00ebf2f7f820ec3527933c7fcbe7c1b634893fe003703f660cbf3ab4d0bdf61d2062590d3c7af5be57cd3192ebb4e5f2900d32f58 + checksum: 10/93de1ebc768ff497ba36720f3b385bff65a853248fdfc0afcb2aea81a43560b1bdc7db9e8417df11a87e106b0de0943989c6301daf62a43d09bd9ac7bc776bf3 languageName: node linkType: hard @@ -5016,6 +6201,43 @@ __metadata: languageName: node linkType: hard +"simple-swizzle@npm:^0.2.2": + version: 0.2.2 + resolution: "simple-swizzle@npm:0.2.2" + dependencies: + is-arrayish: "npm:^0.3.1" + checksum: 10/c6dffff17aaa383dae7e5c056fbf10cf9855a9f79949f20ee225c04f06ddde56323600e0f3d6797e82d08d006e93761122527438ee9531620031c08c9e0d73cc + languageName: node + linkType: hard + +"smart-buffer@npm:^4.2.0": + version: 4.2.0 + resolution: "smart-buffer@npm:4.2.0" + checksum: 10/927484aa0b1640fd9473cee3e0a0bcad6fce93fd7bbc18bac9ad0c33686f5d2e2c422fba24b5899c184524af01e11dd2bd051c2bf2b07e47aff8ca72cbfc60d2 + languageName: node + linkType: hard + +"socks-proxy-agent@npm:^8.0.3": + version: 8.0.5 + resolution: "socks-proxy-agent@npm:8.0.5" + dependencies: + agent-base: "npm:^7.1.2" + debug: "npm:^4.3.4" + socks: "npm:^2.8.3" + checksum: 10/ee99e1dacab0985b52cbe5a75640be6e604135e9489ebdc3048635d186012fbaecc20fbbe04b177dee434c319ba20f09b3e7dfefb7d932466c0d707744eac05c + languageName: node + linkType: hard + +"socks@npm:^2.8.3": + version: 2.8.5 + resolution: "socks@npm:2.8.5" + dependencies: + ip-address: "npm:^9.0.5" + smart-buffer: "npm:^4.2.0" + checksum: 10/0109090ec2bcb8d12d3875a987e85539ed08697500ad971a603c3057e4c266b4bf6a603e07af6d19218c422dd9b72d923aaa6c1f20abae275510bba458e4ccc9 + languageName: node + linkType: hard + "source-map-js@npm:^1.0.2": version: 1.2.1 resolution: "source-map-js@npm:1.2.1" @@ -5044,18 +6266,51 @@ __metadata: languageName: node linkType: hard -"stable-hash@npm:^0.0.4": - version: 0.0.4 - resolution: "stable-hash@npm:0.0.4" - checksum: 10/21c039d21c1cb739cf8342561753a5e007cb95ea682ccd452e76310bbb9c6987a89de8eda023e320b019f3e4691aabda75079cdbb7dadf7ab9013e931f2f23cd +"spawn-command@npm:0.0.2": + version: 0.0.2 + resolution: "spawn-command@npm:0.0.2" + checksum: 10/f13e8c3c63abd4a0b52fb567eba5f7940d480c5ed3ec61781d38a1850f179b1196c39e6efa2bbd301f82c1bf1cd7807abc8fbd8fc8e44bcaa3975a124c0d1657 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 10/e7587128c423f7e43cc625fe2f87e6affdf5ca51c1cc468e910d8aaca46bb44a7fbcfa552f787b1d3987f7043aeb4527d1b99559e6621e01b42b3f45e5a24cbb + languageName: node + linkType: hard + +"ssri@npm:^12.0.0": + version: 12.0.0 + resolution: "ssri@npm:12.0.0" + dependencies: + minipass: "npm:^7.0.3" + checksum: 10/7024c1a6e39b3f18aa8f1c8290e884fe91b0f9ca5a6c6d410544daad54de0ba664db879afe16412e187c6c292fd60b937f047ee44292e5c2af2dcc6d8e1a9b48 + languageName: node + linkType: hard + +"stable-hash@npm:^0.0.5": + version: 0.0.5 + resolution: "stable-hash@npm:0.0.5" + checksum: 10/9222ea2c558e37c4a576cb4e406966b9e6aa05b93f5c4f09ef4aaabe3577439b9b8fbff407b16840b63e2ae83de74290c7b1c2da7360d571e480e46a4aec0a56 + languageName: node + linkType: hard + +"stop-iteration-iterator@npm:^1.1.0": + version: 1.1.0 + resolution: "stop-iteration-iterator@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + internal-slot: "npm:^1.1.0" + checksum: 10/ff36c4db171ee76c936ccfe9541946b77017f12703d4c446652017356816862d3aa029a64e7d4c4ceb484e00ed4a81789333896390d808458638f3a216aa1f41 languageName: node linkType: hard "storybook@npm:^8.6.8": - version: 8.6.12 - resolution: "storybook@npm:8.6.12" + version: 8.6.14 + resolution: "storybook@npm:8.6.14" dependencies: - "@storybook/core": "npm:8.6.12" + "@storybook/core": "npm:8.6.14" peerDependencies: prettier: ^2 || ^3 peerDependenciesMeta: @@ -5065,7 +6320,7 @@ __metadata: getstorybook: ./bin/index.cjs sb: ./bin/index.cjs storybook: ./bin/index.cjs - checksum: 10/babd1d086eb02ba25ee659e02e619f7797a6b91028ad74d2da0ab77e72021cd5c2ac4f239668f15156aabf00bd97066a774370dceadf178b1e649bf971160a26 + checksum: 10/104932fe29ebf49bef24c90285741cec964d1c36b3f0b38da1dace31ac664be457f2a510e41ba69fe8aa0d90c20e3446fec27d1ced41e5eefb3a9ca713d99e79 languageName: node linkType: hard @@ -5076,7 +6331,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -5227,7 +6482,16 @@ __metadata: languageName: node linkType: hard -"style-to-object@npm:^1.0.0": +"style-to-js@npm:1.1.16, style-to-js@npm:^1.0.0": + version: 1.1.16 + resolution: "style-to-js@npm:1.1.16" + dependencies: + style-to-object: "npm:1.0.8" + checksum: 10/a876cc49a29ac90c7723b4d6f002ac6c1ac5ccc6b5bc963d9c607cfc74b15927b704c9324df6f824f576c65689fe4b4ff79caabcd44a13d8a02641f721f1b316 + languageName: node + linkType: hard + +"style-to-object@npm:1.0.8": version: 1.0.8 resolution: "style-to-object@npm:1.0.8" dependencies: @@ -5236,19 +6500,19 @@ __metadata: languageName: node linkType: hard -"styled-jsx@npm:5.1.1": - version: 5.1.1 - resolution: "styled-jsx@npm:5.1.1" +"styled-jsx@npm:5.1.6": + version: 5.1.6 + resolution: "styled-jsx@npm:5.1.6" dependencies: client-only: "npm:0.0.1" peerDependencies: - react: ">= 16.8.0 || 17.x.x || ^18.0.0-0" + react: ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" peerDependenciesMeta: "@babel/core": optional: true babel-plugin-macros: optional: true - checksum: 10/4f6a5d0010770fdeea1183d919d528fd46c484e23c0535ef3e1dd49488116f639c594f3bd4440e3bc8a8686c9f8d53c5761599870ff039ede11a5c3bfe08a4be + checksum: 10/ba01200e8227fe1441a719c2e7da96c8aa7ef61d14211d1500e1abce12efa118479bcb6e7e12beecb9e1db76432caad2f4e01bbc0c9be21c134b088a4ca5ffe0 languageName: node linkType: hard @@ -5261,6 +6525,15 @@ __metadata: languageName: node linkType: hard +"supports-color@npm:^8.1.1": + version: 8.1.1 + resolution: "supports-color@npm:8.1.1" + dependencies: + has-flag: "npm:^4.0.0" + checksum: 10/157b534df88e39c5518c5e78c35580c1eca848d7dbaf31bbe06cdfc048e22c7ff1a9d046ae17b25691128f631a51d9ec373c1b740c12ae4f0de6e292037e4282 + languageName: node + linkType: hard + "supports-preserve-symlinks-flag@npm:^1.0.0": version: 1.0.0 resolution: "supports-preserve-symlinks-flag@npm:1.0.0" @@ -5268,10 +6541,17 @@ __metadata: languageName: node linkType: hard -"tapable@npm:^2.2.0": - version: 2.2.1 - resolution: "tapable@npm:2.2.1" - checksum: 10/1769336dd21481ae6347611ca5fca47add0962fd8e80466515032125eca0084a4f0ede11e65341b9c0018ef4e1cf1ad820adbb0fba7cc99865c6005734000b0a +"tar@npm:^7.4.3": + version: 7.4.3 + resolution: "tar@npm:7.4.3" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.0.1" + mkdirp: "npm:^3.0.1" + yallist: "npm:^5.0.0" + checksum: 10/12a2a4fc6dee23e07cc47f1aeb3a14a1afd3f16397e1350036a8f4cdfee8dcac7ef5978337a4e7b2ac2c27a9a6d46388fc2088ea7c80cb6878c814b1425f8ecf languageName: node linkType: hard @@ -5289,6 +6569,16 @@ __metadata: languageName: node linkType: hard +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.13": + version: 0.2.14 + resolution: "tinyglobby@npm:0.2.14" + dependencies: + fdir: "npm:^6.4.4" + picomatch: "npm:^4.0.2" + checksum: 10/3d306d319718b7cc9d79fb3f29d8655237aa6a1f280860a217f93417039d0614891aee6fc47c5db315f4fcc6ac8d55eb8e23e2de73b2c51a431b42456d9e5764 + languageName: node + linkType: hard + "to-regex-range@npm:^5.0.1": version: 5.0.1 resolution: "to-regex-range@npm:5.0.1" @@ -5298,6 +6588,15 @@ __metadata: languageName: node linkType: hard +"tree-kill@npm:^1.2.2": + version: 1.2.2 + resolution: "tree-kill@npm:1.2.2" + bin: + tree-kill: cli.js + checksum: 10/49117f5f410d19c84b0464d29afb9642c863bc5ba40fcb9a245d474c6d5cc64d1b177a6e6713129eb346b40aebb9d4631d967517f9fbe8251c35b21b13cd96c7 + languageName: node + linkType: hard + "trim-lines@npm:^3.0.0": version: 3.0.1 resolution: "trim-lines@npm:3.0.1" @@ -5312,12 +6611,12 @@ __metadata: languageName: node linkType: hard -"ts-api-utils@npm:^2.0.0": - version: 2.0.0 - resolution: "ts-api-utils@npm:2.0.0" +"ts-api-utils@npm:^2.1.0": + version: 2.1.0 + resolution: "ts-api-utils@npm:2.1.0" peerDependencies: typescript: ">=4.8.4" - checksum: 10/485bdf8bbba98d58712243d958f4fd44742bbe49e559cd77882fb426d866eec6dd05c67ef91935dc4f8a3c776f235859735e1f05be399e4dc9e7ffd580120974 + checksum: 10/02e55b49d9617c6eebf8aadfa08d3ca03ca0cd2f0586ad34117fdfc7aa3cd25d95051843fde9df86665ad907f99baed179e7a117b11021417f379e4d2614eacd languageName: node linkType: hard @@ -5333,7 +6632,7 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.4.0": +"tslib@npm:^2.0.1, tslib@npm:^2.1.0, tslib@npm:^2.4.0, tslib@npm:^2.8.0": version: 2.8.1 resolution: "tslib@npm:2.8.1" checksum: 10/3e2e043d5c2316461cb54e5c7fe02c30ef6dccb3384717ca22ae5c6b5bc95232a6241df19c622d9c73b809bea33b187f6dbc73030963e29950c2141bc32a79f7 @@ -5356,6 +6655,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^4.31.0": + version: 4.41.0 + resolution: "type-fest@npm:4.41.0" + checksum: 10/617ace794ac0893c2986912d28b3065ad1afb484cad59297835a0807dc63286c39e8675d65f7de08fafa339afcb8fe06a36e9a188b9857756ae1e92ee8bda212 + languageName: node + linkType: hard + "typed-array-buffer@npm:^1.0.3": version: 1.0.3 resolution: "typed-array-buffer@npm:1.0.3" @@ -5441,10 +6747,10 @@ __metadata: languageName: node linkType: hard -"undici-types@npm:~6.19.2": - version: 6.19.8 - resolution: "undici-types@npm:6.19.8" - checksum: 10/cf0b48ed4fc99baf56584afa91aaffa5010c268b8842f62e02f752df209e3dea138b372a60a963b3b2576ed932f32329ce7ddb9cb5f27a6c83040d8cd74b7a70 +"undici-types@npm:~6.21.0": + version: 6.21.0 + resolution: "undici-types@npm:6.21.0" + checksum: 10/ec8f41aa4359d50f9b59fa61fe3efce3477cc681908c8f84354d8567bb3701fafdddf36ef6bff307024d3feb42c837cf6f670314ba37fc8145e219560e473d14 languageName: node linkType: hard @@ -5463,6 +6769,24 @@ __metadata: languageName: node linkType: hard +"unique-filename@npm:^4.0.0": + version: 4.0.0 + resolution: "unique-filename@npm:4.0.0" + dependencies: + unique-slug: "npm:^5.0.0" + checksum: 10/6a62094fcac286b9ec39edbd1f8f64ff92383baa430af303dfed1ffda5e47a08a6b316408554abfddd9730c78b6106bef4ca4d02c1231a735ddd56ced77573df + languageName: node + linkType: hard + +"unique-slug@npm:^5.0.0": + version: 5.0.0 + resolution: "unique-slug@npm:5.0.0" + dependencies: + imurmurhash: "npm:^0.1.4" + checksum: 10/beafdf3d6f44990e0a5ce560f8f881b4ee811be70b6ba0db25298c31c8cf525ed963572b48cd03be1c1349084f9e339be4241666d7cf1ebdad20598d3c652b27 + languageName: node + linkType: hard + "unist-util-is@npm:^6.0.0": version: 6.0.0 resolution: "unist-util-is@npm:6.0.0" @@ -5490,6 +6814,17 @@ __metadata: languageName: node linkType: hard +"unist-util-remove@npm:^4.0.0": + version: 4.0.0 + resolution: "unist-util-remove@npm:4.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-is: "npm:^6.0.0" + unist-util-visit-parents: "npm:^6.0.0" + checksum: 10/24a84224720f4c2d2ffce1d570c00b83ef545de80ec32a246698feff880446af6c410fc94deec4b4daafe09851d59f17cd1770e20f66d68092e3cd60c2147fb8 + languageName: node + linkType: hard + "unist-util-stringify-position@npm:^4.0.0": version: 4.0.0 resolution: "unist-util-stringify-position@npm:4.0.0" @@ -5520,6 +6855,67 @@ __metadata: languageName: node linkType: hard +"unrs-resolver@npm:^1.6.2": + version: 1.7.13 + resolution: "unrs-resolver@npm:1.7.13" + dependencies: + "@unrs/resolver-binding-darwin-arm64": "npm:1.7.13" + "@unrs/resolver-binding-darwin-x64": "npm:1.7.13" + "@unrs/resolver-binding-freebsd-x64": "npm:1.7.13" + "@unrs/resolver-binding-linux-arm-gnueabihf": "npm:1.7.13" + "@unrs/resolver-binding-linux-arm-musleabihf": "npm:1.7.13" + "@unrs/resolver-binding-linux-arm64-gnu": "npm:1.7.13" + "@unrs/resolver-binding-linux-arm64-musl": "npm:1.7.13" + "@unrs/resolver-binding-linux-ppc64-gnu": "npm:1.7.13" + "@unrs/resolver-binding-linux-riscv64-gnu": "npm:1.7.13" + "@unrs/resolver-binding-linux-riscv64-musl": "npm:1.7.13" + "@unrs/resolver-binding-linux-s390x-gnu": "npm:1.7.13" + "@unrs/resolver-binding-linux-x64-gnu": "npm:1.7.13" + "@unrs/resolver-binding-linux-x64-musl": "npm:1.7.13" + "@unrs/resolver-binding-wasm32-wasi": "npm:1.7.13" + "@unrs/resolver-binding-win32-arm64-msvc": "npm:1.7.13" + "@unrs/resolver-binding-win32-ia32-msvc": "npm:1.7.13" + "@unrs/resolver-binding-win32-x64-msvc": "npm:1.7.13" + napi-postinstall: "npm:^0.2.2" + dependenciesMeta: + "@unrs/resolver-binding-darwin-arm64": + optional: true + "@unrs/resolver-binding-darwin-x64": + optional: true + "@unrs/resolver-binding-freebsd-x64": + optional: true + "@unrs/resolver-binding-linux-arm-gnueabihf": + optional: true + "@unrs/resolver-binding-linux-arm-musleabihf": + optional: true + "@unrs/resolver-binding-linux-arm64-gnu": + optional: true + "@unrs/resolver-binding-linux-arm64-musl": + optional: true + "@unrs/resolver-binding-linux-ppc64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-gnu": + optional: true + "@unrs/resolver-binding-linux-riscv64-musl": + optional: true + "@unrs/resolver-binding-linux-s390x-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-gnu": + optional: true + "@unrs/resolver-binding-linux-x64-musl": + optional: true + "@unrs/resolver-binding-wasm32-wasi": + optional: true + "@unrs/resolver-binding-win32-arm64-msvc": + optional: true + "@unrs/resolver-binding-win32-ia32-msvc": + optional: true + "@unrs/resolver-binding-win32-x64-msvc": + optional: true + checksum: 10/362aa31e5cd635cf5955a7eb3fe58230a1a32bd5daba4c71e7620e0a0fcd35fffb926655e32d4834a82d48b676cf8a2208cf1de30e30b4bc85c2dc67fa60acb8 + languageName: node + linkType: hard + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -5542,6 +6938,16 @@ __metadata: languageName: node linkType: hard +"vfile-matter@npm:^5.0.1": + version: 5.0.1 + resolution: "vfile-matter@npm:5.0.1" + dependencies: + vfile: "npm:^6.0.0" + yaml: "npm:^2.0.0" + checksum: 10/5eddf848617050df7b539b68c60f4850d4f87e848accb44eb541719cece48a170897fae759023d0f3a87bcfc65fc2183a9875f11c7b3dc9ceaab7b4d739f74d6 + languageName: node + linkType: hard + "vfile-message@npm:^4.0.0": version: 4.0.2 resolution: "vfile-message@npm:4.0.2" @@ -5552,7 +6958,7 @@ __metadata: languageName: node linkType: hard -"vfile@npm:^6.0.0": +"vfile@npm:^6.0.0, vfile@npm:^6.0.3": version: 6.0.3 resolution: "vfile@npm:6.0.3" dependencies: @@ -5615,7 +7021,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.18, which-typed-array@npm:^1.1.2": +"which-typed-array@npm:^1.1.16, which-typed-array@npm:^1.1.19, which-typed-array@npm:^1.1.2": version: 1.1.19 resolution: "which-typed-array@npm:1.1.19" dependencies: @@ -5641,6 +7047,17 @@ __metadata: languageName: node linkType: hard +"which@npm:^5.0.0": + version: 5.0.0 + resolution: "which@npm:5.0.0" + dependencies: + isexe: "npm:^3.1.1" + bin: + node-which: bin/which.js + checksum: 10/6ec99e89ba32c7e748b8a3144e64bfc74aa63e2b2eacbb61a0060ad0b961eb1a632b08fb1de067ed59b002cec3e21de18299216ebf2325ef0f78e0f121e14e90 + languageName: node + linkType: hard + "word-wrap@npm:^1.2.5": version: 1.2.5 resolution: "word-wrap@npm:1.2.5" @@ -5648,7 +7065,7 @@ __metadata: languageName: node linkType: hard -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0, wrap-ansi@npm:^7.0.0": version: 7.0.0 resolution: "wrap-ansi@npm:7.0.0" dependencies: @@ -5678,8 +7095,8 @@ __metadata: linkType: hard "ws@npm:^8.2.3": - version: 8.18.1 - resolution: "ws@npm:8.18.1" + version: 8.18.2 + resolution: "ws@npm:8.18.2" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -5688,7 +7105,59 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10/3f38e9594f2af5b6324138e86b74df7d77bbb8e310bf8188679dd80bac0d1f47e51536a1923ac3365f31f3d8b25ea0b03e4ade466aa8292a86cd5defca64b19b + checksum: 10/018e04ec95561d88248d53a2eaf094b4ae131e9b062f2679e6e8a62f04649bc543448f1e038125225ac6bbb25f54c1e65d7a2cc9dbc1e28b43e5e6b7162ad88e + languageName: node + linkType: hard + +"y18n@npm:^5.0.5": + version: 5.0.8 + resolution: "y18n@npm:5.0.8" + checksum: 10/5f1b5f95e3775de4514edbb142398a2c37849ccfaf04a015be5d75521e9629d3be29bd4432d23c57f37e5b61ade592fb0197022e9993f81a06a5afbdcda9346d + languageName: node + linkType: hard + +"yallist@npm:^4.0.0": + version: 4.0.0 + resolution: "yallist@npm:4.0.0" + checksum: 10/4cb02b42b8a93b5cf50caf5d8e9beb409400a8a4d85e83bb0685c1457e9ac0b7a00819e9f5991ac25ffabb56a78e2f017c1acc010b3a1babfe6de690ba531abd + languageName: node + linkType: hard + +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10/1884d272d485845ad04759a255c71775db0fac56308764b4c77ea56a20d56679fad340213054c8c9c9c26fcfd4c4b2a90df993b7e0aaf3cdb73c618d1d1a802a + languageName: node + linkType: hard + +"yaml@npm:^2.0.0": + version: 2.8.0 + resolution: "yaml@npm:2.8.0" + bin: + yaml: bin.mjs + checksum: 10/7d4bd9c10d0e467601f496193f2ac254140f8e36f96f5ff7f852b9ce37974168eb7354f4c36dc8837dde527a2043d004b6aff48818ec24a69ab2dd3c6b6c381c + languageName: node + linkType: hard + +"yargs-parser@npm:^21.1.1": + version: 21.1.1 + resolution: "yargs-parser@npm:21.1.1" + checksum: 10/9dc2c217ea3bf8d858041252d43e074f7166b53f3d010a8c711275e09cd3d62a002969a39858b92bbda2a6a63a585c7127014534a560b9c69ed2d923d113406e + languageName: node + linkType: hard + +"yargs@npm:^17.7.2": + version: 17.7.2 + resolution: "yargs@npm:17.7.2" + dependencies: + cliui: "npm:^8.0.1" + escalade: "npm:^3.1.1" + get-caller-file: "npm:^2.0.5" + require-directory: "npm:^2.1.1" + string-width: "npm:^4.2.3" + y18n: "npm:^5.0.5" + yargs-parser: "npm:^21.1.1" + checksum: 10/abb3e37678d6e38ea85485ed86ebe0d1e3464c640d7d9069805ea0da12f69d5a32df8e5625e370f9c96dd1c2dc088ab2d0a4dd32af18222ef3c4224a19471576 languageName: node linkType: hard diff --git a/contrib/catalog/read-write-split/README.md b/contrib/catalog/read-write-split/README.md new file mode 100644 index 0000000000..4a99ebe076 --- /dev/null +++ b/contrib/catalog/read-write-split/README.md @@ -0,0 +1,85 @@ +# Catalog Read-Write Split + +This article gives an overview of how you might split your catalog deployment into two - one which handles only reads (the read part of the API), and another that handles everything else (the write part of the API, and processing and ingestion etc). + +This is useful for several reasons: + +- The performance characteristics and scaling needs of those two concerns typically differ significantly +- Moving the bursty processing and ingestion load on a separate deployment can make the important read part of the API have more deterministic response times +- It opens up for easier cross region deployment of read nodes, while having write nodes in a single "home" region +- It also opens up for primary/secondary split of the underlying database, with streaming replication + +## Overview + +This is a rough overview of what we will go through: + +- Ensure that all frontend code uses `catalogApiRef`, and all backend code uses `catalogServiceRef`, for talking to the catalog +- Add a separate discovery name for the write deployment +- Register both frontend and backend implementations of the catalog client that know to send traffic to the right discovery name as needed +- Set up the backend itself with dedicated read and write configuration +- Split the deployment into two +- Follow up with a database split, if desired + +## 1. Prerequisite: Establish usage of catalog client refs + +First, ensure that all of your code uses _injected_ catalog clients for its catalog communications needs instead of making their own with `new`. For frontend code that means leveraging `catalogApiRef`, and for backend it means leveraging `catalogServiceRef`. This is what enables the sort of wholesale injection of custom behaviors that we are about to do, and is a strongly recommended best practice either way. + +- ✅ Search through your projects and ensure that there are no `new CatalogClient` calls. If you find any, consider rewriting that code to instead having the client injected through leveraging the corresponding ref. + +- ✅ Search through your projects and ensure that you do _not_ import the `catalogServiceRef` that specifically is in the `@backstage/plugin-catalog-node/alpha` export. That one has been deprecated for a long time and will not be targeted by this guide. If you find any, consider rewriting that code to instead inject the client from `@backstage/plugin-catalog-node` (note the lack of `/alpha`). + +> [!TIP] +> If you find usages of `new CatalogClient` in tests, you can normally leave those as-is. You can however consider to later try out the `catalogApiMock` from `@backstage/plugin-catalog-react/testUtils` for frontend tests, and `catalogServiceMock` from `@backstage/plugin-catalog-node/testUtils` for backend tests. These allow you to inject a client that behaves like a complete fake catalog backend with entities in it, without complex mocking. + +## 2. Decide your deployment split structure + +We will be defining a fake plugin ID called `catalog-write`. In addition to your current single catalog deployment you will add a second one that receives traffic for `catalog-write`. You need to decide upon what your ingress to those two deployments will look like. This is highly company dependent, so we cannot give general guidance. + +This guide will however NOT split the code base into two. It will instead change your catalog backend code in such a way that it can support either deployment. This is all very flexible and you can tweak it as you see fit, but that's what worked well for us. + +This guide will assume that when all is said and done, requests for the `catalog` plugin ID resolve to the URL `https://catalog-read.example.net/api/catalog`, and requests for the `catalog-write` plugin ID resolve to the URL `https://catalog-write.example.net/api/catalog`. This is just for illustration and you shall change these to their actual correct values at your company. + +- ✅ Copy the contents of [the `app-config.yaml` file](./workspace/app-config.yaml) to your own. We will assume that these exact settings are applied both to your frontend and your catalog (read AND write) deployment. For now, if you are applying this guide step by step rather than all at once, you can set the URLs in there to point to your good old pre-split deployment and only update them again after the split. + +> [!TIP] +> As a future refactor, you could instead break out this behavior into a custom injected discovery implementation in a library that all your projects can import. That takes a few more steps and is left as a separate exercise. If you already have such a library in your internal NPM, feel free to put it there to begin with and import from there. + +## 3. Get split-aware catalog clients in place + +Now let's put clients in place whose methods send traffic to either `catalog` or `catalog-write` as needed. + +- ✅ Copy [the `catalogApi.ts` file](./workspace/packages/app/src/catalogApi.ts) into your `packages/app/src` directory of the project where you develop your Backstage frontend. Then reference that file's API factory in your `packages/app/src/apis.ts` file, [as illustrated here](./workspace/packages/app/src/apis.ts). + +- ✅ Copy [the `catalogService.ts` file](./workspace/packages/backend/src/catalogService.ts) into your `packages/backend/src` directory of the project where you develop your Software Catalog backend. We will reference the file itself in the step below. + +After step 4 below is complete, these will be automatically picked up and used by all callers. + +> [!TIP] +> As a future refactor, you could instead break out these clients into a node and a react library that all your projects can import. That takes a few more steps and is left as a separate exercise. If you already have such libraries in your internal NPM, feel free to put them there to begin with and import from there. + +## 4. Split the catalog backend + +We'll now perform the actual split of the catalog backend. You will make separate config files that apply to each, and adapt the backend code to handle both cases seamlessly. + +- ✅ Duplicate your deployment. It's highly company dependent how this is done. Some may for example duplicate some declarative `Deployment` and `Service` k8s manifests etc, but it depends. + +- ✅ Copy [the `app-config.catalog-read.yaml`] and [the `app-config.catalog-write.yaml`] files into your project root. You must set up your read and write deployments to load their respective files with the `--config` flag, _in addition to_ the `app-config.yaml` file and possibly `app-config.production.yaml` that they already loaded. + +- ✅ Copy [the `config.d.ts`](./workspace/config.d.ts) file to your catalog backend directory at `packages/backend`. You should refer to it in the `package.json`'s `"files"` and `"configSchema"` fields [as per usual](https://backstage.io/docs/conf/defining). + +- ✅ Update your `packages/backend/src/index.ts` file to match [the proposed structure here](./workspace/packages/backend/src/index.ts). Note how it applies the custom catalog service we copied in the previous step, and has a separate section for write-only concerns. + +## 5. Region and database split + +After the above is deployed and working, you are well set up for some next step. + +- Scaling your readers across multiple regions and add geo-aware routing to them, while keeping writers in a "home" region +- Splitting the database server into a primary that the write nodes connect to, and regional secondaries with streaming replication from the primary + +But all of this is left as an exercise for the reader. + +## 6. Help make this smoother + +Congratulations on successfully performing your split! + +We would love [some help](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md) with making this process easier for others. For example, if read nodes could automatically transparently proxy traffic to write nodes as needed, we would need far less fiddling with clients at a relatively small extra cost. diff --git a/contrib/catalog/read-write-split/workspace/app-config.catalog-read.yaml b/contrib/catalog/read-write-split/workspace/app-config.catalog-read.yaml new file mode 100644 index 0000000000..33d7f34714 --- /dev/null +++ b/contrib/catalog/read-write-split/workspace/app-config.catalog-read.yaml @@ -0,0 +1,12 @@ +# This file should be given to the catalog read nodes. + +backend: + database: + # disable running database migrations for every plugin/module + skipMigrations: true + +catalog: + role: read + + # disable processing engine + processingInterval: false diff --git a/contrib/catalog/read-write-split/workspace/app-config.catalog-write.yaml b/contrib/catalog/read-write-split/workspace/app-config.catalog-write.yaml new file mode 100644 index 0000000000..ea1659e140 --- /dev/null +++ b/contrib/catalog/read-write-split/workspace/app-config.catalog-write.yaml @@ -0,0 +1,4 @@ +# This file should be given to the catalog write nodes. + +catalog: + role: write diff --git a/contrib/catalog/read-write-split/workspace/app-config.yaml b/contrib/catalog/read-write-split/workspace/app-config.yaml new file mode 100644 index 0000000000..e4b09e4cb9 --- /dev/null +++ b/contrib/catalog/read-write-split/workspace/app-config.yaml @@ -0,0 +1,19 @@ +# This is in your regular app-config. + +# This introduces a made-up "catalog-write" plugin ID that the frontend catalog +# API implementation can use to resolve where to find the write nodes. +discovery: + endpoints: + # + # TODO: Replace with actual URLs + # + # NOTE: Each target can also be an object with "internal" and "external" + # keys with different URLs, if they should be different when called by + # backends and the frontend, respectively. + # + - target: https://catalog-read.example.net/api/catalog + plugins: + - catalog + - target: https://catalog-write.example.net/api/catalog + plugins: + - catalog-write diff --git a/contrib/catalog/read-write-split/workspace/config.d.ts b/contrib/catalog/read-write-split/workspace/config.d.ts new file mode 100644 index 0000000000..29a80c77f8 --- /dev/null +++ b/contrib/catalog/read-write-split/workspace/config.d.ts @@ -0,0 +1,5 @@ +export interface Config { + catalog: { + role: 'read' | 'write'; + }; +} diff --git a/contrib/catalog/read-write-split/workspace/packages/app/src/apis.ts b/contrib/catalog/read-write-split/workspace/packages/app/src/apis.ts new file mode 100644 index 0000000000..12fd2bfd49 --- /dev/null +++ b/contrib/catalog/read-write-split/workspace/packages/app/src/apis.ts @@ -0,0 +1,11 @@ +import { AnyApiFactory } from '@backstage/core-plugin-api'; +import { catalogApiFactory } from './catalogApi'; + +// This file is already present in a typical Backstage app. We are just adding +// the catalog API factory here to ensure that the frontend sends requests to +// the correct set of catalog nodes depending on whether it's a read or a write +// operation. +export const apis: AnyApiFactory[] = [ + // ...other APIs here... + catalogApiFactory, +]; diff --git a/contrib/catalog/read-write-split/workspace/packages/app/src/catalogApi.ts b/contrib/catalog/read-write-split/workspace/packages/app/src/catalogApi.ts new file mode 100644 index 0000000000..0813249f8f --- /dev/null +++ b/contrib/catalog/read-write-split/workspace/packages/app/src/catalogApi.ts @@ -0,0 +1,174 @@ +import { + AddLocationRequest, + AddLocationResponse, + CatalogApi, + CatalogClient, + CatalogRequestOptions, + GetEntitiesByRefsRequest, + GetEntitiesByRefsResponse, + GetEntitiesRequest, + GetEntitiesResponse, + GetEntityAncestorsRequest, + GetEntityAncestorsResponse, + GetEntityFacetsRequest, + GetEntityFacetsResponse, + GetLocationsResponse, + Location, + QueryEntitiesRequest, + QueryEntitiesResponse, + ValidateEntityResponse, +} from '@backstage/catalog-client'; +import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; +import { + createApiFactory, + DiscoveryApi, + discoveryApiRef, + FetchApi, + fetchApiRef, +} from '@backstage/core-plugin-api'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; + +/** + * Implements the catalog client for frontends, by using a custom service + * discovery to achieve read/write segregation. + */ +export class ReadWriteSplitCatalogClient implements CatalogApi { + #write: CatalogApi; + #read: CatalogApi; + + constructor(options: { discoveryApi: DiscoveryApi; fetchApi: FetchApi }) { + this.#read = new CatalogClient({ + fetchApi: options.fetchApi, + discoveryApi: { + // This uses the normal "catalog" plugin ID + getBaseUrl: () => options.discoveryApi.getBaseUrl('catalog'), + }, + }); + this.#write = new CatalogClient({ + fetchApi: options.fetchApi, + discoveryApi: { + // This uses the made-up "catalog-write" plugin ID (see app-config.yaml + // which defines a custom discovery endpoint for this) + getBaseUrl: () => options.discoveryApi.getBaseUrl('catalog-write'), + }, + }); + } + + getEntities( + request?: GetEntitiesRequest, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getEntities(request, options); + } + + getEntitiesByRefs( + request: GetEntitiesByRefsRequest, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getEntitiesByRefs(request, options); + } + + queryEntities( + request?: QueryEntitiesRequest, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.queryEntities(request, options); + } + + getEntityAncestors( + request: GetEntityAncestorsRequest, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getEntityAncestors(request, options); + } + + getEntityByRef( + entityRef: string | CompoundEntityRef, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getEntityByRef(entityRef, options); + } + + removeEntityByUid( + uid: string, + options?: CatalogRequestOptions, + ): Promise { + return this.#write.removeEntityByUid(uid, options); + } + + refreshEntity( + entityRef: string, + options?: CatalogRequestOptions, + ): Promise { + return this.#write.refreshEntity(entityRef, options); + } + + getEntityFacets( + request: GetEntityFacetsRequest, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getEntityFacets(request, options); + } + + getLocations( + request?: {}, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getLocations(request, options); + } + + getLocationById( + id: string, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getLocationById(id, options); + } + + getLocationByRef( + locationRef: string, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getLocationByRef(locationRef, options); + } + + addLocation( + location: AddLocationRequest, + options?: CatalogRequestOptions, + ): Promise { + return this.#write.addLocation(location, options); + } + + removeLocationById( + id: string, + options?: CatalogRequestOptions, + ): Promise { + return this.#write.removeLocationById(id, options); + } + + getLocationByEntity( + entityRef: string | CompoundEntityRef, + options?: CatalogRequestOptions, + ): Promise { + return this.#read.getLocationByEntity(entityRef, options); + } + + validateEntity( + entity: Entity, + locationRef: string, + options?: CatalogRequestOptions, + ): Promise { + return this.#write.validateEntity(entity, locationRef, options); + } +} + +// You should pass this to createApp. +export const catalogApiFactory = createApiFactory({ + api: catalogApiRef, + deps: { discoveryApi: discoveryApiRef, fetchApi: fetchApiRef }, + factory: ({ discoveryApi, fetchApi }) => { + return new ReadWriteSplitCatalogClient({ + discoveryApi, + fetchApi, + }); + }, +}); diff --git a/contrib/catalog/read-write-split/workspace/packages/backend/src/catalogService.ts b/contrib/catalog/read-write-split/workspace/packages/backend/src/catalogService.ts new file mode 100644 index 0000000000..80711bd4b3 --- /dev/null +++ b/contrib/catalog/read-write-split/workspace/packages/backend/src/catalogService.ts @@ -0,0 +1,231 @@ +import { + AuthService, + coreServices, + createServiceFactory, + DiscoveryService, +} from '@backstage/backend-plugin-api'; +import { + AddLocationRequest, + AddLocationResponse, + CatalogApi, + CatalogClient, + CatalogRequestOptions, + GetEntitiesByRefsRequest, + GetEntitiesByRefsResponse, + GetEntitiesRequest, + GetEntitiesResponse, + GetEntityAncestorsRequest, + GetEntityAncestorsResponse, + GetEntityFacetsRequest, + GetEntityFacetsResponse, + GetLocationsResponse, + Location, + QueryEntitiesRequest, + QueryEntitiesResponse, + ValidateEntityResponse, +} from '@backstage/catalog-client'; +import { CompoundEntityRef, Entity } from '@backstage/catalog-model'; +import { + CatalogService, + CatalogServiceRequestOptions, + catalogServiceRef, +} from '@backstage/plugin-catalog-node'; + +/** + * Implements the catalog client for backends, by using a custom service + * discovery to achieve read/write segregation. + */ +export class ReadWriteSplitCatalogService implements CatalogService { + readonly #auth: AuthService; + readonly #catalogRead: CatalogApi; + readonly #catalogWrite: CatalogApi; + + constructor(options: { auth: AuthService; discovery: DiscoveryService }) { + this.#auth = options.auth; + this.#catalogRead = new CatalogClient({ + discoveryApi: { + // This uses the normal "catalog" plugin ID + getBaseUrl: () => options.discovery.getBaseUrl('catalog'), + }, + }); + this.#catalogWrite = new CatalogClient({ + discoveryApi: { + // This uses the made-up "catalog-write" plugin ID (see app-config.yaml + // which defines a custom discovery endpoint for this) + getBaseUrl: () => options.discovery.getBaseUrl('catalog-write'), + }, + }); + } + + async getEntities( + request: GetEntitiesRequest | undefined, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.getEntities( + request, + await this.#getOptions(options), + ); + } + + async getEntitiesByRefs( + request: GetEntitiesByRefsRequest, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.getEntitiesByRefs( + request, + await this.#getOptions(options), + ); + } + + async queryEntities( + request: QueryEntitiesRequest | undefined, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.queryEntities( + request, + await this.#getOptions(options), + ); + } + + async getEntityAncestors( + request: GetEntityAncestorsRequest, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.getEntityAncestors( + request, + await this.#getOptions(options), + ); + } + + async getEntityByRef( + entityRef: string | CompoundEntityRef, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.getEntityByRef( + entityRef, + await this.#getOptions(options), + ); + } + + async removeEntityByUid( + uid: string, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogWrite.removeEntityByUid( + uid, + await this.#getOptions(options), + ); + } + + async refreshEntity( + entityRef: string, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogWrite.refreshEntity( + entityRef, + await this.#getOptions(options), + ); + } + + async getEntityFacets( + request: GetEntityFacetsRequest, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.getEntityFacets( + request, + await this.#getOptions(options), + ); + } + + async getLocations( + options: CatalogRequestOptions, + ): Promise { + return this.#catalogRead.getLocations(options); + } + + async getLocationById( + id: string, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.getLocationById( + id, + await this.#getOptions(options), + ); + } + + async getLocationByRef( + locationRef: string, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.getLocationByRef( + locationRef, + await this.#getOptions(options), + ); + } + + async addLocation( + location: AddLocationRequest, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogWrite.addLocation( + location, + await this.#getOptions(options), + ); + } + + async removeLocationById( + id: string, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogWrite.removeLocationById( + id, + await this.#getOptions(options), + ); + } + + async getLocationByEntity( + entityRef: string | CompoundEntityRef, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogRead.getLocationByEntity( + entityRef, + await this.#getOptions(options), + ); + } + + async validateEntity( + entity: Entity, + locationRef: string, + options: CatalogServiceRequestOptions, + ): Promise { + return this.#catalogWrite.validateEntity( + entity, + locationRef, + await this.#getOptions(options), + ); + } + + async #getOptions( + options: CatalogServiceRequestOptions, + ): Promise { + return this.#auth.getPluginRequestToken({ + onBehalfOf: options.credentials, + targetPluginId: 'catalog', + }); + } +} + +// You should register this in your backend. +export const catalogService = createServiceFactory({ + service: catalogServiceRef, + deps: { + auth: coreServices.auth, + discovery: coreServices.discovery, + }, + async factory({ auth, discovery }) { + return new ReadWriteSplitCatalogService({ + auth, + discovery, + }); + }, +}); diff --git a/contrib/catalog/read-write-split/workspace/packages/backend/src/index.ts b/contrib/catalog/read-write-split/workspace/packages/backend/src/index.ts new file mode 100644 index 0000000000..0d8e9e41d9 --- /dev/null +++ b/contrib/catalog/read-write-split/workspace/packages/backend/src/index.ts @@ -0,0 +1,34 @@ +import { createBackend } from '@backstage/backend-defaults'; +import { + coreServices, + createBackendFeatureLoader, +} from '@backstage/backend-plugin-api'; +import { catalogService } from './catalogService'; + +const backend = createBackend(); + +backend.add(import('@backstage/plugin-catalog-backend')); +backend.add(catalogService); +// Here at the root level, you can add more features that you want to apply to +// BOTH the read and write nodes, as needed. + +backend.add( + createBackendFeatureLoader({ + deps: { config: coreServices.rootConfig }, + async *loader({ config }) { + if (config.getString('catalog.role') !== 'write') { + return; + } + + // Here inside the loader, you can add more features that you want to + // apply to ONLY the write nodes, as needed. This is where providers and + // processors go, for example. The incremental ingestion provider line + // below is just an example. + yield import( + '@backstage/plugin-catalog-backend-module-incremental-ingestion' + ); + }, + }), +); + +backend.start(); diff --git a/docs/architecture-decisions/adr000-template.md b/docs/architecture-decisions/adr000-template.md index f16ae7d39f..267eceab44 100644 --- a/docs/architecture-decisions/adr000-template.md +++ b/docs/architecture-decisions/adr000-template.md @@ -1,7 +1,6 @@ --- id: adrs-adr000 title: 'ADR000: [TITLE]' -# prettier-ignore description: Architecture Decision Record (ADR) for [TITLE] [DESCRIPTION] --- diff --git a/docs/architecture-decisions/adr001-add-adr-log.md b/docs/architecture-decisions/adr001-add-adr-log.md index de4283319a..8ad0fa3748 100644 --- a/docs/architecture-decisions/adr001-add-adr-log.md +++ b/docs/architecture-decisions/adr001-add-adr-log.md @@ -1,7 +1,6 @@ --- id: adrs-adr001 title: 'ADR001: Architecture Decision Record (ADR) log' -# prettier-ignore description: Architecture Decision Record (ADR) logs as a reference point for the team --- diff --git a/docs/architecture-decisions/adr002-default-catalog-file-format.md b/docs/architecture-decisions/adr002-default-catalog-file-format.md index 3b606cf46b..eb84913313 100644 --- a/docs/architecture-decisions/adr002-default-catalog-file-format.md +++ b/docs/architecture-decisions/adr002-default-catalog-file-format.md @@ -1,7 +1,6 @@ --- id: adrs-adr002 title: 'ADR002: Default Software Catalog File Format' -# prettier-ignore description: Architecture Decision Record (ADR) log on Default Software Catalog File Format --- diff --git a/docs/architecture-decisions/adr003-avoid-default-exports.md b/docs/architecture-decisions/adr003-avoid-default-exports.md index 24445f0be1..8ba37914df 100644 --- a/docs/architecture-decisions/adr003-avoid-default-exports.md +++ b/docs/architecture-decisions/adr003-avoid-default-exports.md @@ -1,7 +1,6 @@ --- id: adrs-adr003 title: 'ADR003: Avoid Default Exports and Prefer Named Exports' -# prettier-ignore description: Architecture Decision Record (ADR) log on Avoid Default Exports and Prefer Named Exports --- diff --git a/docs/architecture-decisions/adr004-module-export-structure.md b/docs/architecture-decisions/adr004-module-export-structure.md index 95d0f27811..507859ef01 100644 --- a/docs/architecture-decisions/adr004-module-export-structure.md +++ b/docs/architecture-decisions/adr004-module-export-structure.md @@ -1,7 +1,6 @@ --- id: adrs-adr004 title: 'ADR004: Module Export Structure' -# prettier-ignore description: Architecture Decision Record (ADR) log on Module Export Structure --- diff --git a/docs/architecture-decisions/adr005-catalog-core-entities.md b/docs/architecture-decisions/adr005-catalog-core-entities.md index 1206d9e83d..ca65425645 100644 --- a/docs/architecture-decisions/adr005-catalog-core-entities.md +++ b/docs/architecture-decisions/adr005-catalog-core-entities.md @@ -1,7 +1,6 @@ --- id: adrs-adr005 title: 'ADR005: Catalog Core Entities' -# prettier-ignore description: Architecture Decision Record (ADR) log on Catalog Core Entities --- diff --git a/docs/architecture-decisions/adr006-avoid-react-fc.md b/docs/architecture-decisions/adr006-avoid-react-fc.md index 6a7c431655..0630718763 100644 --- a/docs/architecture-decisions/adr006-avoid-react-fc.md +++ b/docs/architecture-decisions/adr006-avoid-react-fc.md @@ -1,7 +1,6 @@ --- id: adrs-adr006 title: 'ADR006: Avoid React.FC and React.SFC' -# prettier-ignore description: Architecture Decision Record (ADR) log on Avoid React.FC and React.SFC --- diff --git a/docs/architecture-decisions/adr007-use-msw-to-mock-service-requests.md b/docs/architecture-decisions/adr007-use-msw-to-mock-service-requests.md index a61bb78787..535adea8cb 100644 --- a/docs/architecture-decisions/adr007-use-msw-to-mock-service-requests.md +++ b/docs/architecture-decisions/adr007-use-msw-to-mock-service-requests.md @@ -1,7 +1,6 @@ --- id: adrs-adr007 title: 'ADR007: Use MSW to mock http requests' -# prettier-ignore description: Architecture Decision Record (ADR) log on Use MSW to mock http requests --- diff --git a/docs/architecture-decisions/adr008-default-catalog-file-name.md b/docs/architecture-decisions/adr008-default-catalog-file-name.md index fca65c8355..1f00c19b7e 100644 --- a/docs/architecture-decisions/adr008-default-catalog-file-name.md +++ b/docs/architecture-decisions/adr008-default-catalog-file-name.md @@ -1,7 +1,6 @@ --- id: adrs-adr008 title: 'ADR008: Default Catalog File Name' -# prettier-ignore description: Architecture Decision Record (ADR) log on Default Catalog File Name --- diff --git a/docs/architecture-decisions/adr009-entity-references.md b/docs/architecture-decisions/adr009-entity-references.md index 7cac946388..5779503113 100644 --- a/docs/architecture-decisions/adr009-entity-references.md +++ b/docs/architecture-decisions/adr009-entity-references.md @@ -1,7 +1,6 @@ --- id: adrs-adr009 title: 'ADR009: Entity References' -# prettier-ignore description: Architecture Decision Record (ADR) log on Entity References --- diff --git a/docs/architecture-decisions/adr010-luxon-date-library.md b/docs/architecture-decisions/adr010-luxon-date-library.md index a7b287ae0d..262a468fa9 100644 --- a/docs/architecture-decisions/adr010-luxon-date-library.md +++ b/docs/architecture-decisions/adr010-luxon-date-library.md @@ -1,7 +1,6 @@ --- id: adrs-adr010 title: 'ADR010: Use the Luxon Date Library' -# prettier-ignore description: Architecture Decision Record (ADR) for Luxon Date Library --- diff --git a/docs/architecture-decisions/adr011-plugin-package-structure.md b/docs/architecture-decisions/adr011-plugin-package-structure.md index 8e4b5435f9..323483e2d9 100644 --- a/docs/architecture-decisions/adr011-plugin-package-structure.md +++ b/docs/architecture-decisions/adr011-plugin-package-structure.md @@ -1,7 +1,6 @@ --- id: adrs-adr011 title: 'ADR011: Plugin Package Structure' -# prettier-ignore description: Architecture Decision Record (ADR) for Plugin Package Structure --- diff --git a/docs/architecture-decisions/adr012-use-luxon-locale-and-date-presets.md b/docs/architecture-decisions/adr012-use-luxon-locale-and-date-presets.md index 25bb6c1833..423e2c58f6 100644 --- a/docs/architecture-decisions/adr012-use-luxon-locale-and-date-presets.md +++ b/docs/architecture-decisions/adr012-use-luxon-locale-and-date-presets.md @@ -1,7 +1,6 @@ --- id: adrs-adr012 title: 'ADR012: Use Luxon.toLocaleString and date/time presets' -# prettier-ignore description: Architecture Decision Record (ADR) for using Luxon's toLocaleString method and date/time presets for displaying dates and times --- diff --git a/docs/architecture-decisions/adr013-use-node-fetch.md b/docs/architecture-decisions/adr013-use-node-fetch.md index e65cf0a97b..664faed1db 100644 --- a/docs/architecture-decisions/adr013-use-node-fetch.md +++ b/docs/architecture-decisions/adr013-use-node-fetch.md @@ -1,7 +1,6 @@ --- id: adrs-adr013 title: 'ADR013: [superseded] Proper use of HTTP fetching libraries' -# prettier-ignore description: Architecture Decision Record (ADR) for the proper use of fetchApiRef, node-fetch, and cross-fetch for data fetching. --- diff --git a/docs/architecture-decisions/adr014-use-fetch.md b/docs/architecture-decisions/adr014-use-fetch.md index 8454e69e7c..9faa6c9ead 100644 --- a/docs/architecture-decisions/adr014-use-fetch.md +++ b/docs/architecture-decisions/adr014-use-fetch.md @@ -1,7 +1,6 @@ --- id: adrs-adr014 title: 'ADR014: Proper use of HTTP fetching libraries' -# prettier-ignore description: Architecture Decision Record (ADR) for the proper use of fetchApiRef, native fetch, and cross-fetch for data fetching. --- diff --git a/docs/architecture-decisions/index.md b/docs/architecture-decisions/index.md index 8bb854497a..eddbdbe81e 100644 --- a/docs/architecture-decisions/index.md +++ b/docs/architecture-decisions/index.md @@ -2,7 +2,6 @@ id: adrs-overview title: Architecture Decision Records (ADR) sidebar_label: Overview -# prettier-ignore description: Overview of Architecture Decision Records (ADR) --- diff --git a/docs/auth/autologout.md b/docs/auth/autologout.md index b85f6f486d..e2462522f4 100644 --- a/docs/auth/autologout.md +++ b/docs/auth/autologout.md @@ -1,7 +1,6 @@ --- id: autologout title: Auto Logout -# prettier-ignore description: This section describes how to setup the Auto Logout mechanism in Backstage --- @@ -69,7 +68,7 @@ These are the available settings: | Configuration Key | Component Property | Description | Allowed Values | Default Value | | ----------------------------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | --------------------------- | | `auth.autologout.enabled` | `enabled` | Enable/disable the Auto Logout feature. | `true`/`false` | Default is enabled (`true`) | -| `auth.autologout.idleTimeoutMinutes` | `idleTimeoutMinutes` | Sets the idle time (in minutes) after which the user will be logged out. | `>= 0.5` minutes | `60` | +| `auth.autologout.idleTimeoutMinutes` | `idleTimeoutMinutes` | Sets the idle time (in minutes) after which the user will be logged out. | `>= 0.5` minutes | `0.5` | | `auth.autologout.promptBeforeIdleSeconds` | `promptBeforeIdleSeconds` | Determines the time (in seconds) prior to idle state when a prompt will appear. A value of 0 disables the prompt. This must be less than the value of `idleTimeoutMinutes`. | `>= 0` seconds | `10` | | `auth.autologout.useWorkerTimers` | `useWorkerTimers` | Enables or disables the use of Node's worker thread timers instead of main thread timers. This can be beneficial if the browser is terminating timers in inactive tabs, like those used by auto logout. In case of browser incompatibility, try setting this to false. | `true`/`false` | `true` | | `auth.autologout.logoutIfDisconnected` | `logoutIfDisconnected` | Enable/disable auto logout for disconnected users. Disconnected users are those who are logged in but do not have any active Backstage tabs open in their browsers. If enabled, such users will be automatically logged out after `idleTimeoutMinutes`. | `true`/`false` | `true` | diff --git a/docs/auth/google/gcp-iap-auth.md b/docs/auth/google/gcp-iap-auth.md index 6fe8b56d9e..386fab383f 100644 --- a/docs/auth/google/gcp-iap-auth.md +++ b/docs/auth/google/gcp-iap-auth.md @@ -2,7 +2,6 @@ id: gcp-iap-auth title: Google Identity-Aware Proxy Provider sidebar_label: Google IAP -# prettier-ignore description: Adding Google Identity-Aware Proxy as an authentication provider in Backstage --- diff --git a/docs/auth/oauth.md b/docs/auth/oauth.md index fbd87d653b..06b204fdaf 100644 --- a/docs/auth/oauth.md +++ b/docs/auth/oauth.md @@ -1,7 +1,6 @@ --- id: oauth title: OAuth and OpenID Connect -# prettier-ignore description: This section describes how Backstage allows plugins to request OAuth Access Tokens and OpenID Connect ID Tokens on behalf of the user, to be used for auth to various third party APIs --- diff --git a/docs/auth/service-to-service-auth.md b/docs/auth/service-to-service-auth.md index fecb3f5191..d35aed364d 100644 --- a/docs/auth/service-to-service-auth.md +++ b/docs/auth/service-to-service-auth.md @@ -1,7 +1,6 @@ --- id: service-to-service-auth title: Service to Service Auth -# prettier-ignore description: This section describes service to service authentication works, both internally within Backstage plugins and when external callers want to make requests. --- diff --git a/docs/backend-system/architecture/01-index.md b/docs/backend-system/architecture/01-index.md index 968ff2f001..293a46b7ca 100644 --- a/docs/backend-system/architecture/01-index.md +++ b/docs/backend-system/architecture/01-index.md @@ -2,7 +2,6 @@ id: index title: Backend System Architecture sidebar_label: Overview -# prettier-ignore description: The structure and architecture of the new Backend System and its component parts --- diff --git a/docs/backend-system/architecture/02-backends.md b/docs/backend-system/architecture/02-backends.md index 1310453a3f..8f903eb7a8 100644 --- a/docs/backend-system/architecture/02-backends.md +++ b/docs/backend-system/architecture/02-backends.md @@ -2,7 +2,6 @@ id: backends title: Backend Instances sidebar_label: Backend -# prettier-ignore description: Backend instances --- diff --git a/docs/backend-system/architecture/03-services.md b/docs/backend-system/architecture/03-services.md index ad437e471e..cfcd606d92 100644 --- a/docs/backend-system/architecture/03-services.md +++ b/docs/backend-system/architecture/03-services.md @@ -2,7 +2,6 @@ id: services title: Backend Services sidebar_label: Services -# prettier-ignore description: Services for backend plugins --- diff --git a/docs/backend-system/architecture/04-plugins.md b/docs/backend-system/architecture/04-plugins.md index f2a6b856b9..fdb5012569 100644 --- a/docs/backend-system/architecture/04-plugins.md +++ b/docs/backend-system/architecture/04-plugins.md @@ -2,7 +2,6 @@ id: plugins title: Backend Plugins sidebar_label: Plugins -# prettier-ignore description: Backend plugins --- diff --git a/docs/backend-system/architecture/05-extension-points.md b/docs/backend-system/architecture/05-extension-points.md index 12c4ec75f5..2e11d2763f 100644 --- a/docs/backend-system/architecture/05-extension-points.md +++ b/docs/backend-system/architecture/05-extension-points.md @@ -2,7 +2,6 @@ id: extension-points title: Backend Plugin Extension Points sidebar_label: Extension Points -# prettier-ignore description: Extension points of backend plugins --- diff --git a/docs/backend-system/architecture/06-modules.md b/docs/backend-system/architecture/06-modules.md index 010f36109c..e8905808ee 100644 --- a/docs/backend-system/architecture/06-modules.md +++ b/docs/backend-system/architecture/06-modules.md @@ -2,7 +2,6 @@ id: modules title: Plugin Modules sidebar_label: Modules -# prettier-ignore description: Modules for backend plugins --- diff --git a/docs/backend-system/architecture/07-feature-loaders.md b/docs/backend-system/architecture/07-feature-loaders.md index b2cc574bf9..0a2d611b7b 100644 --- a/docs/backend-system/architecture/07-feature-loaders.md +++ b/docs/backend-system/architecture/07-feature-loaders.md @@ -2,7 +2,6 @@ id: feature-loaders title: Backend Feature Loaders sidebar_label: Feature Loaders -# prettier-ignore description: Backend feature loaders --- diff --git a/docs/backend-system/architecture/08-naming-patterns.md b/docs/backend-system/architecture/08-naming-patterns.md index 32ed1d9035..585a9fe87c 100644 --- a/docs/backend-system/architecture/08-naming-patterns.md +++ b/docs/backend-system/architecture/08-naming-patterns.md @@ -2,7 +2,6 @@ id: naming-patterns title: Backend System Naming Patterns sidebar_label: Naming Patterns -# prettier-ignore description: Naming patterns in the backend system --- diff --git a/docs/backend-system/building-backends/01-index.md b/docs/backend-system/building-backends/01-index.md index ec95e57973..0f0a8e01ea 100644 --- a/docs/backend-system/building-backends/01-index.md +++ b/docs/backend-system/building-backends/01-index.md @@ -2,7 +2,6 @@ id: index title: Building Backends sidebar_label: Overview -# prettier-ignore description: Building backends using the new backend system --- diff --git a/docs/backend-system/building-backends/08-migrating.md b/docs/backend-system/building-backends/08-migrating.md index a827171ff7..c07862cc3c 100644 --- a/docs/backend-system/building-backends/08-migrating.md +++ b/docs/backend-system/building-backends/08-migrating.md @@ -2,7 +2,6 @@ id: migrating title: Migrating your Backend to the New Backend System sidebar_label: Migration Guide -# prettier-ignore description: How to migrate existing backends to the new backend system --- diff --git a/docs/backend-system/building-plugins-and-modules/01-index.md b/docs/backend-system/building-plugins-and-modules/01-index.md index db78faaced..53bf4af8ef 100644 --- a/docs/backend-system/building-plugins-and-modules/01-index.md +++ b/docs/backend-system/building-plugins-and-modules/01-index.md @@ -2,7 +2,6 @@ id: index title: Building Backend Plugins and Modules sidebar_label: Overview -# prettier-ignore description: Building backend plugins and modules using the new backend system --- diff --git a/docs/backend-system/building-plugins-and-modules/02-testing.md b/docs/backend-system/building-plugins-and-modules/02-testing.md index f72d2de49b..6000c14a45 100644 --- a/docs/backend-system/building-plugins-and-modules/02-testing.md +++ b/docs/backend-system/building-plugins-and-modules/02-testing.md @@ -2,7 +2,6 @@ id: testing title: Testing Backend Plugins and Modules sidebar_label: Testing -# prettier-ignore description: Learn how to test your backend plugins and modules --- diff --git a/docs/backend-system/building-plugins-and-modules/08-migrating.md b/docs/backend-system/building-plugins-and-modules/08-migrating.md index 5da443328c..f48c5579f6 100644 --- a/docs/backend-system/building-plugins-and-modules/08-migrating.md +++ b/docs/backend-system/building-plugins-and-modules/08-migrating.md @@ -2,7 +2,6 @@ id: migrating title: Migrating your Backend Plugin to the New Backend System sidebar_label: Migration Guide -# prettier-ignore description: How to migrate existing backend plugins to the new backend system --- diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md index 3be12b2e26..50ebea0e4f 100644 --- a/docs/backend-system/core-services/01-index.md +++ b/docs/backend-system/core-services/01-index.md @@ -2,7 +2,6 @@ id: index title: Core Backend Service APIs sidebar_label: Overview -# prettier-ignore description: Core backend service APIs --- diff --git a/docs/backend-system/core-services/actions-registry.md b/docs/backend-system/core-services/actions-registry.md new file mode 100644 index 0000000000..b1e8fe5f3d --- /dev/null +++ b/docs/backend-system/core-services/actions-registry.md @@ -0,0 +1,177 @@ +--- +id: actions-registry +title: Actions Registry (alpha) +sidebar_label: Actions Registry (alpha) +description: Documentation for the Actions Registry Service +--- + +## Overview + +The Actions Registry Service is a core service designed to provide a distributed registry for actions that can be executed within Backstage backend plugins. This service allows plugins to register reusable actions with well-defined schemas and execution logic, promoting consistency and reusability across the Backstage ecosystem. + +## Action Structure + +Each action registered with the service must conform to the `ActionsRegistryActionOptions` type, which includes: + +### Required Properties + +- **`name`:** A unique identifier for the action (string) +- **`title`:** A human-readable title for the action (string) +- **`description`:** A detailed description of what the action does (string) +- **`schema`:** Object containing input and output schema definitions + - **`input`:** Function that returns a Zod schema for validating input + - **`output`:** Function that returns a Zod schema for validating output +- **`action`:** The async function that executes the action logic + +### Optional Properties + +- **`attributes`:** Object containing behavioral flags: + - **`destructive`:** Boolean indicating if the action modifies or deletes data + - **`idempotent`:** Boolean indicating if running the action multiple times produces the same result + - **`readOnly`:** Boolean indicating if the action only reads data without modifications + +### Action Context + +When an action is executed, it receives a context object (`ActionsRegistryActionContext`) containing: + +- **`input`:** The validated input data matching the defined input schema +- **`logger`:** A LoggerService instance for logging within the action +- **`credentials`:** BackstageCredentials for authentication and authorization + +## Using the Service + +### Registering an Action + +Here's an example of how to register an action with the Actions Registry Service: + +```typescript +import { ActionsRegistryService } from '@backstage/backend-plugin-api'; + +export function registerMyActions(actionsRegistry: ActionsRegistryService) { + // Register a simple read-only action + actionsRegistry.register({ + name: 'fetch-user-info', + title: 'Fetch User Information', + description: 'Retrieves user information from the catalog', + schema: { + input: z => + z.object({ + userRef: z.string(), + includeGroups: z.boolean().optional(), + }), + output: z => + z.object({ + user: z.object({ + name: z.string(), + email: z.string(), + groups: z.array(z.string()).optional(), + }), + }), + }, + attributes: { + readOnly: true, + idempotent: true, + }, + action: async ({ input, logger, credentials }) => { + logger.info(`Fetching user info for ${input.userRef}`); + + // Perform the action logic here + const user = await fetchUserFromCatalog(input.userRef, credentials); + + return { + output: { + user: { + name: user.name, + email: user.email, + groups: input.includeGroups ? user.groups : undefined, + }, + }, + }; + }, + }); + + // Register a destructive action + actionsRegistry.register({ + name: 'delete-entity', + title: 'Delete Entity', + description: 'Removes an entity from the catalog', + schema: { + input: z => + z.object({ + entityRef: z.string(), + force: z.boolean().optional(), + }), + output: z => + z.object({ + deletedEntities: z.array(z.string()), + }), + }, + attributes: { + destructive: true, + idempotent: false, + }, + action: async ({ input, logger, credentials }) => { + logger.warn(`Deleting entity ${input.entityRef}`); + + // Perform the deletion logic here + const { deletedEntities } = await deleteEntityFromCatalog( + input.entityRef, + input.force, + credentials, + ); + + return { + output: deletedEntities, + }; + }, + }); +} +``` + +### Accessing the Service in a Plugin + +To use the Actions Registry Service in your plugin, access it through dependency injection: + +```typescript +import { + createBackendPlugin, + coreServices, +} from '@backstage/backend-plugin-api'; +import { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha'; + +export const myPlugin = createBackendPlugin({ + pluginId: 'my-plugin', + register(env) { + env.registerInit({ + deps: { + actionsRegistry: actionsRegistryServiceRef, + logger: coreServices.logger, + }, + async init({ actionsRegistry, logger }) { + logger.info('Registering actions...'); + registerMyActions(actionsRegistry); + logger.info('Actions registered successfully'); + }, + }); + }, +}); +``` + +## Best Practices + +### Naming Conventions + +- **Use kebab-case:** Action names should be in kebab-case (e.g., `fetch-user-info`, `create-repository`) +- **Be Descriptive:** Choose names that clearly describe what the action does +- **Avoid Redundancy:** Don't include plugin names in action names since the plugin context is separate +- **Use Verbs:** Start action names with verbs that describe the operation (e.g., `fetch`, `create`, `delete`, `update`) + +## Action Attributes Reference + +| Attribute | Type | Default | Description | +| ------------- | ------- | ------- | ------------------------------------------------------------------- | +| `destructive` | boolean | `true` | Indicates the action modifies or deletes data. Use with caution. | +| `idempotent` | boolean | `false` | Indicates the action can be run multiple times with the same result | +| `readOnly` | boolean | `false` | Indicates the action only reads data without making modifications | + +These attributes help consumers of actions understand their behavior and implement appropriate safeguards, retries, or optimizations based on the action's characteristics. diff --git a/docs/backend-system/core-services/actions.md b/docs/backend-system/core-services/actions.md new file mode 100644 index 0000000000..ddb28b4da7 --- /dev/null +++ b/docs/backend-system/core-services/actions.md @@ -0,0 +1,131 @@ +--- +id: actions +title: Actions (alpha) +sidebar_label: Actions (alpha) +description: Documentation for the Actions Service +--- + +## Overview + +The Actions Service is a core service that provides a standardized interface for discovering and executing registered actions within Backstage backend plugins. This service acts as the consumer-facing API for actions that have been registered through the Actions Registry Service, allowing plugins to list available actions and invoke them with proper authentication and input validation. + +## How it Works + +The Actions Service implements the `ActionsService` interface, which provides two primary methods: + +- **`list()`:** Retrieves all available actions with their complete metadata +- **`invoke()`:** Executes a specific action by ID with provided input data + +The service works in conjunction with the [Actions Registry Service](./actions-registry.md), where actions are registered by plugins and then made available for discovery and execution through this service. + +## Action Identification + +Actions are identified using a unique ID that follows a specific format: + +- All action IDs are prefixed with the plugin ID that registered them, following the pattern `pluginId:actionName` +- An action named `fetch-user-info` registered by the `catalog` plugin would have the ID `catalog:fetch-user-info` +- When using the `actionsRegistryServiceMock`, the plugin ID prefix will be `test:` + +This naming convention ensures that action names are globally unique across all plugins and provides clear ownership identification. + +## Configuration + +The Actions Service can be configured to control which plugins' actions are available: + +```yaml +backend: + actions: + pluginSources: + - catalog +``` + +## Using the Service + +### Listing Available Actions + +Here's an example of how to list all available actions: + +```typescript +import { ActionsService } from '@backstage/backend-plugin-api'; + +export async function listAvailableActions( + actionsService: ActionsService, + credentials: BackstageCredentials, +) { + try { + const { actions } = await actionsService.list({ credentials }); + + console.log(`Found ${actions.length} available actions:`); + + actions.forEach(action => { + console.log(`- ${action.id}: ${action.title}`); + console.log(` Description: ${action.description}`); + console.log(` Attributes: ${JSON.stringify(action.attributes)}`); + + if (action.schema.input) { + console.log( + ` Input Schema: ${JSON.stringify(action.schema.input, null, 2)}`, + ); + } + }); + + return actions; + } catch (error) { + console.error('Failed to list actions:', error); + throw error; + } +} +``` + +### Invoking an Action + +Here's an example of how to execute a specific action: + +```typescript +import { ActionsService } from '@backstage/backend-plugin-api'; + +export async function executeAction( + actionsService: ActionsService, + actionId: string, + input: JsonObject, + credentials: BackstageCredentials, +) { + try { + const { output } = await actionsService.invoke({ + id: actionId, + input, + credentials, + }); + + console.log(`Action ${actionId} executed successfully`); + console.log('Output:', JSON.stringify(output, null, 2)); + + return output; + } catch (error) { + console.error(`Failed to execute action ${actionId}:`, error); + throw error; + } +} + +// Example usage +async function fetchUserInfo( + actionsService: ActionsService, + credentials: BackstageCredentials, +) { + const output = await executeAction( + actionsService, + 'catalog:fetch-user-info', // Note: Action ID includes plugin prefix + { + userRef: 'user:default/john.doe', + includeGroups: true, + }, + credentials, + ); + + return output; +} +``` + +## Best Practices + +For comprehensive guidance on action design, naming conventions, and schema design, see the [Actions Registry Best Practices](./actions-registry.md#best-practices) documentation. diff --git a/docs/backend-system/core-services/http-router.md b/docs/backend-system/core-services/http-router.md index d7658d9a67..5e065152a0 100644 --- a/docs/backend-system/core-services/http-router.md +++ b/docs/backend-system/core-services/http-router.md @@ -68,6 +68,60 @@ For those routes you will also have to specify `allowLimitedAccess: true` when using the [`auth`](./auth.md) and [`httpAuth`](./http-auth.md) services to access the incoming credentials. +## Rate limiting + +Rate limiting allows you to limit the amount of requests users can send to you backend. +This is useful for blocking various network attacks, such as DDOS. + +To enable rate limiting, add the following to your config: + +```yaml +backend: + rateLimit: true +``` + +You can additionally configure the rate limiting parameters, also by plugin: + +```yaml +backend: + rateLimit: + global: true # Enables or disables rate limit for all plugins + window: 6s # Time window for rate limiting for single client + incomingRequestLimit: 100 # Number of requests to accept from one client during time window + ipAllowList: ['127.0.0.1'] # IPs to bypass rate limiting + skipSuccesfulRequests: false # Rate limit successful requests + skipFailedRequests: false # Rate limit failed requests + plugin: + # Plugin specific rate limiting + catalog: + window: 3s + incomingRequestLimit: 50 +``` + +By default, the rate limiting is per instance and the request counts are stored into memory. +If you want to share this information across all your backstage instances, you have to configure +the rate limiting store: + +```yaml +backend: + rateLimit: + global: true + store: + type: redis + connection: redis://127.0.0.1:16379 +``` + +If your instance is working behind a proxy, you have to configure the backend to trust the proxy +for the rate limiting being able to distinguish clients. + +```yaml +backend: + trustProxy: true +``` + +For more information about the trust proxy configuration and available options, +please refer to [express documentation](https://expressjs.com/en/guide/behind-proxies.html). + ## Configuring the service For more advanced customization, there are several APIs from the `@backstage/backend-defaults/httpRouter` package that allow you to customize the implementation of the config service. The default implementation uses all of the middleware exported from `@backstage/backend-defaults/httpRouter`, including `createLifecycleMiddleware`, `createAuthIntegrationRouter`, `createCredentialsBarrier` and `createCookieAuthRefreshMiddleware`. You can use these to create your own `httpRouter` service implementation, for example - here's how you would add a custom health check route to all plugins: @@ -78,6 +132,7 @@ import { createCookieAuthRefreshMiddleware, createCredentialsBarrier, createAuthIntegrationRouter, + createRateLimitMiddleware, } from '@backstage/backend-defaults/httpRouter'; import { createServiceFactory } from '@backstage/backend-plugin-api'; @@ -105,6 +160,11 @@ backend.add( }) { const router = PromiseRouter(); + // Optional rate limiting middleware + router.use( + createRateLimitMiddleware({ pluginId: plugin.getId(), config }), + ); + rootHttpRouter.use(`/api/${plugin.getId()}`, router); const credentialsBarrier = createCredentialsBarrier({ diff --git a/docs/backend-system/core-services/root-http-router.md b/docs/backend-system/core-services/root-http-router.md index 7a268e27fc..1e76fb1871 100644 --- a/docs/backend-system/core-services/root-http-router.md +++ b/docs/backend-system/core-services/root-http-router.md @@ -40,6 +40,10 @@ createBackendPlugin({ }); ``` +## Rate limiting + +Please refer to the [HTTP Router documentation](./http-router.md#rate-limiting). + ## Configuring the service ### Via `app-config.yaml` @@ -60,7 +64,7 @@ backend: # - A string in the format of '1d', '2 seconds' etc. as supported by the `ms` library. # - A standard ISO formatted duration string, e.g. 'P2DT6H' or 'PT1M'. # - An object with individual units (in plural) as keys, e.g. `{ days: 2, hours: 6 }`. - serverShutdownTimeout: { seconds: 20 } + serverShutdownDelay: { seconds: 20 } ``` ### Via Code @@ -121,6 +125,11 @@ backend.add( app.use(middleware.cors()); app.use(middleware.compression()); + // Optional rate limiting middleware + app.use(middleware.rateLimit()); + // If you are using rate limiting behind a proxy, you should set the `trust proxy` setting to true + app.set('trust proxy', true); + app.use(healthRouter); // you can add you your own middleware in here @@ -161,3 +170,52 @@ backend.add( }), ); ``` + +## Defining Content Security Policy (CSP) Configuration + +Content Security Policy (CSP) is a crucial security feature that helps protect your Backstage instance from various attacks, particularly Cross-Site Scripting (XSS). Backstage provides a flexible way to configure CSP directives through your `app-config.yaml` file. + +### Basic Configuration + +CSP directives can be defined under the `backend.csp` section in your configuration: + +```yaml +backend: + csp: + default-src: ["'self'"] + script-src: ["'self'", "'unsafe-inline'", 'example.com'] + connect-src: ["'self'", 'http:', 'https:'] + img-src: ["'self'", 'data:', 'https://backstage.io'] + style-src: ["'self'", "'unsafe-inline'"] + frame-src: ['https://some-analytics-provider.com'] +``` + +### Available Directives + +You can configure any CSP directive supported by modern browsers. Common directives include: + +- `default-src`: The fallback for other CSP directives +- `script-src`: Controls which scripts can be executed +- `style-src`: Controls which styles can be applied +- `img-src`: Controls which images can be loaded +- `connect-src`: Controls which URLs can be loaded using fetch, WebSocket, etc. +- `frame-src`: Controls which URLs can be embedded in iframes +- `font-src`: Controls which fonts can be loaded +- `object-src`: Controls which URLs can be loaded as plugins +- `media-src`: Controls which media (audio, video) can be loaded +- `upgrade-insecure-requests`: Instructs browsers to upgrade HTTP to HTTPS + +### Special Values + +- Common special values within directive arrays: + - `self`: Allows content from the same origin + - `unsafe-inline`: Allows inline scripts/styles + - `unsafe-eval`: Allows dynamic code evaluation + - `none`: Blocks all content for that directive + - `data:`: Allows data: URIs (commonly used for images) + - `https:`: Allows any content over HTTPS + +For more information on available CSP options, refer to: + +- [MDN Content Security Policy documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) +- [Helmet Content Security Policy](https://helmetjs.github.io/#content-security-policy) diff --git a/docs/backend-system/index.md b/docs/backend-system/index.md index 9fcd7f0c9a..2eb7f158ef 100644 --- a/docs/backend-system/index.md +++ b/docs/backend-system/index.md @@ -2,7 +2,6 @@ id: index title: The Backend System sidebar_label: Introduction -# prettier-ignore description: Introduction to Backstage's backend system and its documentation --- diff --git a/docs/contribute/getting-involved.md b/docs/contribute/getting-involved.md index 4b8c4dfc6f..696b73b7d4 100644 --- a/docs/contribute/getting-involved.md +++ b/docs/contribute/getting-involved.md @@ -1,7 +1,6 @@ --- id: getting-involved title: Getting Involved -# prettier-ignore description: How can you help us build Backstage? We welcome contributions of all kinds, from documentation to code to design. --- diff --git a/docs/contribute/index.md b/docs/contribute/index.md index 627a2ff0d0..dbdf126b20 100644 --- a/docs/contribute/index.md +++ b/docs/contribute/index.md @@ -1,7 +1,6 @@ --- id: index title: Contributors -# prettier-ignore description: Documentation on how to get set up for doing development on the Backstage repository --- diff --git a/docs/contribute/project-structure.md b/docs/contribute/project-structure.md index 984cfe98d6..08e4379620 100644 --- a/docs/contribute/project-structure.md +++ b/docs/contribute/project-structure.md @@ -1,7 +1,6 @@ --- id: project-structure title: Backstage Project Structure -# prettier-ignore description: Introduction to files and folders in the Backstage Project repository --- diff --git a/docs/dls/figma.md b/docs/dls/figma.md index 21a05d2818..738d607439 100644 --- a/docs/dls/figma.md +++ b/docs/dls/figma.md @@ -1,7 +1,6 @@ --- id: figma title: Figma -# prettier-ignore description: Documentation on using Figma to build your own plugins for Backstage --- diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md index a22a7d94d9..830027f53b 100644 --- a/docs/features/kubernetes/configuration.md +++ b/docs/features/kubernetes/configuration.md @@ -2,7 +2,6 @@ id: configuration title: Configuring Kubernetes integration sidebar_label: Configuration -# prettier-ignore description: Configuring the Kubernetes integration for Backstage expose your entity's objects --- @@ -203,6 +202,28 @@ or the [`AwsEKSClusterProcessor`](https://backstage.io/docs/reference/plugin-catalog-backend-module-aws.awseksclusterprocessor/) to automatically update the set of clusters tracked by Backstage. +For this method to work any entity that would be using this `Resource` to help drive the Kubernetes details in the Catalog's Entity pages needs to have a `dependsOn` relationship setup. Here's a quick example: + +```yaml +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + annotations: + backstage.io/kubernetes-id: dice-roller + backstage.io/kubernetes-namespace: default + name: dice-roller + description: It rolls dice + tags: + - go +spec: + type: service + lifecycle: production + owner: guest + dependsOn: ['resource:my-cluster'] +``` + +This example assumes it's using the default namespace, if that's not the case for you then make sure to include it like this: `resource:my-namespace/my-cluster`. + #### `config` This cluster locator method will read cluster information from your app-config @@ -677,6 +698,7 @@ rules: - '*' resources: - pods + - pods/log - configmaps - services - deployments diff --git a/docs/features/search/README.md b/docs/features/search/README.md index 93aa22ebe1..eb5d12080c 100644 --- a/docs/features/search/README.md +++ b/docs/features/search/README.md @@ -2,7 +2,6 @@ id: search-overview title: Search Documentation sidebar_label: Overview -# prettier-ignore description: Backstage Search lets you find the right information you are looking for in the Backstage ecosystem. --- diff --git a/docs/features/search/declarative-integration.md b/docs/features/search/declarative-integration.md index c331d810ef..b8f1c6ce5c 100644 --- a/docs/features/search/declarative-integration.md +++ b/docs/features/search/declarative-integration.md @@ -182,7 +182,7 @@ export default createPlugin({ }) ``` -Here is the `plugins/techdocs/alpha.tsx` final version, and you can also take a look at the [actual implementation](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/alpha.tsx) of a custom `TechDocs` search result item: +Here is the `plugins/techdocs/alpha/index.tsx` final version, and you can also take a look at the [actual implementation](https://github.com/backstage/backstage/blob/master/plugins/techdocs/src/alpha/index.tsx) of a custom `TechDocs` search result item: ```tsx // plugins/techdocs/alpha.tsx diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 1c36301605..1ef865039f 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -1,7 +1,6 @@ --- id: catalog-customization title: Catalog Customization -# prettier-ignore description: How to add custom filters or interface elements to the Backstage software catalog --- diff --git a/docs/features/software-catalog/descriptor-format.md b/docs/features/software-catalog/descriptor-format.md index 28ddfae282..0e54ba2690 100644 --- a/docs/features/software-catalog/descriptor-format.md +++ b/docs/features/software-catalog/descriptor-format.md @@ -2,7 +2,6 @@ id: descriptor-format title: Descriptor Format of Catalog Entities sidebar_label: YAML File Format -# prettier-ignore description: Documentation on Descriptor Format of Catalog Entities which describes the default data shape and semantics of catalog entities --- diff --git a/docs/features/software-catalog/extending-the-model--old.md b/docs/features/software-catalog/extending-the-model--old.md index 668d1d8311..00a6688352 100644 --- a/docs/features/software-catalog/extending-the-model--old.md +++ b/docs/features/software-catalog/extending-the-model--old.md @@ -1,7 +1,6 @@ --- id: extending-the-model--old title: Extending the model -# prettier-ignore description: Documentation on extending the catalog model --- diff --git a/docs/features/software-catalog/extending-the-model.md b/docs/features/software-catalog/extending-the-model.md index d289886a09..5d51a69e6b 100644 --- a/docs/features/software-catalog/extending-the-model.md +++ b/docs/features/software-catalog/extending-the-model.md @@ -1,7 +1,6 @@ --- id: extending-the-model title: Extending the model -# prettier-ignore description: Documentation on extending the catalog model --- diff --git a/docs/features/software-catalog/external-integrations.md b/docs/features/software-catalog/external-integrations.md index 8938fefdf6..0aef4565d9 100644 --- a/docs/features/software-catalog/external-integrations.md +++ b/docs/features/software-catalog/external-integrations.md @@ -1,7 +1,6 @@ --- id: external-integrations title: External integrations -# prettier-ignore description: Documentation on External integrations to integrate systems with Backstage --- diff --git a/docs/features/software-catalog/index.md b/docs/features/software-catalog/index.md index ac1d0ee8cd..1f374385a4 100644 --- a/docs/features/software-catalog/index.md +++ b/docs/features/software-catalog/index.md @@ -2,7 +2,6 @@ id: software-catalog-overview title: Backstage Software Catalog sidebar_label: Overview -# prettier-ignore description: The Backstage Software Catalog --- diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md index 1489688720..9bb0604b82 100644 --- a/docs/features/software-catalog/life-of-an-entity.md +++ b/docs/features/software-catalog/life-of-an-entity.md @@ -2,7 +2,6 @@ id: life-of-an-entity title: The Life of an Entity sidebar_label: The Life of an Entity -# prettier-ignore description: The life cycle of entities, from being introduced into the catalog, through processing, to being removed again --- diff --git a/docs/features/software-catalog/well-known-annotations.md b/docs/features/software-catalog/well-known-annotations.md index 974fa80993..cdd93b50ac 100644 --- a/docs/features/software-catalog/well-known-annotations.md +++ b/docs/features/software-catalog/well-known-annotations.md @@ -2,7 +2,6 @@ id: well-known-annotations title: Well-known Annotations on Catalog Entities sidebar_label: Well-known Annotations -# prettier-ignore description: Documentation that lists a number of well known Annotations, that have defined semantics. They can be attached to catalog entities and consumed by plugins as needed. --- @@ -115,6 +114,20 @@ the TechDocs in the TechDocs page or needing multiple builds of the same docs. This is for situations where you have complex systems where they share a single repo, and likely a single TechDoc location. +### backstage.io/techdocs-entity-path + +```yaml +# Example: +metadata: + annotations: + backstage.io/techdocs-entity: component:default/example + backstage.io/techdocs-entity-path: /path/to/this/component +``` + +The value of this annotation informs of the path to this component's TechDocs within an external entity that owns the TechDocs. +In conjunction with [backstage.io/techdocs-entity](#backstageiotechdocs-entity) this allows for deep linking into the TechDocs of +another entity, not just linking to the root of another entities TechDocs. + ### backstage.io/view-url, backstage.io/edit-url ```yaml diff --git a/docs/features/software-catalog/well-known-relations.md b/docs/features/software-catalog/well-known-relations.md index 6d61847a15..740dbe0df2 100644 --- a/docs/features/software-catalog/well-known-relations.md +++ b/docs/features/software-catalog/well-known-relations.md @@ -2,7 +2,6 @@ id: well-known-relations title: Well-known Relations between Catalog Entities sidebar_label: Well-known Relations -# prettier-ignore description: Documentation that lists a number of well known Relations, that have defined semantics. They can be attached to catalog entities and consumed by plugins as needed. --- diff --git a/docs/features/software-catalog/well-known-statuses.md b/docs/features/software-catalog/well-known-statuses.md index d293ae5062..6829b1ccdf 100644 --- a/docs/features/software-catalog/well-known-statuses.md +++ b/docs/features/software-catalog/well-known-statuses.md @@ -2,7 +2,6 @@ id: well-known-statuses title: Well-known Status fields of Catalog Entities sidebar_label: Well-known Statuses -# prettier-ignore description: Lists a number of well known entity statuses, that have defined semantics. They can be attached to catalog entities and consumed by plugins as needed. --- diff --git a/docs/features/software-templates/experimental.md b/docs/features/software-templates/experimental.md index 929fe088cf..1df041d7a2 100644 --- a/docs/features/software-templates/experimental.md +++ b/docs/features/software-templates/experimental.md @@ -1,7 +1,6 @@ --- id: experimental title: Experimental Features -# prettier-ignore description: Information on Experimental Features that are currently available in the Scaffolder --- diff --git a/docs/features/software-templates/index.md b/docs/features/software-templates/index.md index 10550f7c01..16f7c3cbbd 100644 --- a/docs/features/software-templates/index.md +++ b/docs/features/software-templates/index.md @@ -2,7 +2,6 @@ id: software-templates-index title: Backstage Software Templates sidebar_label: Overview -# prettier-ignore description: The Software Templates part of Backstage is a tool that can help you create Components inside Backstage --- diff --git a/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md b/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md index bd8d4bdb72..830c343033 100644 --- a/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md +++ b/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3.md @@ -1,7 +1,6 @@ --- id: migrating-from-v1beta2-to-v1beta3 title: Migrating to v1beta3 templates -# prettier-ignore description: How to migrate your existing templates to beta3 syntax --- diff --git a/docs/features/software-templates/migrating-to-rjsf-v5.md b/docs/features/software-templates/migrating-to-rjsf-v5.md index 8357d7567b..d35eb166f0 100644 --- a/docs/features/software-templates/migrating-to-rjsf-v5.md +++ b/docs/features/software-templates/migrating-to-rjsf-v5.md @@ -1,7 +1,6 @@ --- id: migrating-to-rjsf-v5 title: 'Migrating to react-jsonschema-form@v5' -# prettier-ignore description: Docs on migrating to `react-jsonschema-form`@v5 and the new designs --- diff --git a/docs/features/software-templates/writing-custom-actions.md b/docs/features/software-templates/writing-custom-actions.md index 26773c15c6..1a64406b04 100644 --- a/docs/features/software-templates/writing-custom-actions.md +++ b/docs/features/software-templates/writing-custom-actions.md @@ -12,7 +12,7 @@ by writing custom actions which can be used alongside our When adding custom actions, the actions array will **replace the built-in actions too**. Meaning, you will no longer be able to use them. -If you want to continue using the builtin actions, include them in the actions +If you want to continue using the builtin actions, include them in the `actions` array when registering your custom actions, as seen below. ::: @@ -52,19 +52,20 @@ its generated unit test. We will replace the existing placeholder code with our import { resolveSafeChildPath } from '@backstage/backend-plugin-api'; import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; import fs from 'fs-extra'; -import { z } from 'zod'; +import { type z } from 'zod'; export const createNewFileAction = () => { return createTemplateAction({ id: 'acme:file:create', description: 'Create an Acme file.', schema: { - input: z.object({ - contents: z.string().describe('The contents of the file'), - filename: z - .string() - .describe('The filename of the file that will be created'), - }), + input: { + contents: z => z.string({ description: 'The contents of the file' }), + filename: z => + z.string({ + description: 'The filename of the file that will be created', + }), + }, }, async handler(ctx) { @@ -95,53 +96,11 @@ The `createTemplateAction` takes an object which specifies the following: function using `ctx.output` - `handler` - the actual code which is run as part of the action, with a context -You can also choose to define your custom action using JSON schema instead of `zod`: - -```ts title="With JSON Schema" -import { resolveSafeChildPath } from '@backstage/backend-plugin-api'; -import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; -import { writeFile } from 'fs'; - -export const createNewFileAction = () => { - return createTemplateAction<{ contents: string; filename: string }>({ - id: 'acme:file:create', - description: 'Create an Acme file.', - schema: { - input: { - required: ['contents', 'filename'], - type: 'object', - properties: { - contents: { - type: 'string', - title: 'Contents', - description: 'The contents of the file', - }, - filename: { - type: 'string', - title: 'Filename', - description: 'The filename of the file that will be created', - }, - }, - }, - }, - async handler(ctx) { - const { signal } = ctx; - await writeFile( - resolveSafeChildPath(ctx.workspacePath, ctx.input.filename), - ctx.input.contents, - { signal }, - _ => {}, - ); - }, - }); -}; -``` - ### Naming Conventions Try to keep names consistent for both your own custom actions, and any actions contributed to open source. We've found that a separation of `:` and using a verb as the last part of the name works well. -We follow `provider:entity:verb` or as close to this as possible for our built in actions. For example, +We follow `provider:entity:verb` or as close to this as possible for our built-in actions. For example, `github:actions:create` or `github:repo:create`. Also feel free to use your company name to namespace them if you prefer too, for example `acme:file:create` like above. @@ -151,14 +110,14 @@ and writing of template entity definitions. ### Adding a TemplateExample -A TemplateExample is a way to document different ways that your custom action can be used. Once added it will be visible +A TemplateExample is a way to document different ways that your custom action can be used. Once added, it will be visible in your Backstage instance under the [/create/actions](https://demo.backstage.io/create/actions) path. You can have multiple examples for one action that can demonstrate different combinations of inputs and how to use them. #### Define TemplateExamples Below is a sample TemplateExample that is used for `publish:github`. The source code is available -on [github](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.ts) +on [GitHub](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.ts) and preview on [demo.backstage.io/create/actions](https://demo.backstage.io/create/actions#publish-github) ```ts title="With JSON Schema" @@ -222,7 +181,7 @@ return createTemplateAction({ #### Test TemplateAction examples It is also possible to test your example TemplateActions. You can see a sample test -on [github](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts) +on [GitHub](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-github/src/actions/github.examples.test.ts) ### The context object @@ -234,13 +193,12 @@ argument. It looks like the following: implement [idempotency of the actions](https://github.com/backstage/backstage/tree/master/beps/0004-scaffolder-task-idempotency) by not re-running the same function again if it was executed successfully on the previous run. -- `ctx.logger` - a Winston logger for additional logging inside your action -- `ctx.logStream` - a stream version of the logger if needed +- `ctx.logger` - a [LoggerService](../../backend-system/core-services/logger.md) instance for additional logging inside your action - `ctx.workspacePath` - a string of the working directory of the template run - `ctx.input` - an object which should match the `zod` or JSON schema provided in the `schema.input` part of the action definition - `ctx.output` - a function which you can call to set outputs that match the - JSON schema or `zod` in `schema.output` for ex. `ctx.output('downloadUrl', myDownloadUrl)` + `zod` schema in `schema.output` for ex. `ctx.output('downloadUrl', myDownloadUrl)` - `createTemporaryDirectory` a function to call to give you a temporary directory somewhere on the runner, so you can store some files there rather than polluting the `workspacePath` @@ -249,7 +207,7 @@ argument. It looks like the following: ## Registering Custom Actions -To register your new custom action in the Backend System you will need to create a backend module. Here is a very +To register your new custom action in the Backend System, you will need to create a backend module. Here is a very simplified example of how to do that: ```ts title="packages/backend/src/index.ts" @@ -327,8 +285,8 @@ const res = await ctx.checkpoint?.({ }); ``` -You have to define the unique key in scope of the scaffolder task for your checkpoint. During the execution task engine -will check if the checkpoint with such key was already executed or not, if yes, and the run was successful, the callback +You have to define the unique key in the scope of the scaffolder task for your checkpoint. During the execution task engine +will check if the checkpoint with such a key was already executed or not, if yes, and the run was successful, the callback will be skipped and instead the stored value will be returned. Whenever you change the return type of the checkpoint, we encourage you to change the ID. diff --git a/docs/features/software-templates/writing-templates.md b/docs/features/software-templates/writing-templates.md index eeaa4ad203..275d5c26b2 100644 --- a/docs/features/software-templates/writing-templates.md +++ b/docs/features/software-templates/writing-templates.md @@ -274,6 +274,58 @@ spec: password: ${{ secrets.password }} ``` +You can also consume secrets within `each` step of the template. + +```yaml +apiVersion: scaffolder.backstage.io/v1beta3 +kind: Template +metadata: + name: v1beta3-demo + title: Test Action template + description: scaffolder v1beta3 template demo +spec: + owner: backstage/techdocs-core + type: service + + parameters: + - title: Authentication + description: Provide authentication for the resource + required: + - service1 + - token1 + - service2 + - token2 + properties: + service1: + type: string + token1: + type: string + ui:field: Secret + service2: + type: string + token2: + type: string + ui:field: Secret + + steps: + - id: setupAuthentication + action: auth:create + each: + [ + { + name: '${{ parameters.service1 }}', + token: '${{ secrets.token1 }}', + }, + { + name: '${{ parameters.service2 }}', + token: '${{ secrets.token2 }}', + }, + ] + input: + name: ${{ each.value.name }} + token: ${{ each.value.token }} +``` + ### Custom step layouts If you find that the default layout of the form used in a particular step does not meet your needs then you can supply your own [custom step layout](./writing-custom-step-layouts.md). diff --git a/docs/features/techdocs/README.md b/docs/features/techdocs/README.md index beec6d1fad..0306a9746b 100644 --- a/docs/features/techdocs/README.md +++ b/docs/features/techdocs/README.md @@ -2,7 +2,6 @@ id: techdocs-overview title: TechDocs Documentation sidebar_label: Overview -# prettier-ignore description: TechDocs is Spotify’s homegrown docs-like-code solution built directly into Backstage --- diff --git a/docs/features/techdocs/cli.md b/docs/features/techdocs/cli.md index 517b2a3547..a52730d335 100644 --- a/docs/features/techdocs/cli.md +++ b/docs/features/techdocs/cli.md @@ -1,7 +1,6 @@ --- id: cli title: TechDocs CLI -# prettier-ignore description: TechDocs CLI - a utility command line interface for managing TechDocs sites in Backstage. --- diff --git a/docs/features/techdocs/concepts.md b/docs/features/techdocs/concepts.md index 2944197dfb..f427f0cd2b 100644 --- a/docs/features/techdocs/concepts.md +++ b/docs/features/techdocs/concepts.md @@ -1,7 +1,6 @@ --- id: concepts title: Concepts -# prettier-ignore description: Documentation on concepts that are introduced with Spotify's docs-like-code solution in Backstage --- diff --git a/docs/features/techdocs/configuration.md b/docs/features/techdocs/configuration.md index 05f184e90f..e21e452b7c 100644 --- a/docs/features/techdocs/configuration.md +++ b/docs/features/techdocs/configuration.md @@ -1,7 +1,6 @@ --- id: configuration title: TechDocs Configuration Options -# prettier-ignore description: Reference documentation for configuring TechDocs using app-config.yaml --- diff --git a/docs/features/techdocs/configuring-ci-cd.md b/docs/features/techdocs/configuring-ci-cd.md index 20a73798a4..d818c129a4 100644 --- a/docs/features/techdocs/configuring-ci-cd.md +++ b/docs/features/techdocs/configuring-ci-cd.md @@ -1,7 +1,6 @@ --- id: configuring-ci-cd title: Configuring CI/CD to generate and publish TechDocs sites -# prettier-ignore description: Configuring CI/CD to generate and publish TechDocs sites to cloud storage --- diff --git a/docs/features/techdocs/how-to-guides.md b/docs/features/techdocs/how-to-guides.md index 8a95c86533..7d8c99ffda 100644 --- a/docs/features/techdocs/how-to-guides.md +++ b/docs/features/techdocs/how-to-guides.md @@ -942,6 +942,35 @@ metadata: backstage.io/techdocs-entity: system:default/example ``` +### Deep linking into TechDocs + +The `backstage.io/techdocs-entity-path` annotation can be use to deep link into a specific page within the components TechDocs. +This can be used in conjunction with `backstage.io/techdocs-entity` or standalone. + +```yaml +apiVersion: backstage.io/v1alpha1 +kind: System +metadata: + name: example + namespace: default + title: Example + description: This is the parent entity + annotations: + backstage.io/techdocs-ref: dir:. + +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: example-platfrom + title: Example Application Platform + namespace: default + description: This is the child entity + annotations: + backstage.io/techdocs-entity: system:default/example + backstage.io/techdocs-entity-path: /path/to/component/docs +``` + ## How to resolve broken links from moved or renamed pages in your documentation site TechDocs supports using the [mkdocs-redirects](https://github.com/mkdocs/mkdocs-redirects/tree/master) plugin to create a redirect map for any TechDocs site. This allows broken links from renamed or moved pages in your site to be redirected to their specified replacement. diff --git a/docs/frontend-system/architecture/00-index.md b/docs/frontend-system/architecture/00-index.md index 20a12ba1e8..8307877f16 100644 --- a/docs/frontend-system/architecture/00-index.md +++ b/docs/frontend-system/architecture/00-index.md @@ -2,7 +2,6 @@ id: index title: Frontend System Architecture sidebar_label: Overview -# prettier-ignore description: The structure and architecture of the new Frontend System --- diff --git a/docs/frontend-system/architecture/10-app.md b/docs/frontend-system/architecture/10-app.md index 0fa4ba04cc..3fcfec9e9b 100644 --- a/docs/frontend-system/architecture/10-app.md +++ b/docs/frontend-system/architecture/10-app.md @@ -2,7 +2,6 @@ id: app title: App Instances sidebar_label: App -# prettier-ignore description: App instances --- @@ -77,3 +76,98 @@ app: ``` Note that you do not need to manually exclude packages that you also import explicitly in code, since plugin instances are deduplicated by the app. You will never end up with duplicate plugin installations except if they are in fact two different plugin instances with different IDs. + +## Plugin Info Resolution + +When a plugin is installed in an app it may provide sources of information about the plugin that can be useful to end users and admins. This includes things like what version of a plugin is running, what team owns the plugin, and who to contact for support. You can read more about how the plugins provide this information in the [plugins `info` option section](./15-plugins.md#info). + +By default the app will pick a few common fields from `package.json` files, and assume that the opaque manifests are `catalog-info.yaml` files that some information can be gathered from too. This information will then be available via the `info()` method on plugin instances, returning a structure of the `FrontendPluginInfo` type. + +### Extending Plugin Info + +The default plugin info is intended as a base to build upon. As part of setting up an app you can both customize the way that the plugin info is resolved, as well as extend the `FrontendPluginInfo` type to include more information. + +In order to extend the `FrontendPluginInfo` type you use [TypeScript module augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation). This makes it possible to extend the `FrontendPluginInfo` interface with additional fields, which you can then add custom resolution logic for as well as access within the app. For example, you might add a `slackChannel` field as follows: + +```ts +declare module '@backstage/frontend-plugin-api' { + interface FrontendPluginInfo { + /** + * The slack channel to use for support requests for this plugin. + */ + slackChannel?: string; + } +} +``` + +### Customizing Plugin Info Resolution + +With the new `slackChannel` field in place, we now need to provide a custom resolver that knows how to extract this information from the plugin information sources. This is done by passing a custom `pluginInfoResolver` to `createApp`, which in our example is declared like this: + +```ts title="pluginInfoResolver.ts" +import { createPluginInfoResolver } from '@backstage/frontend-plugin-api'; + +// It is recommended to keep the above module augmentation in this file too + +export const pluginInfoResolver: FrontendPluginInfoResolver = async ctx => { + // In our particular example app we assume that all plugin manifests are catalog-info.yaml files + const manifest = (await ctx.manifest?.()) as Entity | undefined; + + // Call the default resolver to populate common fields + const { info } = await ctx.defaultResolver({ + packageJson: await ctx.packageJson(), + manifest: manifest, + }); + + // In this example the catalog model has been extended with a metadata.slackChannel field + const slackChannel = manifest?.metadata?.slackChannel?.toString(); + + if (slackChannel) { + info.slackChannel = slackChannel; + info.links = [ + ...(info.links ?? []), + { + title: 'Slack Channel', + url: `https://our-workspace.enterprise.slack.com/archives/${slackChannel}`, + }, + ]; + } + + return { info }; +}; +``` + +And included in the app as follows: + +```ts title="App.tsx" +import { pluginInfoResolver } from './pluginInfoResolver'; + +const app = createApp({ + pluginInfoResolver, + // ... other options +}); +``` + +### Overriding Plugin Info + +Another way to customize the plugin info is to use the `app.pluginOverrides` static configuration key. These overrides are applied after the plugin info has been resolved as a final step before making it available to users. These overrides are particularly useful to override information in third-party plugins. For example, if your organization has an individual team that is responsible for the maintenance of the Software Catalog, you might configure the following override: + +```yaml +app: + pluginOverrides: + - match: + pluginId: catalog + info: + ownerEntityRefs: [catalog-owners] +``` + +You can match on both the `pluginId` and/or `packageName` of the plugin, although the `packageName` will only be supported if the plugin provides an loader for the `package.json` file. Using `//` you are also able to use a regex pattern for this matching. For example, if you wanted to override the owner for all plugins from the `@acme` namespace, you could do the following: + +```yaml +app: + pluginOverrides: + - match: + packageName: /@acme/.*/ + info: + ownerEntityRefs: [acme-owners] +``` diff --git a/docs/frontend-system/architecture/15-plugins.md b/docs/frontend-system/architecture/15-plugins.md index 825f2a3982..13c93c6962 100644 --- a/docs/frontend-system/architecture/15-plugins.md +++ b/docs/frontend-system/architecture/15-plugins.md @@ -2,7 +2,6 @@ id: plugins title: Frontend Plugins sidebar_label: Plugins -# prettier-ignore description: Frontend plugins --- @@ -53,6 +52,35 @@ These are the routes that the plugin exposes to the app. The `routes` option dec This is a list of feature flag declarations that your plugin provides to the app. This makes sure that the feature flags are correctly registered and can be toggled in the app. To read a feature flag you can use the feature flags [Utility API](../architecture/33-utility-apis.md), accessible via `featureFlagsApiRef`. +### `info` option + +This options is used to provide loaders for different sources of information about the plugin that may be useful to users and admins. The two available loaders are `packageJson` and `manifest`, and a plugin can use either or both as needed. The resulting information is available via the `info()` method on the plugin instance once it is installed in an app, but it is up to each app to decide how to derive the information from the provided sources. + +The `info.packageJson` loader **MUST** be used by all plugins that are implemented within their own package, and it should load the `package.json` file for the plugin package. Typical usage looks like this: + +```ts +export default createFrontendPlugin({ + pluginId: 'my-plugin', + info: { + packageJson: () => import('../package.json'), + }, + extensions: [...], +}); +``` + +The `info.manifest` loader is used to point to an opaque plugin manifest. This **MUST ONLY** be used by plugins that are intended for use within a single organization. Plugins that are published to an open package registry should **NOT** use this loader. The loader is useful for adding additional internal metadata associated with the plugin, and it is up to the Backstage app to decide how these manifests are parsed and used. The default manifest parser in an app created with `createApp` from `@backstage/frontend-defaults` is able to parse the default `catalog-info.yaml` format and built-in fields such as `metadata.links` and `spec.owner`. + +Typical usage looks like this: + +```ts +export default createFrontendPlugin({ + pluginId: '...', + info: { + manifest: () => import('../catalog-info.yaml'), + }, +}); +``` + ## Installing a Plugin in an App A plugin instance is considered a frontend feature and can be installed directly in any Backstage frontend app. See the [app documentation](./10-app.md) for more information about the different ways in which you can install new features in an app. diff --git a/docs/frontend-system/architecture/20-extensions.md b/docs/frontend-system/architecture/20-extensions.md index eae0405bda..590d0a7bb9 100644 --- a/docs/frontend-system/architecture/20-extensions.md +++ b/docs/frontend-system/architecture/20-extensions.md @@ -2,7 +2,6 @@ id: extensions title: Frontend Extensions sidebar_label: Extensions -# prettier-ignore description: Frontend extensions --- diff --git a/docs/frontend-system/architecture/23-extension-blueprints.md b/docs/frontend-system/architecture/23-extension-blueprints.md index fb10749845..081497655e 100644 --- a/docs/frontend-system/architecture/23-extension-blueprints.md +++ b/docs/frontend-system/architecture/23-extension-blueprints.md @@ -2,7 +2,6 @@ id: extension-blueprints title: Frontend Extension Blueprints sidebar_label: Extensions Blueprints -# prettier-ignore description: Frontend extensions --- diff --git a/docs/frontend-system/architecture/25-extension-overrides.md b/docs/frontend-system/architecture/25-extension-overrides.md index faaf446f41..6b07fe4faa 100644 --- a/docs/frontend-system/architecture/25-extension-overrides.md +++ b/docs/frontend-system/architecture/25-extension-overrides.md @@ -2,7 +2,6 @@ id: extension-overrides title: Frontend Extension Overrides sidebar_label: Extension Overrides -# prettier-ignore description: Frontend extension overrides --- diff --git a/docs/frontend-system/architecture/30-references.md b/docs/frontend-system/architecture/30-references.md index 24a9e5df2a..618f2868bb 100644 --- a/docs/frontend-system/architecture/30-references.md +++ b/docs/frontend-system/architecture/30-references.md @@ -2,7 +2,6 @@ id: references title: Value References sidebar_label: Value References -# prettier-ignore description: Value References --- diff --git a/docs/frontend-system/architecture/33-utility-apis.md b/docs/frontend-system/architecture/33-utility-apis.md index fd069319de..ce67956281 100644 --- a/docs/frontend-system/architecture/33-utility-apis.md +++ b/docs/frontend-system/architecture/33-utility-apis.md @@ -2,7 +2,6 @@ id: utility-apis title: Utility APIs sidebar_label: Utility APIs -# prettier-ignore description: Utility APIs --- diff --git a/docs/frontend-system/architecture/36-routes.md b/docs/frontend-system/architecture/36-routes.md index 7b6376b2eb..c07eea304d 100644 --- a/docs/frontend-system/architecture/36-routes.md +++ b/docs/frontend-system/architecture/36-routes.md @@ -2,7 +2,6 @@ id: routes title: Frontend Routes sidebar_label: Routes -# prettier-ignore description: Frontend routes --- diff --git a/docs/frontend-system/architecture/50-naming-patterns.md b/docs/frontend-system/architecture/50-naming-patterns.md index 55068d8ea1..14634b4355 100644 --- a/docs/frontend-system/architecture/50-naming-patterns.md +++ b/docs/frontend-system/architecture/50-naming-patterns.md @@ -2,7 +2,6 @@ id: naming-patterns title: Frontend System Naming Patterns sidebar_label: Naming Patterns -# prettier-ignore description: Naming patterns in the frontend system --- diff --git a/docs/frontend-system/architecture/60-migrations.md b/docs/frontend-system/architecture/60-migrations.md index 3a33e663f4..413b3b07f4 100644 --- a/docs/frontend-system/architecture/60-migrations.md +++ b/docs/frontend-system/architecture/60-migrations.md @@ -2,7 +2,6 @@ id: migrations title: Frontend System Changelog sidebar_label: Changelog -# prettier-ignore description: Changelog documentation for different versions of the frontend system core APIs. --- diff --git a/docs/frontend-system/building-apps/01-index.md b/docs/frontend-system/building-apps/01-index.md index 5b5298a2c5..0a65ddf122 100644 --- a/docs/frontend-system/building-apps/01-index.md +++ b/docs/frontend-system/building-apps/01-index.md @@ -2,7 +2,6 @@ id: index title: Building Frontend Apps sidebar_label: Overview -# prettier-ignore description: Building frontend apps using the new frontend system --- diff --git a/docs/frontend-system/building-apps/02-configuring-extensions.md b/docs/frontend-system/building-apps/02-configuring-extensions.md index 4052ef47f0..11da9810a4 100644 --- a/docs/frontend-system/building-apps/02-configuring-extensions.md +++ b/docs/frontend-system/building-apps/02-configuring-extensions.md @@ -2,7 +2,6 @@ id: configuring-extensions title: Configuring Extensions in the App sidebar_label: Configuring Extensions -# prettier-ignore description: Documentation for how to configure extensions in a Backstage app --- diff --git a/docs/frontend-system/building-apps/03-built-in-extensions.md b/docs/frontend-system/building-apps/03-built-in-extensions.md index 5f74100df0..4cca7cebe2 100644 --- a/docs/frontend-system/building-apps/03-built-in-extensions.md +++ b/docs/frontend-system/building-apps/03-built-in-extensions.md @@ -2,7 +2,6 @@ id: built-in-extensions title: App Built-in Extensions sidebar_label: Built-in extensions -# prettier-ignore description: Configuring or overriding built-in extensions --- diff --git a/docs/frontend-system/building-apps/06-plugin-conversion.md b/docs/frontend-system/building-apps/06-plugin-conversion.md index 2fab6cf828..720a29ddb7 100644 --- a/docs/frontend-system/building-apps/06-plugin-conversion.md +++ b/docs/frontend-system/building-apps/06-plugin-conversion.md @@ -2,14 +2,14 @@ id: plugin-conversion title: Converting 3rd-party plugins from the old system sidebar_label: Converting 3rd-party Plugins -# prettier-ignore description: Documentation for how to convert 3rd-party plugins to support the new frontend system. --- If you are using or want to use a 3rd-party plugin that does not yet support the new frontend system in your app, you can often use conversion utilities from `@backstage/core-compat-api` in order wrap the plugin to make it possible to install in your app. -> [!CAUTION] -> The purpose of these utilities is to wrap 3rd-party plugins. Do not use them for your own plugins where you can add support for the new frontend system directly. +:::caution +The purpose of these utilities is to wrap 3rd-party plugins. Do not use them for your own plugins where you can add support for the new frontend system directly. +::: ## Converting a legacy plugin diff --git a/docs/frontend-system/building-apps/08-migrating.md b/docs/frontend-system/building-apps/08-migrating.md index 7b1fbf28d8..6b1332834a 100644 --- a/docs/frontend-system/building-apps/08-migrating.md +++ b/docs/frontend-system/building-apps/08-migrating.md @@ -2,7 +2,6 @@ id: migrating title: Migrating Apps sidebar_label: Migration Guide -# prettier-ignore description: How to migrate existing apps to the new frontend system --- diff --git a/docs/frontend-system/building-plugins/01-index.md b/docs/frontend-system/building-plugins/01-index.md index 33ec65d9d1..e9d6f1cbe2 100644 --- a/docs/frontend-system/building-plugins/01-index.md +++ b/docs/frontend-system/building-plugins/01-index.md @@ -2,7 +2,6 @@ id: index title: Building Frontend Plugins sidebar_label: Overview -# prettier-ignore description: Building frontend plugins using the new frontend system --- diff --git a/docs/frontend-system/building-plugins/02-testing.md b/docs/frontend-system/building-plugins/02-testing.md index 87c22b839b..f37c7cb106 100644 --- a/docs/frontend-system/building-plugins/02-testing.md +++ b/docs/frontend-system/building-plugins/02-testing.md @@ -2,7 +2,6 @@ id: testing title: Frontend System Testing Plugins sidebar_label: Testing -# prettier-ignore description: Testing plugins in the frontend system --- diff --git a/docs/frontend-system/building-plugins/03-common-extension-blueprints.md b/docs/frontend-system/building-plugins/03-common-extension-blueprints.md index b437a44552..e1e903eadd 100644 --- a/docs/frontend-system/building-plugins/03-common-extension-blueprints.md +++ b/docs/frontend-system/building-plugins/03-common-extension-blueprints.md @@ -2,7 +2,6 @@ id: common-extension-blueprints title: Common Extension Blueprints sidebar_label: Common Extension Blueprints -# prettier-ignore description: Extension blueprints provided by the frontend system and core features --- diff --git a/docs/frontend-system/building-plugins/04-built-in-data-refs.md b/docs/frontend-system/building-plugins/04-built-in-data-refs.md index a26f6549b7..00392ed467 100644 --- a/docs/frontend-system/building-plugins/04-built-in-data-refs.md +++ b/docs/frontend-system/building-plugins/04-built-in-data-refs.md @@ -2,7 +2,6 @@ id: built-in-data-refs title: Built-in data refs sidebar_label: Built-in data refs -# prettier-ignore description: Configuring or overriding built-in extension data references --- diff --git a/docs/frontend-system/building-plugins/05-migrating.md b/docs/frontend-system/building-plugins/05-migrating.md index ba292aa5d5..483ebf68f8 100644 --- a/docs/frontend-system/building-plugins/05-migrating.md +++ b/docs/frontend-system/building-plugins/05-migrating.md @@ -2,7 +2,6 @@ id: migrating title: Migrating Plugins sidebar_label: Migration Guide -# prettier-ignore description: How to migrate an existing frontend plugin to the new frontend system --- diff --git a/docs/frontend-system/index.md b/docs/frontend-system/index.md index 201718f6d3..c9a8059086 100644 --- a/docs/frontend-system/index.md +++ b/docs/frontend-system/index.md @@ -2,7 +2,6 @@ id: index title: The Frontend System sidebar_label: Introduction -# prettier-ignore description: The Frontend System --- diff --git a/docs/frontend-system/utility-apis/01-index.md b/docs/frontend-system/utility-apis/01-index.md index 07f7dcc2a8..71e1eea740 100644 --- a/docs/frontend-system/utility-apis/01-index.md +++ b/docs/frontend-system/utility-apis/01-index.md @@ -2,7 +2,6 @@ id: index title: Utility APIs sidebar_label: Overview -# prettier-ignore description: Working with Utility APIs in the New Frontend System --- diff --git a/docs/frontend-system/utility-apis/02-creating.md b/docs/frontend-system/utility-apis/02-creating.md index bf53911d24..d02b74cbf6 100644 --- a/docs/frontend-system/utility-apis/02-creating.md +++ b/docs/frontend-system/utility-apis/02-creating.md @@ -2,7 +2,6 @@ id: creating title: Creating Utility APIs sidebar_label: Creating APIs -# prettier-ignore description: Creating new utility APIs in your plugins and app --- diff --git a/docs/frontend-system/utility-apis/03-consuming.md b/docs/frontend-system/utility-apis/03-consuming.md index bdf3b8dcdb..d5ea537284 100644 --- a/docs/frontend-system/utility-apis/03-consuming.md +++ b/docs/frontend-system/utility-apis/03-consuming.md @@ -2,7 +2,6 @@ id: consuming title: Consuming Utility APIs sidebar_label: Consuming APIs -# prettier-ignore description: Consuming utility APIs --- diff --git a/docs/frontend-system/utility-apis/04-configuring.md b/docs/frontend-system/utility-apis/04-configuring.md index 4847fc6eaf..1b28bf1351 100644 --- a/docs/frontend-system/utility-apis/04-configuring.md +++ b/docs/frontend-system/utility-apis/04-configuring.md @@ -2,7 +2,6 @@ id: configuring title: Configuring Utility APIs sidebar_label: Configuring -# prettier-ignore description: Configuring, extending, and overriding utility APIs --- diff --git a/docs/getting-started/config/authentication.md b/docs/getting-started/config/authentication.md index cb0a329ae1..e25f357ff8 100644 --- a/docs/getting-started/config/authentication.md +++ b/docs/getting-started/config/authentication.md @@ -128,7 +128,7 @@ backend.add(import('@backstage/plugin-auth-backend-module-github-provider')); /* highlight-add-end */ ``` -Restart Backstage from the terminal, by stopping it with `Ctrl+C`, and starting it with `yarn dev`. You should be welcomed by a login prompt! If you try to login at this point you will get a "Failed to sign-in, unable to resolve user identity" message, read on as we'll fix that next. +Restart Backstage from the terminal, by stopping it with `Ctrl+C`, and starting it with `yarn start`. You should be welcomed by a login prompt! If you try to login at this point you will get a "Failed to sign-in, unable to resolve user identity" message, read on as we'll fix that next. :::note Note @@ -157,7 +157,7 @@ For the sake of this guide we'll simply step you though adding a User to the `or 3. Now make sure to replace the text "YOUR GITHUB USERNAME" with your actual GitHub User name. -Let's restart Backstage from the terminal once more, by stopping it with `Ctrl+C`, and starting it with `yarn dev`. You should now be able to log into Backstage and see items in your Catalog. +Let's restart Backstage from the terminal once more, by stopping it with `Ctrl+C`, and starting it with `yarn start`. You should now be able to log into Backstage and see items in your Catalog. To learn more about Authentication in Backstage, here are some docs you could read: @@ -199,7 +199,7 @@ integrations: :::note Note -If you've updated the configuration for your integration, it's likely that the backend will need a restart to apply these changes. To do this, stop the running instance in your terminal with `Control-C`, then start it again with `yarn dev`. Once the backend has restarted, retry the operation. +If you've updated the configuration for your integration, it's likely that the backend will need a restart to apply these changes. To do this, stop the running instance in your terminal with `Control-C`, then start it again with `yarn start`. Once the backend has restarted, retry the operation. ::: diff --git a/docs/integrations/aws-codecommit/locations.md b/docs/integrations/aws-codecommit/locations.md index 35187b1b89..28e77769b2 100644 --- a/docs/integrations/aws-codecommit/locations.md +++ b/docs/integrations/aws-codecommit/locations.md @@ -2,7 +2,6 @@ id: locations sidebar_label: Locations title: Amazon Web Services CodeCommit Locations -# prettier-ignore description: Setting up an integration with Amazon Web Services CodeCommit --- diff --git a/docs/integrations/aws-s3/discovery.md b/docs/integrations/aws-s3/discovery.md index fa1eb017fc..fcba5ca04f 100644 --- a/docs/integrations/aws-s3/discovery.md +++ b/docs/integrations/aws-s3/discovery.md @@ -2,7 +2,6 @@ id: discovery title: AWS S3 Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from an AWS S3 Bucket --- diff --git a/docs/integrations/aws-s3/locations.md b/docs/integrations/aws-s3/locations.md index 9bac28f906..3ed6af62fe 100644 --- a/docs/integrations/aws-s3/locations.md +++ b/docs/integrations/aws-s3/locations.md @@ -2,7 +2,6 @@ id: locations sidebar_label: Locations title: Amazon Web Services S3 Locations -# prettier-ignore description: Setting up an integration with Amazon Web Services S3 --- diff --git a/docs/integrations/azure-blobStorage/discovery.md b/docs/integrations/azure-blobStorage/discovery.md index 32612daf75..bed97441f9 100644 --- a/docs/integrations/azure-blobStorage/discovery.md +++ b/docs/integrations/azure-blobStorage/discovery.md @@ -2,7 +2,6 @@ id: discovery title: Azure Blob Storage Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from an Azure Blob Storage account --- diff --git a/docs/integrations/azure-blobStorage/locations.md b/docs/integrations/azure-blobStorage/locations.md index 38d8555c2e..abe2a238ba 100644 --- a/docs/integrations/azure-blobStorage/locations.md +++ b/docs/integrations/azure-blobStorage/locations.md @@ -2,7 +2,6 @@ id: locations sidebar_label: Locations title: Azure Blob Storage account Locations -# prettier-ignore description: Setting up an integration with Azure Blob Storage account --- diff --git a/docs/integrations/azure/discovery.md b/docs/integrations/azure/discovery.md index b749f8e9ed..a4584ef338 100644 --- a/docs/integrations/azure/discovery.md +++ b/docs/integrations/azure/discovery.md @@ -2,7 +2,6 @@ id: discovery title: Azure DevOps Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from repositories in an Azure DevOps organization --- diff --git a/docs/integrations/azure/locations.md b/docs/integrations/azure/locations.md index 61c54287c9..3ea180f5bd 100644 --- a/docs/integrations/azure/locations.md +++ b/docs/integrations/azure/locations.md @@ -2,7 +2,6 @@ id: locations title: Azure DevOps Locations sidebar_label: Locations -# prettier-ignore description: Integrating source code stored in Azure DevOps into the Backstage catalog --- diff --git a/docs/integrations/azure/org.md b/docs/integrations/azure/org.md index 58c6c9f889..efcd8ae612 100644 --- a/docs/integrations/azure/org.md +++ b/docs/integrations/azure/org.md @@ -2,7 +2,6 @@ id: org title: Microsoft Entra Tenant Data sidebar_label: Org Data -# prettier-ignore description: Importing users and groups from Microsoft Entra ID into Backstage --- diff --git a/docs/integrations/bitbucketCloud/discovery.md b/docs/integrations/bitbucketCloud/discovery.md index 9560c5e06b..e0fab954ac 100644 --- a/docs/integrations/bitbucketCloud/discovery.md +++ b/docs/integrations/bitbucketCloud/discovery.md @@ -2,7 +2,6 @@ id: discovery title: Bitbucket Cloud Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from repositories in Bitbucket Cloud --- diff --git a/docs/integrations/bitbucketCloud/locations.md b/docs/integrations/bitbucketCloud/locations.md index 9b08a79c63..f0a032353c 100644 --- a/docs/integrations/bitbucketCloud/locations.md +++ b/docs/integrations/bitbucketCloud/locations.md @@ -2,7 +2,6 @@ id: locations title: Bitbucket Cloud Locations sidebar_label: Locations -# prettier-ignore description: Integrating source code stored in Bitbucket Cloud into the Backstage catalog --- diff --git a/docs/integrations/bitbucketServer/discovery.md b/docs/integrations/bitbucketServer/discovery.md index 36282b1f48..350bc33aed 100644 --- a/docs/integrations/bitbucketServer/discovery.md +++ b/docs/integrations/bitbucketServer/discovery.md @@ -2,7 +2,6 @@ id: discovery title: Bitbucket Server Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from repositories in Bitbucket Server --- @@ -67,6 +66,7 @@ catalog: projectKey: '^apis-.*$' # optional; RegExp repoSlug: '^service-.*$' # optional; RegExp skipArchivedRepos: true # optional; boolean + validateLocationsExist: false # optional; boolean schedule: # same options as in SchedulerServiceTaskScheduleDefinition # supports cron, ISO duration, "human duration" as used in code frequency: { minutes: 30 } @@ -87,6 +87,10 @@ catalog: Regular expression used to filter results based on the repo slug. - **`skipArchivedRepos`** _(optional)_: Boolean flag to filter out archived repositories. +- **`validateLocationsExist`** _(optional)_: + Defaults to `false`. + Whether to validate locations that exist before emitting them. + This option avoids generating locations for catalog info files that do not exist in the source repository. - **`schedule`**: - **`frequency`**: How often you want the task to run. The system does its best to avoid overlapping invocations. diff --git a/docs/integrations/bitbucketServer/locations.md b/docs/integrations/bitbucketServer/locations.md index 7ff19b8b27..0c8b0e16b4 100644 --- a/docs/integrations/bitbucketServer/locations.md +++ b/docs/integrations/bitbucketServer/locations.md @@ -2,7 +2,6 @@ id: locations title: Bitbucket Server Locations sidebar_label: Locations -# prettier-ignore description: Integrating source code stored in Bitbucket Server into the Backstage catalog --- diff --git a/docs/integrations/datadog-rum/installation.md b/docs/integrations/datadog-rum/installation.md index 6659bec182..5b4fe8bd40 100644 --- a/docs/integrations/datadog-rum/installation.md +++ b/docs/integrations/datadog-rum/installation.md @@ -2,7 +2,6 @@ id: installation title: Datadog RUM Installation sidebar_label: Installation -# prettier-ignore description: Adding Datadog Real User Monitoring (RUM) to Your App --- diff --git a/docs/integrations/gerrit/discovery.md b/docs/integrations/gerrit/discovery.md index dbbc7ba7a4..06fb144e50 100644 --- a/docs/integrations/gerrit/discovery.md +++ b/docs/integrations/gerrit/discovery.md @@ -2,7 +2,6 @@ id: discovery title: Gerrit Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from Gerrit repositories --- diff --git a/docs/integrations/gitea/discovery.md b/docs/integrations/gitea/discovery.md index 6cae169b58..ce8ad9d360 100644 --- a/docs/integrations/gitea/discovery.md +++ b/docs/integrations/gitea/discovery.md @@ -30,7 +30,7 @@ backend.add(import('@backstage/plugin-catalog-backend-module-gitea')); ## Configuration -To use the discovery processor, you'll need a Gitea integration +To use the discovery provider, you'll need a Gitea integration [set up](locations.md). Then you can add any number of providers. ```yaml diff --git a/docs/integrations/github/discovery.md b/docs/integrations/github/discovery.md index 01567a7191..5dd13a7bec 100644 --- a/docs/integrations/github/discovery.md +++ b/docs/integrations/github/discovery.md @@ -2,7 +2,6 @@ id: discovery title: GitHub Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from repositories in a GitHub organization --- diff --git a/docs/integrations/github/org.md b/docs/integrations/github/org.md index 3d0e0a4221..b054daf343 100644 --- a/docs/integrations/github/org.md +++ b/docs/integrations/github/org.md @@ -2,7 +2,6 @@ id: org title: GitHub Organizational Data sidebar_label: Org Data -# prettier-ignore description: Importing users and groups from a GitHub organization into Backstage --- diff --git a/docs/integrations/gitlab/discovery.md b/docs/integrations/gitlab/discovery.md index de35fbcc96..e0ededd1fa 100644 --- a/docs/integrations/gitlab/discovery.md +++ b/docs/integrations/gitlab/discovery.md @@ -2,7 +2,6 @@ id: discovery title: GitLab Discovery sidebar_label: Discovery -# prettier-ignore description: Automatically discovering catalog entities from repositories in GitLab --- diff --git a/docs/integrations/google-cloud-storage/locations.md b/docs/integrations/google-cloud-storage/locations.md index 1f0334ff17..99bba9feb7 100644 --- a/docs/integrations/google-cloud-storage/locations.md +++ b/docs/integrations/google-cloud-storage/locations.md @@ -2,7 +2,6 @@ id: locations sidebar_label: Locations title: Google Cloud Storage Locations -# prettier-ignore description: Setting up an integration with Google Cloud Storage --- diff --git a/docs/integrations/index.md b/docs/integrations/index.md index b090d6d77e..00463a810f 100644 --- a/docs/integrations/index.md +++ b/docs/integrations/index.md @@ -2,8 +2,7 @@ id: index title: Integrations sidebar_label: Overview -# prettier-ignore -description: Configuring Backstage to read or publish data with external providers using integrations +description: Configuring Backstage to read or publish data with external providers using integrations --- Integrations allow Backstage to read or publish data using external providers diff --git a/docs/integrations/ldap/org--old.md b/docs/integrations/ldap/org--old.md index 448e9bbed1..03862d8625 100644 --- a/docs/integrations/ldap/org--old.md +++ b/docs/integrations/ldap/org--old.md @@ -2,7 +2,6 @@ id: org--old title: LDAP Organizational Data sidebar_label: Org Data -# prettier-ignore description: Setting up ingestion of organizational data from LDAP --- diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index 9913cf0729..8adc81184a 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -2,7 +2,6 @@ id: org title: LDAP Organizational Data sidebar_label: Org Data -# prettier-ignore description: Setting up ingestion of organizational data from LDAP --- diff --git a/docs/notifications/index.md b/docs/notifications/index.md index 2af8879ac0..c31d2716e4 100644 --- a/docs/notifications/index.md +++ b/docs/notifications/index.md @@ -158,6 +158,21 @@ You can customize the origin names shown in the UI by passing an object where th Each notification processor will receive its own row in the settings page, where the user can enable or disable notifications from that processor. +### Automatic notification cleanup + +Notifications are deleted automatically after a certain period of time to prevent the database from growing indefinitely +and to keep the user interface clean. The default retention period is set to 1 year, meaning that notifications older +than that will be deleted automatically. + +The retention period can be configured by setting the `notifications.retention` in the `app-config.yaml` file. + +```yaml +notifications: + retention: 1y +``` + +If the retention is set to false, notifications will not be automatically deleted. + ## Additional info An example of a backend plugin sending notifications can be found in the [`@backstage/plugin-scaffolder-backend-module-notifications` package](https://github.com/backstage/backstage/tree/master/plugins/scaffolder-backend-module-notifications). diff --git a/docs/notifications/notificationSettings.png b/docs/notifications/notificationSettings.png index cdad63d764..e135a3f194 100644 Binary files a/docs/notifications/notificationSettings.png and b/docs/notifications/notificationSettings.png differ diff --git a/docs/overview/adopting.md b/docs/overview/adopting.md index a6053d0f85..e924cfbeb0 100644 --- a/docs/overview/adopting.md +++ b/docs/overview/adopting.md @@ -1,7 +1,6 @@ --- id: adopting title: Strategies for adopting -# prettier-ignore description: Documentation on some general best practices that have been key to Backstage's success inside Spotify --- diff --git a/docs/overview/background.md b/docs/overview/background.md index 5e59967b21..147fe8ce7b 100644 --- a/docs/overview/background.md +++ b/docs/overview/background.md @@ -1,7 +1,6 @@ --- id: background title: The Spotify Story -# prettier-ignore description: Backstage was born out of necessity at Spotify. We found that as we grew, our infrastructure was becoming more fragmented, our engineers less productive. --- diff --git a/docs/overview/vision.md b/docs/overview/vision.md index f6d6af90dd..aab5eaa9b8 100644 --- a/docs/overview/vision.md +++ b/docs/overview/vision.md @@ -1,7 +1,6 @@ --- id: vision title: Vision -# prettier-ignore description: Goal is to provide engineers with the best developer experience in the world --- diff --git a/docs/overview/what-is-backstage.md b/docs/overview/what-is-backstage.md index ef452d5d15..fa1c75de44 100644 --- a/docs/overview/what-is-backstage.md +++ b/docs/overview/what-is-backstage.md @@ -1,7 +1,6 @@ --- id: what-is-backstage title: What is Backstage? -# prettier-ignore description: Backstage is an open source framework for building developer portals. Powered by a centralized software catalog, Backstage restores order to your microservices and infrastructure --- diff --git a/docs/permissions/frontend-integration.md b/docs/permissions/frontend-integration.md index 1e83f8ad7d..d5329eca96 100644 --- a/docs/permissions/frontend-integration.md +++ b/docs/permissions/frontend-integration.md @@ -4,6 +4,10 @@ title: Frontend Integration description: How to place your Backstage frontend components behind authorization --- +:::info +Starting with a [fresh Backstage installation](https://backstage.io/docs/getting-started/), the code example below is already implemented, so there are no actual code changes required. +::: + Now that we understand how to [author a permission policy](./writing-a-policy.md), let's consider cases where we'll need to supplement our policy with authorization checks on the frontend. In most cases, actual functionality that live within various plugins will already have been placed behind authorization by the plugin authors. The permission backend will use your permission policy to return an authorization result, and the plugin frontend will correspondingly show/hide/disable the relevant UI component. @@ -13,25 +17,20 @@ However, there are some cases where the integrator needs to supplement the polic If your Backstage permission policy may return a `DENY` for users requesting the `catalogEntityCreatePermission`, it may make sense, for example, to remove access to the `/catalog-import` page entirely: ```tsx title="packages/app/src/App.tsx" -/* highlight-add-start */ import { RequirePermission } from '@backstage/plugin-permission-react'; -import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common'; -/* highlight-add-end */ +import { catalogEntityCreatePermission } from '@backstage/plugin-catalog-common/alpha'; const routes = ( - {/* highlight-remove-next-line */} - } /> - {/* highlight-add-start */} } /> - {/* highlight-add-end */} {/* ... */} ); diff --git a/docs/permissions/writing-a-policy.md b/docs/permissions/writing-a-policy.md index a479684287..576afcac21 100644 --- a/docs/permissions/writing-a-policy.md +++ b/docs/permissions/writing-a-policy.md @@ -92,6 +92,13 @@ import { catalogEntityDeletePermission, } from '@backstage/plugin-catalog-common/alpha'; /* highlight-add-end */ +import { + PermissionPolicy, + PolicyQuery, + /* highlight-add-next-line */ + PolicyQueryUser, +} from '@backstage/plugin-permission-node'; + class CustomPermissionPolicy implements PermissionPolicy { /* highlight-remove-next-line */ @@ -143,8 +150,8 @@ import { PolicyDecision, /* highlight-remove-next-line */ isPermission, - isResourcePermission, /* highlight-add-next-line */ + isResourcePermission, } from '@backstage/plugin-permission-common'; import { catalogConditions, @@ -155,6 +162,11 @@ import { catalogEntityDeletePermission, } from '@backstage/plugin-catalog-common/alpha'; /* highlight-remove-end */ +import { + PermissionPolicy, + PolicyQuery, + PolicyQueryUser, +} from '@backstage/plugin-permission-node'; class CustomPermissionPolicy implements PermissionPolicy { async handle( diff --git a/docs/plugins/call-existing-api.md b/docs/plugins/call-existing-api.md index f8cfe23275..35a6d8d599 100644 --- a/docs/plugins/call-existing-api.md +++ b/docs/plugins/call-existing-api.md @@ -1,7 +1,6 @@ --- id: call-existing-api title: Call Existing API -# prettier-ignore description: Describes the various options that Backstage frontend plugins have, in communicating with service APIs that already exist --- diff --git a/docs/plugins/composability.md b/docs/plugins/composability.md index a0e0e2d5e6..d6c9abc98f 100644 --- a/docs/plugins/composability.md +++ b/docs/plugins/composability.md @@ -1,7 +1,6 @@ --- id: composability title: Composability System -# prettier-ignore description: Documentation for the Backstage plugin composability APIs. --- diff --git a/docs/plugins/observability.md b/docs/plugins/observability.md index c294001606..7803d90bd5 100644 --- a/docs/plugins/observability.md +++ b/docs/plugins/observability.md @@ -1,7 +1,6 @@ --- id: observability title: Observability -# prettier-ignore description: Adding Observability to Your Plugin --- diff --git a/docs/references/glossary.md b/docs/references/glossary.md index 906260e710..8d3c072685 100644 --- a/docs/references/glossary.md +++ b/docs/references/glossary.md @@ -1,7 +1,6 @@ --- id: glossary title: Glossary -# prettier-ignore description: List of terms, abbreviations, and phrases used in Backstage, together with their explanations. --- @@ -11,7 +10,7 @@ A [token](#token) that gives access to perform actions on behalf of a user. It w ## Administrator -Someone responsible for installing and maintaining a Backstage [app](#app) for an organization. A [user role](#user-role). +Someone responsible for installing, configuring, and maintaining a Backstage [app](#app) for an organization. A [user role](#user-role). ## API (catalog plugin) @@ -21,6 +20,14 @@ An [entity](#entity) representing a schema that two [components](#component) use An installed instance of Backstage. An app can be local, intended for a single development group or individual developer, or organizational, for use by an entire enterprise. +## Authentication + +The process of verifying the identity of a user, system, or entity attempting to access a resource, system, or network. It answers the question: "Are you who you claim to be?" See [this Wikipedia article](https://en.wikipedia.org/wiki/Authentication) for more details. + +## Authorization + +The process of determining what an authenticated user or system is allowed to do within a system, application, or resource. It comes after authentication, and answers the question: "What are you allowed to access or do?" It involves assigning specific privileges or access rights or roles to the user. See [this Wikipedia article](https://en.wikipedia.org/wiki/Authorization) for more details. + ## Authorization Code A type of [OAuth flow](#oauth) used by confidential and public clients to get an [access token](#access-token). See [the OAuth docs](https://oauth.net/2/grant-types/authorization-code/) for more details. @@ -43,7 +50,7 @@ The actual framework that Backstage [plugins](#plugin) sit on. This spans both t ## Catalog -1. The core Backstage plugin that handle ingestion and display of your organizations software products. +1. The core Backstage plugin that handles ingestion and display of your organization's software products. 2. An organization's portfolio of software products managed in Backstage. @@ -51,16 +58,12 @@ The actual framework that Backstage [plugins](#plugin) sit on. This spans both t A set of technologies that "empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach." ([CNCF Cloud Native Definition v1.0](https://github.com/cncf/toc/blob/main/DEFINITION.md)). -## Cloud Native Computing Foundation +## Cloud Native Computing Foundation (AKA CNCF) A foundation dedicated to the promotion and advancement of [Cloud Native Computing](#Cloud-Native-Computing). The mission of the Cloud Native Computing Foundation (CNCF) is "to make cloud native computing ubiquitous" ([CNCF Charter](https://github.com/cncf/foundation/blob/main/charter.md)). CNCF is part of the [Linux Foundation](https://www.linuxfoundation.org/). -## CNCF - -Cloud Native Computing Foundation. - ## Code Grant [OAuth](#oauth) flow where the client receives an [authorization code](#code) that is passed to the backend to be exchanged for an [access token](#access-token) and possibly a [refresh token](#refresh-token). @@ -99,9 +102,9 @@ An executable or package file with all of the necessary information required to ## Developer -1. Someone who writes code and develops software. +1. A professional who designs, builds, tests, deploys, and maintains software applications and systems. Developers essentially turn ideas or requirements into functional digital products. -2. A [user role](#user-role) defined as someone who uses a Backstage [app](#app). Might or might not actually be a software developer. +2. A [user role](#user-role) defined as someone who creates, modifies, or uses a Backstage [app](#app). Might or might not actually be a software developer. ## Developer Portal @@ -109,15 +112,21 @@ A centralized system comprising a user interface and database used to facilitate ## Document (search plugin) -An abstract concept representing something that can be found by searching for it. A document can represent a software entity, a TechDocs page, etc. Documents are made up of metadata fields, at a minimum -- a title, text, and location (as in a URL). +1. A piece of information or data that is recorded on some medium for the purpose of storing and conveying information. + +2. An abstract concept representing something that can be found by searching for it. A document can represent a software entity, a TechDocs page, etc. Documents are made up of metadata fields, at a minimum -- a title, body (text), and location (as in a URL). ## Domain -An area that relates systems or entities to a business unit. See [the catalog docs](https://backstage.io/docs/features/software-catalog/system-model) for more information. +1. A collection of systems that share terminology, domain models, metrics, KPIs, business purpose, or documentation; that is, it forms a bounded context. + +2. An area that relates systems or entities to a business unit. See [the catalog docs](https://backstage.io/docs/features/software-catalog/system-model) for more information. ## Entity -What is cataloged in the Backstage Software Catalog. An entity is identified by a unique combination of [kind](#Kind), [namespace](#Namespace), and name. See [the catalog docs](https://backstage.io/docs/features/software-catalog/system-model) for more information. +1. Something that exists as a separate and distinct unit. Its existence can be real or abstract, physical or conceptual, persistent or ephemeral. + +2. What is cataloged in the Backstage Software Catalog. An entity is identified by a unique combination of [kind](#Kind), [namespace](#Namespace), and name. See [the catalog docs](https://backstage.io/docs/features/software-catalog/system-model) for more information. ## Evaluator @@ -125,11 +134,13 @@ Someone who assesses whether Backstage is a suitable solution for their organiza ## ID Token -A [JWT](#jwt) used to prove a user's identity, containing for example the user's email. Part of [OpenID Connect](#openid-connect). +A security token used in authentication processes, primarily defined by the [OpenID Connect (OIDC) standard](#openid-connect). Its main purpose is to prove that a user has been successfully authenticated by an identity provider. + +See [JSON Web Token](#json-web-token). ## Index (search plugin) -An index is a collection of [documents](#documents) of a given type. +A collection of [documents](#documents) of a given type. ## Indexer (search plugin) @@ -139,11 +150,9 @@ A write stream of [documents](#documents). Someone who develops one or more plugins that enable Backstage to interoperate with another software system. A [user role](#user-role). -## JWT +## JSON Web Token (AKA JWT) -JSON Web Token. - -A popular JSON based token format that is commonly encrypted and/or signed, see [the Wikipedia article](https://en.wikipedia.org/wiki/JSON_Web_Token) for more details. +A popular, compact, and self-contained open standard for securely transmitting information between parties as a JSON object. It is commonly used to verify a user's identity [authentication](#authentication) and permissions [authorization](#authorization). Each JWT consists of a header, payload, and digital signature separated by dots. While often encrypted, JWTs are always signed for integrity. This standard is a key component of [OpenID Connect](#openid-connect). For more details, see [the Wikipedia article](https://en.wikipedia.org/wiki/JSON_Web_Token). ## Kind @@ -159,7 +168,7 @@ A core Backstage plugin enabling a service owner-focused view of Kubernetes reso ## Local Package -One of the [packages](#package) within a [monorepo](#monorepo). These package may or may not also be published to a [package registry](#package-registry). +One of the [packages](#package) within a [monorepo](#monorepo). A package may or may not also be published to a [package registry](#package-registry). ## Monorepo @@ -173,11 +182,11 @@ An optional attribute that can be used to organize [entities](#entity). ## Objective -A high level goal of a [user role](#User-Role) interacting with Backstage. Some goals of the _administrator_ user role, for example, are to maintain an instance ("app") of Backstage; to add and update functionality via plugins; and to troubleshoot issues. +A high-level goal of a [user role](#User-Role) interacting with Backstage. Some goals of the _administrator_ user role, for example, are to maintain an instance ("app") of Backstage; to add and update functionality via plugins; and to troubleshoot issues. ## OAuth -Refers to: OAuth 2.0, a standard protocol for authorization. See [oauth.net/2/](https://oauth.net/2/). +Refers to: OAuth 2.0, a standard protocol and framework for granting third-party applications access to their data on other websites or services without sharing their passwords. See [oauth.net/2/](https://oauth.net/2/). ## Offline Access @@ -203,6 +212,10 @@ A service that hosts [packages](#package). The most prominent example is [NPM](h The declared role of a package, see [package roles](../tooling/cli/02-build-system.md#package-roles). +## Permission + +Specific rules or settings that define the level of access and types of actions that a user, group, or system process is allowed to perform on a particular resource. They are a core component of authorization that determine "what you can do" after you've been authenticated. Permissions are properties of objects or resources. Closely related to [Privilege](#privilege) (the terms are often used interchangeably). + ## Permission (core Backstage plugin) A core Backstage plugin and framework that allows restriction of actions to specific users. See [their docs](https://backstage.io/docs/permissions/overview) for more information. @@ -231,6 +244,10 @@ A specific response to a user's request to perform an action on a list of [resou A separate browser window opened on top of the previous one. +## Privilege + +Specific rules or settings that define what a user or process is allowed to do within the system, often relating to system-wide operations or capabilities. Privileges are properties of a subject, such as a user account or process, and represent a higher-level authority or right to perform certain security-critical functions. Closely related to [Permission](#permission) (the terms are often used interchangeably). + ## Procedure (use cases) A set of actions that accomplish a goal, usually as part of a [use case](#Use-Case). A procedure can be high-level, containing other procedures, or can be as simple as a single [task](#Task). @@ -241,9 +258,7 @@ An abstraction layer between a search engine and the [Backstage Search](#search) ## Refresh token -A special token that an [OAuth](#oauth) client can use to get a new [access token](#access-token) when the latter expires. - -https://oauth.net/2/refresh-tokens/ +A special token that an [OAuth](#oauth) client can use to get a new [access token](#access-token) when the latter expires. See [OAuth Refresh Tokens](https://oauth.net/2/refresh-tokens/) for details. ## Resource (catalog plugin) @@ -291,7 +306,7 @@ A "skeleton" software project created and managed in the Backstage Software Temp ## System (catalog plugin) -A system is a collection of [entities](#entity) that cooperate to perform a function. A system generally provides one or a few public APIs and consists of a handful of components, resources and private APIs. See [the catalog docs](https://backstage.io/docs/features/software-catalog/system-model) for more information. +A collection of [entities](#entity) that cooperate to perform a function. A system generally provides one or a few public APIs and consists of a handful of components, resources, and private or public APIs. See [the catalog docs](https://backstage.io/docs/features/software-catalog/system-model) for more information. ## Task (use cases) @@ -299,7 +314,7 @@ A low-level step-by-step [Procedure](#Procedure). ## TechDocs -A documentation solution that manages and generates a technical documentation from Markdown files stored with software component code. A core feature of Backstage. +A documentation solution that manages and generates technical documentation from Markdown files stored with software component code. A core feature of Backstage. ## Token @@ -307,8 +322,12 @@ A string containing information. ## Use Case -A purpose for which a [user role](#User-Role) interacts with Backstage. Related to [Objective](#objective): An objective is _what_ the user wants to do; a use case is _how_ the user does it. +A purpose for which a [user role](#User-Role) interacts with Backstage. Related to [Objective](#objective): An objective is _what_ the user wants to do, a use case is _how_ the user does it. + +## User + +Any consumer of Backstage or Backstage products/applications. Includes individuals like employees and contractors, as well as software that interacts with the backend through an API or acts as a proxy for a person by operating the user interface. ## User Role -A class of Backstage user for purposes of analyzing [use cases](#use-case). One of: evaluator; administrator; developer; integrator; and contributor. +A class of Backstage user for purposes of analyzing [use cases](#use-case). One of: [evaluator](#evaluator); [administrator](#administrator); [developer](#developer); [integrator](#integrator); and [contributor](#contributor). diff --git a/docs/releases/v1.40.0-changelog.md b/docs/releases/v1.40.0-changelog.md new file mode 100644 index 0000000000..e5b65ab8ed --- /dev/null +++ b/docs/releases/v1.40.0-changelog.md @@ -0,0 +1,2771 @@ +# Release v1.40.0 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.40.0](https://backstage.github.io/upgrade-helper/?to=1.40.0) + +## @backstage/plugin-scaffolder-backend@2.0.0 + +### Major Changes + +- 33394db: **BREAKING CHANGES** + + Removal of deprecated re-exports from module packages. + + The following functions have been re-exported from the `scaffolder-backend` plugin for quite some time, and now it's time to clean them up. They've been moved as follows: + + - `createPublishAzureAction` should be imported from `@backstage/plugin-scaffolder-backend-module-azure` instead. + + - `createPublishBitbucketCloudAction` should be imported from `@backstage/plugin-scaffolder-backend-module-bitbucket-cloud` instead. + + - `createPublishBitbucketServerAction` and `createPublishBitbucketServerPullRequestAction` can be imported from `@backstage/plugin-scaffolder-backend-module-bitbucket-server` instead. + + - `createPublishBitbucketAction` should be imported from `@backstage/plugin-scaffolder-backend-module-bitbucket` instead. + + - `createPublishGerritAction` and `createPublishGerritReviewAction` can be imported from `@backstage/plugin-scaffolder-backend-module-gerrit` instead. + + - `createGithubActionsDispatchAction`, `createGithubDeployKeyAction`, `createGithubEnvironmentAction`, `createGithubIssuesLabelAction`, `CreateGithubPullRequestActionOptions`, `createGithubRepoCreateAction`, `createGithubRepoPushAction`, `createGithubWebhookAction`, and `createPublishGithubAction` can be imported from `@backstage/plugin-scaffolder-backend-module-github` instead. + + - `createPublishGitlabAction` should be imported from `@backstage/plugin-scaffolder-backend-module-gitlab` instead. + + - `ActionContext`. `createTemplateAction`, `executeShellCommand`, `ExecuteShellCommandOptions`, `fetchContents`, `TaskSecrets`, and `TemplateAction` should be imported from `@backstage/plugin-scaffolder-node` instead. + + - `ScaffolderEntitiesProcessor` should be imported from `@backstage/plugin-catalog-backend-module-scaffolder-entity-model` instead. + +- a8fcf04: **BREAKING ALPHA**: The `/alpha` export no longer exports the plugin. Please use `import('@backstage/plugin-scaffolder-backend')` instead as this has been removed. + + **BREAKING CHANGES**: The old `createRouter` function which was used in the old backend system has been removed along with the `RouterOptions` type. + +- 73b94d7: **BREAKING CHANGES** + + The following functions have been re-exported from the `scaffolder-backend` plugin for quite some time, and now it's time to clean them up. They've been moved as follows: + + - `SerializedTask`, `SerializedTaskEvent`, `TaskBroker`, `TaskBrokerDispatchOptions`, `TaskBrokerDispatchResult`, `TaskCompletionState`, `TaskContext`, `TaskEventType`, `TaskStatus`, `TemplateFilter`, and `TemplateGlobal` should be imported from `@backstage/plugin-scaffolder-node` instead. + + - The deprecated `copyWithoutRender` option has been removed from `fetch:template` action. You should rename the option to `copyWithoutTemplating` instead. + +- 5863b04: **BREAKING CHANGES** + + - The `createBuiltinActions` method has been removed, as this should no longer be needed with the new backend system route, and was only useful when passing the default list of actions again in the old backend system. You should be able to rely on the default behaviour of the new backend system which is to merge the actions. + + - The `createCatalogRegisterAction` and `createFetchCatalogEntityAction` actions no longer require an `AuthService`, and now accepts a `CatalogService` instead of `CatalogClient`. + + Unless you're providing your own override action to the default, this should be a non-breaking change. + + You can migrate using the following if you're getting typescript errors: + + ```ts + import { catalogServiceRef } from '@backstage/plugin-catalog-node'; + import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; + + export const myModule = createBackendModule({ + pluginId: 'scaffolder', + moduleId: 'test', + register({ registerInit }) { + registerInit({ + deps: { + scaffolder: scaffolderActionsExtensionPoint, + catalog: catalogServiceRef, + }, + async init({ scaffolder, catalog }) { + scaffolder.addActions( + createCatalogRegisterAction({ + catalog, + }), + createFetchCatalogEntityAction({ + catalog, + integrations, + }), + ); + }, + }); + }, + }); + ``` + +### Minor Changes + +- 73b94d7: **DEPRECATIONS** + + The following types and implementations have been deprecated, either because they're no longer relevant, or because upcoming changes to the `scaffolder-backend` after `2.0.0` will influence the changes to these API surfaces. + + - `CreateWorkerOptions` + - `DatabaseTaskStore` + - `DatabaseTaskStoreOptions` + - `TaskManager` + - `TaskStoreCreateTaskOptions` + - `TaskStoreCreateTaskResult` + - `TaskStoreEmitOptions` + - `TaskStoreListEventsOptions` + - `TaskStoreRecoverTaskOptions` + - `TaskStoreShutDownTaskOptions` + + There is no current path off deprecation, these types are going to be removed and rethought with a better way to define workers in the new backend system. + +### Patch Changes + +- 89a941d: Migrating to latest action format + +- 023629e: Enable usage of secrets within 'each' step of software templates. For example, you can now structure your `each` step like this: + + each: + [ + { name: "Service1", token: "${{ secrets.token1 }}" }, + { name: "Service2", token: "${{ secrets.token2 }}" }, + ] + +- e92e481: Add tests for Scaffolder + +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.2 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.10 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10 + - @backstage/plugin-scaffolder-backend-module-github@0.8.0 + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.10 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.10 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.11 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/backend-defaults@0.11.0 + +### Minor Changes + +- 3ccb7fc: Enhanced error handling in the auditor service factory to pass errors as objects. Aligned WinstonRootAuditorService with the default service factory's error handling. + +### Patch Changes + +- 1220cf8: Added new rate limit middleware to allow rate limiting requests to the backend + + If you are using the `configure` callback of the root HTTP router service and do NOT call `applyDefaults()` inside it, please see [the relevant changes](https://github.com/backstage/backstage/pull/28708/files#diff-86ad1b6a694dd250823aee39d410428dd837c9d9a04ca8c33bd1081fbe3f22af) that were made, to see if you want to apply them as well to your custom configuration. + Rate limiting can be turned on by adding the following configuration to `app-config.yaml`: + + ```yaml + backend: + rateLimit: + window: 6s + incomingRequestLimit: 100 + ``` + + Plugin specific rate limiting can be configured by adding the following configuration to `app-config.yaml`: + + ```yaml + backend: + rateLimit: + global: false # This will disable the global rate limiting + plugin: + catalog: + window: 6s + incomingRequestLimit: 100 + ``` + +- c999c25: Added some default implementations for the experimental `ActionsService` and `ActionsRegistryService` under `/alpha` that allow registration of actions for a particular plugin. + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-app-api@1.2.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-node@0.10.1 + +## @backstage/backend-plugin-api@1.4.0 + +### Minor Changes + +- 664c07a: Added `actionsRegistry` and `actions` experimental services to `/alpha` to allow registration of distributed actions from plugins, and the ability to invoke these actions. You can use these services by including them like the following: + + ```ts + import { + actionsRegistryServiceRef, + actionsServiceRef, + } from '@backstage/backend-plugin-api/alpha'; + + createBackendPlugin({ + pluginId: 'test-plugin', + register({ registerInit }) { + registerInit({ + deps: { + actions: actionsServiceRef, + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actions, actionsRegistry }) { + actionsRegistry.register({ + ..., + }); + + await actions.invoke(...); + }, + }); + }, + }); + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + +## @backstage/backend-test-utils@1.6.0 + +### Minor Changes + +- 6dfb7be: Added `mockServices.permissions()` that can return actual results. +- c999c25: Added an `actionsRegistryServiceMock` and `actionsServiceMock` to `/alpha` export for the experimental services. + + This allows you to write tests for your actions by doing something similar to the following: + + ```ts + import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha'; + + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock({ + entities: [ + ... + ], + }); + + createGetCatalogEntityAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:get-catalog-entity', + input: { name: 'test' }, + }), + ).resolves.toEqual(...) + ``` + +### Patch Changes + +- 12c1fd4: Make the `user` credentials mock behave more like production +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-app-api@1.2.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/canon@0.5.0 + +### Minor Changes + +- 621fac9: We are updating the default size of the Button component in Canon to be small instead of medium. +- a842554: We set the default size for IconButton in Canon to be small instead of medium. +- 35fd51d: Move TextField component to use react Aria under the hood. Introducing a new FieldLabel component to help build custom fields. +- 78204a2: **Breaking** We are adding a new as prop on the Heading and Text component to make it easier to change the component tag. We are removing the render prop in favour of the as prop. +- c49e335: TextField in Canon now has multiple label sizes as well as the capacity to hide label and description but still make them available for screen readers. +- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using <Grid.Root /> instead of just . + +### Patch Changes + +- 44df879: Add min-width: 0; by default on every Flex components in Canon to help support truncated texts inside flex elements. +- ee6ffe6: Fix styling for the title4 prop on the Heading component in Canon. +- f2f814a: Added a render prop to the Button component in Canon to use it as a link. +- 98f02a6: Add new Switch component in Canon. +- c94f8e0: The filter input in menu comboboxes should now always use the full width of the menu it's in. +- 269316d: Remove leftover console.log from Container component. + +## @backstage/cli@0.33.0 + +### Minor Changes + +- eef0e83: Internal update to promote the modular CLI entrypoint to stable. + +### Patch Changes + +- d07fe35: Added user feedback when opening config docs in browser. The command now clearly indicates what it's doing and provides fallback instructions if the browser fails to open. +- ce70439: The `BACKSTAGE_CLI_EXPERIMENTAL_BUILD_CACHE` flag has been removed. Existing users are encouraged to switch to `EXPERIMENTAL_RSPACK` instead. +- 1d8f00b: Switched to using the `ModuleFederationPlugin` from `@module-federation/enhanced/rspack` for Rspack, rather than the built-in one. +- 2b9633f: The experimental `FORCE_REACT_DEVELOPMENT` flag has been removed. +- d8c4a54: Only use the caching Jest module loader for frontend packages in order to avoid breaking real ESM module imports. +- d6d63c7: Updating the scaffolder action boilerplate to use new `zod` schema +- e36e855: Added `backstage.pluginId` field in `package.json` to all default plugin package templates for the `new` command. +- 1bab255: Internal refactor to combine alpha `build` and `start` modules. +- 713e957: fix: merge eslint reports when using json format +- 8a0164c: Fix an issue where some commands were not usable because of missing dist files +- Updated dependencies + - @backstage/eslint-plugin@0.1.11 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.1 + +## @backstage/create-app@0.7.0 + +### Minor Changes + +- 30474c4: Add .cache directory to shipped gitignore. + +### Patch Changes + +- d57a6f7: Bumped create-app version. +- f628f44: Bumped create-app version. +- 9c9faf2: Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.15 + +## @backstage/repo-tools@0.14.0 + +### Minor Changes + +- bf9a173: Add support for caching the per-package output from the `package-docs` command. + +### Patch Changes + +- 4bff5d0: Fixed a bug where linting would fail with the generated clients when defining top-level `enum` schema values. +- 2d20024: Fix an issue where errors were not printed to console when running `backstage-repo-tools schema openapi generate` without the `--watch` flag. +- e643ee4: Add missing highlight language for the `package-docs` command. +- c83cd8b: Fixed some circular or otherwise unclear imports +- a372bf1: Updated dependency `@electric-sql/pglite` to `^0.3.0`. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + +## @backstage/plugin-catalog@1.31.0 + +### Minor Changes + +- 406acb6: Add support to customize the about card icon links via `EntityIconLinkBlueprint` and provide a default catalog view catalog source, launch scaffolder template and read techdocs docs icon links extensions. + + **BREAKING ALPHA** + + The `Scaffolder` launch template and `TechDocs` read documentation icons have been extracted from the default `Catalog` about card links and are now provided respectively by the `Scaffolder` and `TechDocs` plugins in the new frontend system. It means that they will not be available unless you install the `TechDocs` and `Scaffolder` plugins. Also If you are using translation for these icon link titles other than the default, you should now translate them using the scaffolder translation reference or the TechDocs translation reference (the translation keys are still the same, `aboutCard.viewTechdocs` and `aboutCard.launchTemplate`). + +- ec7b35d: Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into another entities TechDocs in conjunction with `backstage.io/techdocs-entity`. + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/plugin-search-react@1.9.1 + - @backstage/integration-react@1.2.8 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-scaffolder-common@1.5.11 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-catalog-backend@2.1.0 + +### Minor Changes + +- 2e7adf0: Implement the action `get-catalog-entity` with the `ActionsRegistry` + +### Patch Changes + +- 2cac8b0: You can now specify an optional value when applying the `HAS_LABEL` permission rule, similar to the `HAS_ANNOTATION` permission rule. +- c83cd8b: Fixed some circular or otherwise unclear imports +- 4654a78: Update `refresh_state_references.id` to be a big int +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.0 + +### Minor Changes + +- 8a150bf: **BREAKING**: `BitbucketCloudEntityProvider` now accepts a `CatalogService` instead of a `CatalogApi`. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.0 + +### Minor Changes + +- eb8b3aa: Add validateLocationsExist option to avoid generating locations for catalog-info.yaml files that do not exist in the source repository. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-backend-module-github@0.10.0 + +### Minor Changes + +- 7c0dfb0: GitHub organization now matches in a case-insensitive manner when processing events. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-catalog-backend@2.1.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.0 + +### Minor Changes + +- 42bb3b8: **BREAKING CHANGE**: User and Group discovery will default to ingesting all users in sub groups that belong to the specified root group in config. Disable by setting `restrictUsersToGroup: true` in app-config under your module settings. + +### Patch Changes + +- 57a0bad: Implement retry for GitLab API calls to handle rate limiting +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-react@1.19.0 + +### Minor Changes + +- 406acb6: Introduces a new `EntityIconLinkBlueprint` that customizes the `About` card icon links on the `Catalog` entity page. + + The blueprint currently accepts a `useProps` hook as `param` and this function returns the following props that will be passed to the icon link component: + + | Name | Description | Type | Default Value | + | ---------- | --------------------------------------------------- | ------------- | ------------- | + | `icon` | The icon to display. | `JSX.Element` | N/A | + | `label` | The label for the element. | `string` | N/A | + | `title` | The title for the element. | `string` | N/A | + | `disabled` | Whether the element is disabled. | `boolean` | `false` | + | `href` | The URL to navigate to when the element is clicked. | `string` | N/A | + | `onClick` | A function to call when the element is clicked. | `() => void` | N/A | + + Here is an usage example: + + ```tsx + import { EntityIconLinkBlueprint } from '@backstage/plugin-catalog-react/alpha'; + //... + + EntityIconLinkBlueprint.make({ + name: 'my-icon-link', + params: { + useProps() { + const { t } = useTranslationRef(myIconLinkTranslationRef); + return { + label: t('myIconLink.label'), + icon: , + href: '/my-plugin', + }; + }, + }, + }); + ``` + + Additionally, the `app-config.yaml` file allows you to override some of the default icon link parameters, including `label` and `title` values. Here's how to set them: + + ```yaml + app: + extensions: + - entity-icon-link:my-plugin/my-icon-link: + config: + label: 'My Custom Icon Link label' + ``` + + Finally, you can disable all links if you want to hide the About card header completely (useful, for example, when links are displayed on separate cards). The header is hidden when no icon links extensions are enabled. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/integration-react@1.2.8 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/frontend-test-utils@0.3.3 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-events-backend-module-kafka@0.1.0 + +### Minor Changes + +- b034b9d: Adds a new module `kafka` for plugin-events-backend + + The module introduces the `KafkaConsumerClient` which creates a Kafka client used to establish consumer connections. It also provides the `KafkaConsumingEventPublisher`, a consumer that subscribes to configured Kafka topics and publishes received messages to the Event Service. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-mcp-actions-backend@0.1.0 + +### Minor Changes + +- 4ed0fb6: Initial implementation of an `mcp-actions` backend + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder@1.32.0 + +### Minor Changes + +- 6c972fe: Added information about the `entityRef` and `taskId` to the analytics events whenever is possible. +- 3c59ece: **New Frontend System Only:** + The `Scaffolder` plugin is now responsible for providing an entity icon link extension to launch templates from the catalog entity page. + +### Patch Changes + +- d781b33: render details for composite property schemas +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- b00c160: Remove React import form notification and scaffolder plugin +- 95a1d72: Added appropriate message when global templating function metadata is absent. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-scaffolder-react@1.17.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/integration-react@1.2.8 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-backend-module-github@0.8.0 + +### Minor Changes + +- 5863b04: **BREAKING CHANGES** + + The `createGithubEnvironmentAction` action no longer requires an `AuthService`, and now accepts a `CatalogService` instead of `CatalogClient`. + + Unless you're providing your own override action to the default, this should be a non-breaking change. + + You can migrate using the following if you're getting typescript errors: + + ```ts + import { catalogServiceRef } from '@backstage/plugin-catalog-node'; + import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; + + export const myModule = createBackendModule({ + pluginId: 'scaffolder', + moduleId: 'test', + register({ registerInit }) { + registerInit({ + deps: { + scaffolder: scaffolderActionsExtensionPoint, + catalog: catalogServiceRef, + }, + async init({ scaffolder, catalog }) { + scaffolder.addActions( + createGithubEnvironmentAction({ + catalog, + }), + ); + }, + }); + }, + }); + ``` + +### Patch Changes + +- 575c76b: Migrate to using new actions +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-node@0.9.0 + +### Minor Changes + +- 5863b04: **BREAKING CHANGES** + + The legacy methods to define `createTemplateActions` have been replaced with the new native `zod` approaches for defining input and output schemas. + + You can migrate actions that look like the following with the below examples: + + ```ts + // really old legacy json schema + createTemplateAction<{ repoUrl: string }, { repoOutput: string }>({ + id: 'test', + schema: { + input: { + type: 'object' + required: ['repoUrl'] + properties: { + repoUrl: { + type: 'string', + description: 'repository url description' + } + } + } + } + }); + + // old zod method + createTemplateAction({ + id: 'test' + schema: { + input: { + repoUrl: z.string({ description: 'repository url description' }) + } + } + }) + + // new method: + createTemplateAction({ + id: 'test', + schema: { + input: { + repoUrl: z => z.string({ description: 'repository url description' }) + } + } + }) + + // or for more complex zod types like unions + createTemplateAction({ + id: 'test', + schema: { + input: z => z.object({ + repoUrl: z.string({ description: 'repository url description' }) + }) + } + }) + ``` + + This breaking change also means that `logStream` has been removed entirely from `ActionsContext`, and that the `logger` is now just a `LoggerService` implementation instead. There is no replacement for the `logStream`, if you wish to still keep using a `logStream` we recommend that you create your own stream that writes to `ctx.logger` instead. + +### Patch Changes + +- e89d7b6: Use `LoggerService` instead of `Logger`. This is a non-breaking change, as the `LoggerService` is a subset of the `Logger` interface. +- 9c8ff0c: Update pull request creation filter to include .gitignore files in the created pull request +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.0 + +### Minor Changes + +- 3cea7ee: **BREAKING CHANGES** + + Because of the removal of the `logStream` property to the `ActionsContext` this has been removed from the `createMockActionContext` method. + + You can remove this as it's no longer supported in the scaffolder actions. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-test-utils@1.6.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-react@1.17.0 + +### Minor Changes + +- 6c972fe: Added information about the `entityRef` and `taskId` to the analytics events whenever is possible. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-techdocs@1.13.0 + +### Minor Changes + +- 3c59ece: **New Frontend System Only:** + The `TechDocs` plugin is now responsible for providing an entity icon link extension to read documentation from the catalog entity page. +- ec7b35d: Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into another entities TechDocs in conjunction with `backstage.io/techdocs-entity`. + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- 9dde3ba: Improved Keyboard accessibility in techdocs. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/plugin-search-react@1.9.1 + - @backstage/integration-react@1.2.8 + - @backstage/plugin-auth-react@0.1.16 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/theme@0.6.6 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-techdocs-react@1.3.0 + +### Minor Changes + +- ec7b35d: Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into another entities TechDocs in conjunction with `backstage.io/techdocs-entity`. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/version-bridge@1.0.11 + +## @backstage/app-defaults@1.6.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/core-app-api@1.17.1 + - @backstage/theme@0.6.6 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/backend-app-api@1.2.4 + +### Patch Changes + +- bb9a501: Fixed a bug where occasionally the initialization order of multiple modules consuming a single extension point could happen in the wrong order. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/backend-dynamic-feature-service@0.7.1 + +### Patch Changes + +- c83cd8b: Fixed some circular or otherwise unclear imports +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/plugin-catalog-backend@2.1.0 + - @backstage/plugin-events-backend@0.5.3 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/backend-openapi-utils@0.5.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/catalog-client@1.10.1 + +### Patch Changes + +- 22fad0d: Fixed `CatalogClient` error responses for `refreshEntity` and `addLocation`. +- Updated dependencies + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + +## @backstage/core-app-api@1.17.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.8 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/core-compat-api@0.4.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/version-bridge@1.0.11 + +## @backstage/core-components@0.17.3 + +### Patch Changes + +- 6232160: table actions header support i18n +- Updated dependencies + - @backstage/core-plugin-api@1.10.8 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/version-bridge@1.0.11 + +## @backstage/core-plugin-api@1.10.8 + +### Patch Changes + +- c83cd8b: Fixed some circular or otherwise unclear imports +- 0169b23: Internal tweak to avoid circular dependencies +- Updated dependencies + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/dev-utils@1.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/app-defaults@1.6.3 + - @backstage/integration-react@1.2.8 + - @backstage/catalog-model@1.7.4 + - @backstage/core-app-api@1.17.1 + - @backstage/theme@0.6.6 + +## @backstage/eslint-plugin@0.1.11 + +### Patch Changes + +- 098ef95: Fix custom rules package scanning performance. +- 063b2d3: Added new eslint rule to restrict mixed plugin imports. + + New rule `@backstage/no-mixed-plugin-imports` disallows mixed imports between plugins that are mixing + the backstage architecture. This rule forces that: + + - No imports from frontend plugins to backend plugins or other frontend plugins. + - No imports from backend plugins to frontend plugins or other backend plugins. + - No imports from common plugins to frontend or backend plugins. + + The current recommended configuration is giving a warning for mixed imports. This is to be changed in + the future to an error so please adjust your workspace accordingly. + +## @backstage/frontend-app-api@0.11.3 + +### Patch Changes + +- 0169b23: Internal tweak to avoid circular dependencies +- c38c9e8: Implemented support for the `plugin.info()` method in specialized apps with a default resolved for `package.json` and `catalog-info.yaml`. The default resolution logic can be overridden via the `pluginInfoResolver` option to `createSpecializedApp`, and plugin-specific overrides can be applied via the new `app.pluginOverrides` key in static configuration. +- Updated dependencies + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/frontend-defaults@0.2.3 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/frontend-defaults@0.2.3 + +### Patch Changes + +- fa5650c: Forwarded the new `pluginInfoResolver` option for `createApp`. +- Updated dependencies + - @backstage/plugin-app@0.1.10 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/frontend-app-api@0.11.3 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/frontend-dynamic-feature-loader@0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/config@1.3.2 + +## @backstage/frontend-plugin-api@0.10.3 + +### Patch Changes + +- 0169b23: Internal tweak to avoid circular dependencies + +- 9e3868f: Added a new optional `info` option to `createFrontendPlugin` that lets you provide a loaders for different sources of metadata information about the plugin. + + There are two available loaders. The first one is `info.packageJson`, which can be used to point to a `package.json` file for the plugin. This is recommended for any plugin that is defined within its own package, especially all plugins that are published to a package registry. Typical usage looks like this: + + ```ts + export default createFrontendPlugin({ + pluginId: '...', + info: { + packageJson: () => import('../package.json'), + }, + }); + ``` + + The second loader is `info.manifest`, which can be used to point to an opaque plugin manifest. This **MUST ONLY** be used by plugins that are intended for use within a single organization. Plugins that are published to an open package registry should **NOT** use this loader. The loader is useful for adding additional internal metadata associated with the plugin, and it is up to the Backstage app to decide how these manifests are parsed and used. The default manifest parser in an app created with `createApp` from `@backstage/frontend-defaults` is able to parse the default `catalog-info.yaml` format and built-in fields such as `spec.owner`. + + Typical usage looks like this: + + ```ts + export default createFrontendPlugin({ + pluginId: '...', + info: { + manifest: () => import('../catalog-info.yaml'), + }, + }); + ``` + +- 6f48f71: Added a new `useAppNode` hook, which can be used to get a reference to the `AppNode` from by the closest `ExtensionBoundary`. + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/frontend-test-utils@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-app@0.1.10 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/frontend-app-api@0.11.3 + - @backstage/config@1.3.2 + - @backstage/test-utils@1.7.9 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/integration-react@1.2.8 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.8 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + +## @techdocs/cli@1.9.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/plugin-techdocs-node@1.13.4 + +## @backstage/test-utils@1.7.9 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.8 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-api-docs@0.12.8 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/plugin-catalog@1.31.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-app@0.1.10 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/integration-react@1.2.8 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-app-backend@0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34 + +## @backstage/plugin-app-node@0.1.34 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config-loader@1.10.1 + +## @backstage/plugin-app-visualizer@0.1.20 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + +## @backstage/plugin-auth-backend@0.25.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.4 + +### Patch Changes + +- c83cd8b: Fixed some circular or otherwise unclear imports +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + - @backstage/plugin-auth-backend@0.25.1 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-backend@0.25.1 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.4 + +### Patch Changes + +- b25977f: Updated dependency `@davidzemon/passport-okta-oauth` to `^0.0.6`. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + +## @backstage/plugin-auth-node@0.6.4 + +### Patch Changes + +- 0169b23: Internal tweak to avoid circular dependencies +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-react@0.1.16 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + +## @backstage/plugin-catalog-backend-module-aws@0.4.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-catalog-backend-module-azure@0.3.6 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-catalog-backend-module-github@0.10.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-gitlab@0.7.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-catalog-backend@2.1.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-catalog-backend-module-ldap@0.11.6 + +### Patch Changes + +- 087d51d: Export LDAP vendor types and instances for testing custom transformers + +- f07b0ad: Added the ability to configure disabling one side of the relations tree with LDAP. + + Groups have a `member` attribute and users have a `memberOf` attribute, however these can drift out of sync in some LDAP installations, leaving weird states in the Catalog as we collate these results together and deduplicate them. + + You can chose to optionally disable one side of these relationships, or even both by setting the respective mapping to `null` in your `app-config.yaml` for your groups and/or users: + + ```yaml + catalog: + providers: + ldapOrg: + default: + target: ldaps://ds.example.net + bind: + dn: uid=ldap-reader-user,ou=people,ou=example,dc=example,dc=net + secret: ${LDAP_SECRET} + users: + - dn: ou=people,ou=example,dc=example,dc=net + options: + filter: (uid=*) + map: + # this ensures that outgoing memberships from users is ignored + memberOf: null + groups: + - dn: ou=access,ou=groups,ou=example,dc=example,dc=net + options: + filter: (&(objectClass=some-group-class)(!(groupType=email))) + map: + description: l + set: + metadata.customField: 'hello' + map: + # this ensures that outgoing memberships from groups is ignored + members: null + ``` + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-logs@0.1.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.1.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-backend-module-msgraph@0.7.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.11 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.8 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-catalog-graph@0.4.20 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog-import@0.13.1 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- 5d7c539: Catalog import plugin full support i18n +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/integration-react@1.2.8 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-node@1.17.1 + +### Patch Changes + +- 0169b23: Internal tweak to avoid circular dependencies +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.18 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + +## @backstage/plugin-config-schema@0.1.69 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-devtools@0.1.28 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/plugin-devtools-common@0.1.16 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-devtools-backend@0.5.6 + +### Patch Changes + +- 9a99735: Removed the usage of `permissionIntegrationRouter` in favor of using the new `coreServices.permissionsRegistry` +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-devtools-common@0.1.16 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + +## @backstage/plugin-events-backend@0.5.3 + +### Patch Changes + +- c83cd8b: Fixed some circular or otherwise unclear imports +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-module-azure@0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-module-gerrit@0.2.21 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-module-github@0.4.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-module-gitlab@0.3.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-module-google-pubsub@0.1.1 + +### Patch Changes + +- f983e99: Add an `EventConsumingGooglePubSubPublisher`, for pushing Backstage events to pubsub +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-backend-test-utils@0.1.45 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-events-node@0.4.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-gateway-backend@1.0.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-home@0.8.9 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- 0ebad54: Fixed the `WelcomeTitle` to properly default to the previous value of `inherit` +- cef60db: Home plugin support i18n +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-home-react@0.1.27 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-compat-api@0.4.3 + - @backstage/theme@0.6.6 + +## @backstage/plugin-home-react@0.1.27 + +### Patch Changes + +- c83cd8b: Fixed some circular or otherwise unclear imports +- cef60db: Home plugin support i18n +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + +## @backstage/plugin-kubernetes@0.12.8 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- 3ea5d1b: chore(deps): Update deprecated xterm to new package under @xterm +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/plugin-kubernetes-react@0.5.8 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-kubernetes-backend@0.19.7 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-kubernetes-node@0.3.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + +## @backstage/plugin-kubernetes-cluster@0.0.26 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/plugin-kubernetes-react@0.5.8 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-kubernetes-node@0.3.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-kubernetes-react@0.5.8 + +### Patch Changes + +- 3ea5d1b: chore(deps): Update deprecated xterm to new package under @xterm +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-notifications@0.5.6 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- b00c160: Remove React import form notification and scaffolder plugin +- 1fb5f06: Adds ability for user to turn on/off notifications for specific topics within an origin. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-notifications-common@0.0.9 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.14 + +## @backstage/plugin-notifications-backend@0.5.7 + +### Patch Changes + +- 41d4d6e: Notifications are now automatically deleted after 1 year by default. + + There is a new scheduled task that runs every 24 hours to delete notifications older than 1 year. + This can be configured by setting the `notifications.retention` in the `app-config.yaml` file. + + ```yaml + notifications: + retention: 1y + ``` + + If the retention is set to false, notifications will not be automatically deleted. + +- 8a150bf: Internal changes to switch to the non-alpha `catalogServiceRef` + +- 1fb5f06: Adds ability for user to turn on/off notifications for specific topics within an origin. + +- ef9ab82: Notifications API will now return user as null always for broadcast notifications + +- Updated dependencies + - @backstage/plugin-notifications-common@0.0.9 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-notifications-node@0.2.16 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-signals-node@0.1.21 + +## @backstage/plugin-notifications-backend-module-email@0.3.10 + +### Patch Changes + +- 8a150bf: Internal changes to switch to the non-alpha `catalogServiceRef` +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-notifications-common@0.0.9 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-notifications-node@0.2.16 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + +## @backstage/plugin-notifications-backend-module-slack@0.1.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-notifications-common@0.0.9 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-notifications-node@0.2.16 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-notifications-common@0.0.9 + +### Patch Changes + +- 1fb5f06: Adds ability for user to turn on/off notifications for specific topics within an origin. +- Updated dependencies + - @backstage/config@1.3.2 + +## @backstage/plugin-notifications-node@0.2.16 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-notifications-common@0.0.9 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-signals-node@0.1.21 + +## @backstage/plugin-org@0.6.40 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- 4fe364f: Org plugin support i18n +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-org-react@0.1.39 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/catalog-client@1.10.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + +## @backstage/plugin-permission-backend@0.7.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + +## @backstage/plugin-permission-node@0.10.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-permission-react@0.4.35 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.8 + - @backstage/config@1.3.2 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-proxy-backend@0.6.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/types@1.2.1 + - @backstage/plugin-proxy-node@0.1.5 + +## @backstage/plugin-proxy-node@0.1.5 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.10 + +### Patch Changes + +- e89d7b6: Migrating `azure` actions to using the new `zod` schema format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.11 + +### Patch Changes + +- 7f710d2: Migrating `bitbucket` actions to use the new `zod` format +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10 + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10 + +### Patch Changes + +- ca9fdc0: Migrate `bitbucket-cloud` to new actions format +- 9c8ff0c: Update pull request creation filter to include .gitignore files in the created pull request +- 280611d: Fix `bitbucketCloudBranchRestrictions` API calls to accept null to prevent 400 errors for some branch restriction kinds defined. +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10 + +### Patch Changes + +- d8169fc: Migrate the actions to the new format +- 9c8ff0c: Update pull request creation filter to include .gitignore files in the created pull request +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.10 + +### Patch Changes + +- 4a86bca: Migrate actions to new format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.11 + +### Patch Changes + +- 0b2bbf1: Migrate using new actions format +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.10 + +### Patch Changes + +- e24b29b: Migrating to use new format for actions +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.10 + +### Patch Changes + +- ed41017: Migrate to new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.2 + +### Patch Changes + +- 063b2d3: Fixed dependency to frontend package from tests +- a296637: Migrate to new action format +- 3d6493a: Support merge request labels in publish:gitlab:merge-request +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.11 + +### Patch Changes + +- 1fb5f06: Adds ability for user to turn on/off notifications for specific topics within an origin. +- 3f56115: Removed `octokit` dependency as it was not being used +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/plugin-notifications-common@0.0.9 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-notifications-node@0.2.16 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.10 + +### Patch Changes + +- a579693: Migrate to new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.10 + +### Patch Changes + +- 6c6fb4a: Migrate to new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.11 + +### Patch Changes + +- b392a34: Migrate to new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node-test-utils@0.3.0 + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-search@1.4.27 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/plugin-search-react@1.9.1 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend@2.0.3 + +### Patch Changes + +- c83cd8b: Fixed some circular or otherwise unclear imports +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-catalog@0.3.5 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-elasticsearch@1.7.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-explore@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-pg@0.5.45 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.10 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-techdocs@0.4.3 + +### Patch Changes + +- b47ec38: Exports the default document collator for use in document transformation during search indexing. +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-techdocs-node@1.13.4 + +## @backstage/plugin-search-backend-node@1.3.12 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-react@1.9.1 + +### Patch Changes + +- 869fa46: SearchBar clear button support i18n +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-signals@0.0.20 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.14 + +## @backstage/plugin-signals-backend@0.3.5 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-signals-node@0.1.21 + +## @backstage/plugin-signals-node@0.1.21 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-signals-react@0.0.14 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.8 + - @backstage/types@1.2.1 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.49 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.0 + - @backstage/plugin-catalog@1.31.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/plugin-search-react@1.9.1 + - @backstage/integration-react@1.2.8 + - @backstage/core-app-api@1.17.1 + - @backstage/test-utils@1.7.9 + +## @backstage/plugin-techdocs-backend@2.0.3 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1 + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.3 + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-techdocs-node@1.13.4 + +## @backstage/plugin-techdocs-common@0.1.1 + +### Patch Changes + +- ec7b35d: Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into another entities TechDocs in conjunction with `backstage.io/techdocs-entity`. + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.25 + +### Patch Changes + +- 9dde3ba: Improved Keyboard accessibility in techdocs. +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/integration-react@1.2.8 + - @backstage/integration@1.17.0 + +## @backstage/plugin-techdocs-node@1.13.4 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-common@0.1.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-user-settings@0.8.23 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- ab6d3dd: Add some translation to user-setting plugin +- c83cd8b: Fixed some circular or otherwise unclear imports +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-app-api@1.17.1 + - @backstage/core-compat-api@0.4.3 + - @backstage/errors@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.14 + - @backstage/plugin-user-settings-common@0.0.1 + +## @backstage/plugin-user-settings-backend@0.3.3 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-node@0.1.21 + - @backstage/plugin-user-settings-common@0.0.1 + +## example-app@0.2.110 + +### Patch Changes + +- Updated dependencies + - @backstage/canon@0.5.0 + - @backstage/core-components@0.17.3 + - @backstage/cli@0.33.0 + - @backstage/plugin-scaffolder-react@1.17.0 + - @backstage/plugin-scaffolder@1.32.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18 + - @backstage/plugin-catalog-import@0.13.1 + - @backstage/plugin-catalog-graph@0.4.20 + - @backstage/plugin-notifications@0.5.6 + - @backstage/plugin-user-settings@0.8.23 + - @backstage/plugin-kubernetes@0.12.8 + - @backstage/plugin-api-docs@0.12.8 + - @backstage/plugin-devtools@0.1.28 + - @backstage/plugin-techdocs@1.13.0 + - @backstage/plugin-catalog@1.31.0 + - @backstage/plugin-signals@0.0.20 + - @backstage/plugin-search@1.4.27 + - @backstage/plugin-home@0.8.9 + - @backstage/plugin-org@0.6.40 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-app-api@0.11.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/plugin-search-react@1.9.1 + - @backstage/app-defaults@1.6.3 + - @backstage/integration-react@1.2.8 + - @backstage/plugin-auth-react@0.1.16 + - @backstage/plugin-kubernetes-cluster@0.0.26 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-search-common@1.2.18 + +## example-app-next@0.0.24 + +### Patch Changes + +- Updated dependencies + - @backstage/canon@0.5.0 + - @backstage/core-components@0.17.3 + - @backstage/cli@0.33.0 + - @backstage/plugin-scaffolder-react@1.17.0 + - @backstage/plugin-scaffolder@1.32.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18 + - @backstage/plugin-app-visualizer@0.1.20 + - @backstage/plugin-catalog-import@0.13.1 + - @backstage/plugin-catalog-graph@0.4.20 + - @backstage/plugin-notifications@0.5.6 + - @backstage/plugin-user-settings@0.8.23 + - @backstage/plugin-kubernetes@0.12.8 + - @backstage/plugin-api-docs@0.12.8 + - @backstage/plugin-techdocs@1.13.0 + - @backstage/plugin-catalog@1.31.0 + - @backstage/plugin-signals@0.0.20 + - @backstage/plugin-search@1.4.27 + - @backstage/plugin-home@0.8.9 + - @backstage/plugin-app@0.1.10 + - @backstage/plugin-org@0.6.40 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/frontend-app-api@0.11.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/frontend-defaults@0.2.3 + - @backstage/plugin-search-react@1.9.1 + - @backstage/app-defaults@1.6.3 + - @backstage/integration-react@1.2.8 + - @backstage/plugin-auth-react@0.1.16 + - @backstage/plugin-kubernetes-cluster@0.0.26 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-compat-api@0.4.3 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-search-common@1.2.18 + +## app-next-example-plugin@0.0.24 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/frontend-plugin-api@0.10.3 + +## example-backend@0.0.39 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-notifications-backend@0.5.7 + - @backstage/plugin-scaffolder-backend-module-github@0.8.0 + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-scaffolder-backend@2.0.0 + - @backstage/plugin-catalog-backend@2.1.0 + - @backstage/plugin-devtools-backend@0.5.6 + - @backstage/plugin-mcp-actions-backend@0.1.0 + - @backstage/plugin-events-backend@0.5.3 + - @backstage/plugin-search-backend@2.0.3 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.11 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-search-backend-module-techdocs@0.4.3 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-kubernetes-backend@0.19.7 + - @backstage/plugin-search-backend-module-catalog@0.3.5 + - @backstage/plugin-techdocs-backend@2.0.3 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-app-backend@0.5.3 + - @backstage/plugin-auth-backend@0.25.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3 + - @backstage/plugin-catalog-backend-module-openapi@0.2.11 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1 + - @backstage/plugin-permission-backend@0.7.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-proxy-backend@0.6.3 + - @backstage/plugin-search-backend-module-explore@0.3.3 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-signals-backend@0.3.5 + +## e2e-test@0.2.29 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.0 + - @backstage/cli-common@0.1.15 + - @backstage/errors@1.2.7 + +## @internal/frontend@0.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @internal/scaffolder@0.0.10 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.17.0 + - @backstage/frontend-plugin-api@0.10.3 + +## techdocs-cli-embedded-app@0.2.109 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/cli@0.33.0 + - @backstage/plugin-techdocs@1.13.0 + - @backstage/plugin-catalog@1.31.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/app-defaults@1.6.3 + - @backstage/integration-react@1.2.8 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/test-utils@1.7.9 + - @backstage/theme@0.6.6 + +## yarn-plugin-backstage@0.0.6 + +### Patch Changes + +- a0f9e4e: added functionality so that adding or updating a backstage dependency to a package would maintain the "backstage:^" placeholder for the version. +- Updated dependencies + - @backstage/cli-common@0.1.15 + - @backstage/release-manifests@0.0.13 + +## @internal/plugin-todo-list@1.0.40 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + +## @internal/plugin-todo-list-backend@1.0.40 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 diff --git a/docs/releases/v1.40.0-next.0-changelog.md b/docs/releases/v1.40.0-next.0-changelog.md new file mode 100644 index 0000000000..10ed249086 --- /dev/null +++ b/docs/releases/v1.40.0-next.0-changelog.md @@ -0,0 +1,1490 @@ +# Release v1.40.0-next.0 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.40.0-next.0](https://backstage.github.io/upgrade-helper/?to=1.40.0-next.0) + +## @backstage/backend-plugin-api@1.4.0-next.0 + +### Minor Changes + +- 664c07a: Added `coreServices.actionsRegistry` and `coreServices.actions` to allow registration of distributed actions from plugins, and the ability to invoke these actions + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + +## @backstage/backend-test-utils@1.6.0-next.0 + +### Minor Changes + +- c999c25: Added mock implementations for `ActionsService` and `ActionsRegistryService` + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/backend-app-api@1.2.4-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/canon@0.5.0-next.0 + +### Minor Changes + +- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using <Grid.Root /> instead of just . + +### Patch Changes + +- 269316d: Remove leftover console.log from Container component. + +## @backstage/create-app@0.7.0-next.0 + +### Minor Changes + +- 30474c4: Add .cache directory to shipped gitignore. + +## @backstage/repo-tools@0.14.0-next.0 + +### Minor Changes + +- bf9a173: Add support for caching the per-package output from the `package-docs` command. + +### Patch Changes + +- 2d20024: Fix an issue where errors were not printed to console when running `backstage-repo-tools schema openapi generate` without the `--watch` flag. +- e643ee4: Add missing highlight language for the `package-docs` command. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + +## @backstage/plugin-catalog@1.31.0-next.0 + +### Minor Changes + +- ec7b35d: Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into another entities TechDocs in conjunction with `backstage.io/techdocs-entity`. + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/plugin-techdocs@1.13.0-next.0 + +### Minor Changes + +- ec7b35d: Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into another entities TechDocs in conjunction with `backstage.io/techdocs-entity`. + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/plugin-techdocs-react@1.3.0-next.0 + +### Minor Changes + +- ec7b35d: Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into another entities TechDocs in conjunction with `backstage.io/techdocs-entity`. + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + +## @backstage/backend-app-api@1.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/backend-defaults@0.10.1-next.0 + +### Patch Changes + +- c999c25: Added some default implementations for the `ActionsService` and `ActionsRegistryService` that allow registration of actions for a particular plugin. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-app-api@1.2.4-next.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + +## @backstage/backend-dynamic-feature-service@0.7.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/plugin-catalog-backend@2.0.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-events-backend@0.5.3-next.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + - @backstage/backend-openapi-utils@0.5.4-next.0 + - @backstage/plugin-app-node@0.1.34-next.0 + +## @backstage/backend-openapi-utils@0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/core-compat-api@0.4.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/dev-utils@1.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/frontend-app-api@0.11.3-next.0 + +### Patch Changes + +- c38c9e8: Implemented support for the `plugin.info()` method in specialized apps with a default resolved for `package.json` and `catalog-info.yaml`. The default resolution logic can be overridden via the `pluginInfoResolver` option to `createSpecializedApp`, and plugin-specific overrides can be applied via the new `app.pluginOverrides` key in static configuration. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/frontend-defaults@0.2.3-next.0 + +## @backstage/frontend-defaults@0.2.3-next.0 + +### Patch Changes + +- fa5650c: Forwarded the new `pluginInfoResolver` option for `createApp`. +- Updated dependencies + - @backstage/plugin-app@0.1.10-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/frontend-app-api@0.11.3-next.0 + +## @backstage/frontend-dynamic-feature-loader@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + +## @backstage/frontend-plugin-api@0.10.3-next.0 + +### Patch Changes + +- 9e3868f: Added a new optional `info` option to `createFrontendPlugin` that lets you provide a loaders for different sources of metadata information about the plugin. + + There are two available loaders. The first one is `info.packageJson`, which can be used to point to a `package.json` file for the plugin. This is recommended for any plugin that is defined within its own package, especially all plugins that are published to a package registry. Typical usage looks like this: + + ```ts + export default createFrontendPlugin({ + pluginId: '...', + info: { + packageJson: () => import('../package.json'), + }, + }); + ``` + + The second loader is `info.manifest`, which can be used to point to an opaque plugin manifest. This **MUST ONLY** be used by plugins that are intended for use within a single organization. Plugins that are published to an open package registry should **NOT** use this loader. The loader is useful for adding additional internal metadata associated with the plugin, and it is up to the Backstage app to decide how these manifests are parsed and used. The default manifest parser in an app created with `createApp` from `@backstage/frontend-defaults` is able to parse the default `catalog-info.yaml` format and built-in fields such as `spec.owner`. + + Typical usage looks like this: + + ```ts + export default createFrontendPlugin({ + pluginId: '...', + info: { + manifest: () => import('../catalog-info.yaml'), + }, + }); + ``` + +- 6f48f71: Added a new `useAppNode` hook, which can be used to get a reference to the `AppNode` from by the closest `ExtensionBoundary`. + +## @backstage/frontend-test-utils@0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-app@0.1.10-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/frontend-app-api@0.11.3-next.0 + +## @techdocs/cli@1.9.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-techdocs-node@1.13.4-next.0 + +## @backstage/plugin-api-docs@0.12.8-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/plugin-catalog@1.31.0-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-app@0.1.10-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/plugin-app-backend@0.5.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-app-node@0.1.34-next.0 + +## @backstage/plugin-app-node@0.1.34-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/config-loader@1.10.1 + +## @backstage/plugin-app-visualizer@0.1.20-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + +## @backstage/plugin-auth-backend@0.25.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-backend@0.25.1-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-github-provider@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-backend@0.25.1-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-auth-node@0.6.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-catalog-backend@2.0.1-next.0 + +### Patch Changes + +- 4654a78: Update `refresh_state_references.id` to be a big int +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + - @backstage/backend-openapi-utils@0.5.4-next.0 + +## @backstage/plugin-catalog-backend-module-aws@0.4.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-azure@0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/backend-openapi-utils@0.5.4-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.4.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.4.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-github@0.9.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-backend-module-github@0.9.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-catalog-backend-module-gitlab@0.6.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-backend-module-gitlab@0.6.7-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-catalog-backend-module-ldap@0.11.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-logs@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-catalog-backend-module-msgraph@0.7.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + +## @backstage/plugin-catalog-graph@0.4.20-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-catalog-import@0.13.1-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/plugin-catalog-node@1.17.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + +## @backstage/plugin-catalog-react@1.18.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/frontend-test-utils@0.3.3-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + +## @backstage/plugin-devtools@0.1.28-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + +## @backstage/plugin-devtools-backend@0.5.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-permission-node@0.10.1-next.0 + +## @backstage/plugin-events-backend@0.5.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/backend-openapi-utils@0.5.4-next.0 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-backend-module-azure@0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-backend-module-gerrit@0.2.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-backend-module-github@0.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-backend-module-gitlab@0.3.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-backend-module-google-pubsub@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-backend-test-utils@0.1.45-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-events-node@0.4.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-gateway-backend@1.0.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-home@0.8.9-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-kubernetes@0.12.8-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-kubernetes-backend@0.19.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-kubernetes-node@0.3.1-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + +## @backstage/plugin-kubernetes-cluster@0.0.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-kubernetes-node@0.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-notifications@0.5.6-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + +## @backstage/plugin-notifications-backend@0.5.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/plugin-notifications-node@0.2.16-next.0 + - @backstage/plugin-signals-node@0.1.21-next.0 + +## @backstage/plugin-notifications-backend-module-email@0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-notifications-node@0.2.16-next.0 + +## @backstage/plugin-notifications-backend-module-slack@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-notifications-node@0.2.16-next.0 + +## @backstage/plugin-notifications-node@0.2.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-signals-node@0.1.21-next.0 + +## @backstage/plugin-org@0.6.40-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-org-react@0.1.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-permission-backend@0.7.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + +## @backstage/plugin-permission-node@0.10.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + +## @backstage/plugin-proxy-backend@0.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-proxy-node@0.1.5-next.0 + +## @backstage/plugin-proxy-node@0.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder@1.31.1-next.0 + +### Patch Changes + +- d781b33: render details for composite property schemas +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-scaffolder-react@1.16.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/plugin-scaffolder-backend@1.33.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.0 + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.2-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.11-next.0 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.10-next.0 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.10-next.0 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.10-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.7.2-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.0 + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.0 + +### Patch Changes + +- 9c8ff0c: Update pull request creation filter to include .gitignore files in the created pull request +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.0 + +### Patch Changes + +- 9c8ff0c: Update pull request creation filter to include .gitignore files in the created pull request +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-github@0.7.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.2-next.0 + +### Patch Changes + +- 3d6493a: Support merge request labels in publish:gitlab:merge-request +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-notifications-node@0.2.16-next.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-scaffolder-node-test-utils@0.2.3-next.0 + +## @backstage/plugin-scaffolder-node@0.8.3-next.0 + +### Patch Changes + +- 9c8ff0c: Update pull request creation filter to include .gitignore files in the created pull request +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-node-test-utils@0.2.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/backend-test-utils@1.6.0-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-scaffolder-react@1.16.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-search@1.4.27-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/plugin-search-react@1.9.1-next.0 + +## @backstage/plugin-search-backend@2.0.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + - @backstage/backend-openapi-utils@0.5.4-next.0 + +## @backstage/plugin-search-backend-module-catalog@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + +## @backstage/plugin-search-backend-module-elasticsearch@1.7.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + +## @backstage/plugin-search-backend-module-explore@0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + +## @backstage/plugin-search-backend-module-pg@0.5.45-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + +## @backstage/plugin-search-backend-module-techdocs@0.4.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-techdocs-node@1.13.4-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + +## @backstage/plugin-search-backend-node@1.3.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-search-react@1.9.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + +## @backstage/plugin-signals@0.0.20-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + +## @backstage/plugin-signals-backend@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/plugin-signals-node@0.1.21-next.0 + +## @backstage/plugin-signals-node@0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.49-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.0-next.0 + - @backstage/plugin-catalog@1.31.0-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/plugin-techdocs-backend@2.0.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-common@0.1.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-techdocs-node@1.13.4-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.0 + +## @backstage/plugin-techdocs-common@0.1.1-next.0 + +### Patch Changes + +- ec7b35d: Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into another entities TechDocs in conjunction with `backstage.io/techdocs-entity`. + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/integration-react@1.2.7 + +## @backstage/plugin-techdocs-node@1.13.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs-common@0.1.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + +## @backstage/plugin-user-settings@0.8.23-next.0 + +### Patch Changes + +- 18c64e9: Added the `info.packageJson` option to the plugin instance for the new frontend system. +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.0 + +## @backstage/plugin-user-settings-backend@0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-signals-node@0.1.21-next.0 + +## example-app@0.2.110-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.31.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.0 + - @backstage/plugin-catalog-import@0.13.1-next.0 + - @backstage/plugin-catalog-graph@0.4.20-next.0 + - @backstage/plugin-notifications@0.5.6-next.0 + - @backstage/plugin-user-settings@0.8.23-next.0 + - @backstage/plugin-kubernetes@0.12.8-next.0 + - @backstage/plugin-api-docs@0.12.8-next.0 + - @backstage/plugin-devtools@0.1.28-next.0 + - @backstage/plugin-techdocs@1.13.0-next.0 + - @backstage/plugin-catalog@1.31.0-next.0 + - @backstage/plugin-signals@0.0.20-next.0 + - @backstage/plugin-search@1.4.27-next.0 + - @backstage/plugin-home@0.8.9-next.0 + - @backstage/plugin-org@0.6.40-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/frontend-app-api@0.11.3-next.0 + - @backstage/canon@0.5.0-next.0 + - @backstage/plugin-scaffolder-react@1.16.1-next.0 + - @backstage/cli@0.32.1 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.0 + - @backstage/integration-react@1.2.7 + +## example-app-next@0.0.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.31.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.0 + - @backstage/plugin-app-visualizer@0.1.20-next.0 + - @backstage/plugin-catalog-import@0.13.1-next.0 + - @backstage/plugin-catalog-graph@0.4.20-next.0 + - @backstage/plugin-notifications@0.5.6-next.0 + - @backstage/plugin-user-settings@0.8.23-next.0 + - @backstage/plugin-kubernetes@0.12.8-next.0 + - @backstage/plugin-api-docs@0.12.8-next.0 + - @backstage/plugin-techdocs@1.13.0-next.0 + - @backstage/plugin-catalog@1.31.0-next.0 + - @backstage/plugin-signals@0.0.20-next.0 + - @backstage/plugin-search@1.4.27-next.0 + - @backstage/plugin-home@0.8.9-next.0 + - @backstage/plugin-app@0.1.10-next.0 + - @backstage/plugin-org@0.6.40-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/frontend-defaults@0.2.3-next.0 + - @backstage/frontend-app-api@0.11.3-next.0 + - @backstage/canon@0.5.0-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-scaffolder-react@1.16.1-next.0 + - @backstage/cli@0.32.1 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.0 + - @backstage/integration-react@1.2.7 + +## app-next-example-plugin@0.0.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + +## example-backend@0.0.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-events-backend@0.5.3-next.0 + - @backstage/plugin-search-backend@2.0.3-next.0 + - @backstage/plugin-scaffolder-backend@1.33.1-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.7.2-next.0 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.0 + - @backstage/plugin-techdocs-backend@2.0.3-next.0 + - @backstage/plugin-app-backend@0.5.3-next.0 + - @backstage/plugin-auth-backend@0.25.1-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4-next.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.2.11-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.0 + - @backstage/plugin-devtools-backend@0.5.6-next.0 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1-next.0 + - @backstage/plugin-kubernetes-backend@0.19.7-next.0 + - @backstage/plugin-notifications-backend@0.5.7-next.0 + - @backstage/plugin-permission-backend@0.7.1-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + - @backstage/plugin-proxy-backend@0.6.3-next.0 + - @backstage/plugin-search-backend-module-catalog@0.3.5-next.0 + - @backstage/plugin-search-backend-module-explore@0.3.3-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + - @backstage/plugin-signals-backend@0.3.5-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1-next.0 + +## e2e-test@0.2.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.0-next.0 + +## @internal/frontend@0.0.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + +## @internal/scaffolder@0.0.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-scaffolder-react@1.16.1-next.0 + +## techdocs-cli-embedded-app@0.2.109-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.0-next.0 + - @backstage/plugin-catalog@1.31.0-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/cli@0.32.1 + - @backstage/integration-react@1.2.7 + +## @internal/plugin-todo-list-backend@1.0.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 diff --git a/docs/releases/v1.40.0-next.1-changelog.md b/docs/releases/v1.40.0-next.1-changelog.md new file mode 100644 index 0000000000..7f1ae68b01 --- /dev/null +++ b/docs/releases/v1.40.0-next.1-changelog.md @@ -0,0 +1,1922 @@ +# Release v1.40.0-next.1 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.40.0-next.1](https://backstage.github.io/upgrade-helper/?to=1.40.0-next.1) + +## @backstage/plugin-scaffolder-backend@2.0.0-next.1 + +### Major Changes + +- 33394db: **BREAKING CHANGES** + + Removal of deprecated re-exports from module packages. + + The following functions have been re-exported from the `scaffolder-backend` plugin for quite some time, and now it's time to clean them up. They've been moved as follows: + + - `createPublishAzureAction` should be imported from `@backstage/plugin-scaffolder-backend-module-azure` instead. + + - `createPublishBitbucketCloudAction` should be imported from `@backstage/plugin-scaffolder-backend-module-bitbucket-cloud` instead. + + - `createPublishBitbucketServerAction` and `createPublishBitbucketServerPullRequestAction` can be imported from `@backstage/plugin-scaffolder-backend-module-bitbucket-server` instead. + + - `createPublishBitbucketAction` should be imported from `@backstage/plugin-scaffolder-backend-module-bitbucket` instead. + + - `createPublishGerritAction` and `createPublishGerritReviewAction` can be imported from `@backstage/plugin-scaffolder-backend-module-gerrit` instead. + + - `createGithubActionsDispatchAction`, `createGithubDeployKeyAction`, `createGithubEnvironmentAction`, `createGithubIssuesLabelAction`, `CreateGithubPullRequestActionOptions`, `createGithubRepoCreateAction`, `createGithubRepoPushAction`, `createGithubWebhookAction`, and `createPublishGithubAction` can be imported from `@backstage/plugin-scaffolder-backend-module-github` instead. + + - `createPublishGitlabAction` should be imported from `@backstage/plugin-scaffolder-backend-module-gitlab` instead. + + - `ActionContext`. `createTemplateAction`, `executeShellCommand`, `ExecuteShellCommandOptions`, `fetchContents`, `TaskSecrets`, and `TemplateAction` should be imported from `@backstage/plugin-scaffolder-node` instead. + + - `ScaffolderEntitiesProcessor` should be imported from `@backstage/plugin-catalog-backend-module-scaffolder-entity-model` instead. + +- a8fcf04: **BREAKING ALPHA**: The `/alpha` export no longer exports the plugin. Please use `import('@backstage/plugin-scaffolder-backend')` instead as this has been removed. + + **BREAKING CHANGES**: The old `createRouter` function which was used in the old backend system has been removed along with the `RouterOptions` type. + +- 73b94d7: **BREAKING CHANGES** + + The following functions have been re-exported from the `scaffolder-backend` plugin for quite some time, and now it's time to clean them up. They've been moved as follows: + + - `SerializedTask`, `SerializedTaskEvent`, `TaskBroker`, `TaskBrokerDispatchOptions`, `TaskBrokerDispatchResult`, `TaskCompletionState`, `TaskContext`, `TaskEventType`, `TaskStatus`, `TemplateFilter`, and `TemplateGlobal` should be imported from `@backstage/plugin-scaffolder-node` instead. + + - The deprecated `copyWithoutRender` option has been removed from `fetch:template` action. You should rename the option to `copyWithoutTemplating` instead. + +### Minor Changes + +- 73b94d7: **DEPRECATIONS** + + The following types and implementations have been deprecated, either because they're no longer relevant, or because upcoming changes to the `scaffolder-backend` after `2.0.0` will influence the changes to these API surfaces. + + - `CreateWorkerOptions` + - `DatabaseTaskStore` + - `DatabaseTaskStoreOptions` + - `TaskManager` + - `TaskStoreCreateTaskOptions` + - `TaskStoreCreateTaskResult` + - `TaskStoreEmitOptions` + - `TaskStoreListEventsOptions` + - `TaskStoreRecoverTaskOptions` + - `TaskStoreShutDownTaskOptions` + + There is no current path off deprecation, these types are going to be removed and rethought with a better way to define workers in the new backend system. + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.10-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.1 + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.1 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.10-next.1 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.10-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.11-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.7.2-next.1 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.2-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/canon@0.5.0-next.1 + +### Minor Changes + +- 621fac9: We are updating the default size of the Button component in Canon to be small instead of medium. +- a842554: We set the default size for IconButton in Canon to be small instead of medium. + +## @backstage/backend-app-api@1.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/backend-defaults@0.10.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-app-api@1.2.4-next.1 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/backend-dynamic-feature-service@0.7.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-backend@2.0.1-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34-next.1 + - @backstage/plugin-events-backend@0.5.3-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/backend-openapi-utils@0.5.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/backend-plugin-api@1.4.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/backend-test-utils@1.6.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-app-api@1.2.4-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/catalog-client@1.10.1-next.0 + +### Patch Changes + +- 22fad0d: Fixed `CatalogClient` error responses for `refreshEntity` and `addLocation`. +- Updated dependencies + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + +## @backstage/cli@0.32.2-next.0 + +### Patch Changes + +- ce70439: The `BACKSTAGE_CLI_EXPERIMENTAL_BUILD_CACHE` flag has been removed. Existing users are encouraged to switch to `EXPERIMENTAL_RSPACK` instead. +- 1d8f00b: Switched to using the `ModuleFederationPlugin` from `@module-federation/enhanced/rspack` for Rspack, rather than the built-in one. +- 2b9633f: The experimental `FORCE_REACT_DEVELOPMENT` flag has been removed. +- d8c4a54: Only use the caching Jest module loader for frontend packages in order to avoid breaking real ESM module imports. +- 1bab255: Internal refactor to combine alpha `build` and `start` modules. +- 713e957: fix: merge eslint reports when using json format +- Updated dependencies + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.1.10 + - @backstage/integration@1.17.0 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.1 + +## @backstage/core-compat-api@0.4.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/version-bridge@1.0.11 + +## @backstage/create-app@0.7.0-next.1 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.15 + +## @backstage/dev-utils@1.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/app-defaults@1.6.2 + - @backstage/catalog-model@1.7.4 + - @backstage/core-app-api@1.17.0 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + +## @backstage/repo-tools@0.14.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + +## @techdocs/cli@1.9.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/plugin-techdocs-node@1.13.4-next.1 + +## @backstage/plugin-api-docs@0.12.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.31.0-next.1 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-app-backend@0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34-next.1 + +## @backstage/plugin-app-node@0.1.34-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config-loader@1.10.1 + +## @backstage/plugin-auth-backend@0.25.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/plugin-auth-backend@0.25.1-next.1 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-github-provider@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-backend@0.25.1-next.1 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + +## @backstage/plugin-auth-node@0.6.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog@1.31.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder-common@1.5.11 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## @backstage/plugin-catalog-backend@2.0.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/plugin-catalog-backend-module-aws@0.4.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-catalog-backend-module-azure@0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.4.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-github@0.9.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-backend@2.0.1-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-github@0.9.1-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.6.7-next.1 + +### Patch Changes + +- 57a0bad: Implement retry for GitLab API calls to handle rate limiting +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-gitlab@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-catalog-backend-module-ldap@0.11.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-logs@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-msgraph@0.7.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.8 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-catalog-graph@0.4.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog-import@0.13.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/integration@1.17.0 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-node@1.17.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/plugin-catalog-react@1.18.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/frontend-test-utils@0.3.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + +## @backstage/plugin-devtools@0.1.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-devtools-common@0.1.16 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-devtools-backend@0.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-devtools-common@0.1.16 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/plugin-events-backend@0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-module-azure@0.2.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-module-gerrit@0.2.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-module-github@0.4.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-module-gitlab@0.3.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-module-google-pubsub@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-backend-test-utils@0.1.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-events-node@0.4.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-gateway-backend@1.0.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-home@0.8.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/theme@0.6.6 + - @backstage/plugin-home-react@0.1.26 + +## @backstage/plugin-kubernetes@0.12.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-kubernetes-react@0.5.7 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-kubernetes-backend@0.19.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-kubernetes-node@0.3.1-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/plugin-kubernetes-cluster@0.0.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-kubernetes-react@0.5.7 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-kubernetes-node@0.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-notifications@0.5.6-next.1 + +### Patch Changes + +- 1fb5f06: Adds ability for user to turn on/off notifications for specific topics within an origin. +- Updated dependencies + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.13 + +## @backstage/plugin-notifications-backend@0.5.7-next.1 + +### Patch Changes + +- 1fb5f06: Adds ability for user to turn on/off notifications for specific topics within an origin. +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-notifications-node@0.2.16-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-signals-node@0.1.21-next.1 + +## @backstage/plugin-notifications-backend-module-email@0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-notifications-node@0.2.16-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + +## @backstage/plugin-notifications-backend-module-slack@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-notifications-node@0.2.16-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-notifications-common@0.0.9-next.0 + +### Patch Changes + +- 1fb5f06: Adds ability for user to turn on/off notifications for specific topics within an origin. +- Updated dependencies + - @backstage/config@1.3.2 + +## @backstage/plugin-notifications-node@0.2.16-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-signals-node@0.1.21-next.1 + +## @backstage/plugin-org@0.6.40-next.1 + +### Patch Changes + +- 4fe364f: Org plugin support i18n +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-org-react@0.1.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + +## @backstage/plugin-permission-backend@0.7.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/plugin-permission-node@0.10.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-proxy-backend@0.6.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/types@1.2.1 + - @backstage/plugin-proxy-node@0.1.5-next.1 + +## @backstage/plugin-proxy-node@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-scaffolder@1.31.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/plugin-scaffolder-react@1.16.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/integration@1.17.0 + - @backstage/integration-react@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.10-next.1 + +### Patch Changes + +- e89d7b6: Migrating `azure` actions to using the new `zod` schema format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.11-next.1 + +### Patch Changes + +- 7f710d2: Migrating `bitbucket` actions to use the new `zod` format +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.1 + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.1 + +### Patch Changes + +- ca9fdc0: Migrate `bitbucket-cloud` to new actions format +- 280611d: Fix `bitbucketCloudBranchRestrictions` API calls to accept null to prevent 400 errors for some branch restriction kinds defined. +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.1 + +### Patch Changes + +- d8169fc: Migrate the actions to the new format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.10-next.1 + +### Patch Changes + +- 4a86bca: Migrate actions to new format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.11-next.1 + +### Patch Changes + +- 0b2bbf1: Migrate using new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.10-next.1 + +### Patch Changes + +- e24b29b: Migrating to use new format for actions +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.10-next.1 + +### Patch Changes + +- ed41017: Migrate to new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-github@0.7.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.1 + +### Patch Changes + +- 1fb5f06: Adds ability for user to turn on/off notifications for specific topics within an origin. +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/plugin-notifications-node@0.2.16-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/plugin-scaffolder-node-test-utils@0.2.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-node@0.8.3-next.1 + +### Patch Changes + +- e89d7b6: Use `LoggerService` instead of `Logger`. This is a non-breaking change, as the `LoggerService` is a subset of the `Logger` interface. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-node-test-utils@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/backend-test-utils@1.6.0-next.1 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-react@1.16.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-search@1.4.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.0 + +## @backstage/plugin-search-backend@2.0.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-catalog@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-elasticsearch@1.7.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-explore@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-pg@0.5.45-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-techdocs@0.4.3-next.1 + +### Patch Changes + +- b47ec38: Exports the default document collator for use in document transformation during search indexing. +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-techdocs-node@1.13.4-next.1 + +## @backstage/plugin-search-backend-node@1.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-signals-backend@0.3.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-signals-node@0.1.21-next.1 + +## @backstage/plugin-signals-node@0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-techdocs@1.13.0-next.1 + +### Patch Changes + +- 9dde3ba: Improved Keyboard accessibility in techdocs. +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/integration@1.17.0 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-auth-react@0.1.15 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.49-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.0-next.1 + - @backstage/plugin-catalog@1.31.0-next.1 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/integration-react@1.2.7 + - @backstage/test-utils@1.7.8 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## @backstage/plugin-techdocs-backend@2.0.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + - @backstage/plugin-techdocs-node@1.13.4-next.1 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.1 + +### Patch Changes + +- 9dde3ba: Improved Keyboard accessibility in techdocs. +- Updated dependencies + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/integration@1.17.0 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## @backstage/plugin-techdocs-node@1.13.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + +## @backstage/plugin-user-settings@0.8.23-next.1 + +### Patch Changes + +- ab6d3dd: Add some translation to user-setting plugin +- Updated dependencies + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.13 + - @backstage/plugin-user-settings-common@0.0.1 + +## @backstage/plugin-user-settings-backend@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-node@0.1.21-next.1 + - @backstage/plugin-user-settings-common@0.0.1 + +## example-app@0.2.110-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/canon@0.5.0-next.1 + - @backstage/cli@0.32.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.1 + - @backstage/plugin-techdocs@1.13.0-next.1 + - @backstage/plugin-org@0.6.40-next.1 + - @backstage/plugin-user-settings@0.8.23-next.1 + - @backstage/plugin-notifications@0.5.6-next.1 + - @backstage/plugin-catalog@1.31.0-next.1 + - @backstage/plugin-catalog-graph@0.4.20-next.1 + - @backstage/plugin-catalog-import@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/plugin-home@0.8.9-next.1 + - @backstage/plugin-scaffolder@1.31.1-next.1 + - @backstage/plugin-scaffolder-react@1.16.1-next.1 + - @backstage/app-defaults@1.6.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-api-docs@0.12.8-next.1 + - @backstage/plugin-auth-react@0.1.15 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.1 + - @backstage/plugin-devtools@0.1.28-next.1 + - @backstage/plugin-kubernetes@0.12.8-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.1 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-search@1.4.27-next.1 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-signals@0.0.20-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## example-app-next@0.0.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/canon@0.5.0-next.1 + - @backstage/cli@0.32.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.1 + - @backstage/plugin-techdocs@1.13.0-next.1 + - @backstage/plugin-org@0.6.40-next.1 + - @backstage/plugin-user-settings@0.8.23-next.1 + - @backstage/plugin-notifications@0.5.6-next.1 + - @backstage/plugin-catalog@1.31.0-next.1 + - @backstage/plugin-catalog-graph@0.4.20-next.1 + - @backstage/plugin-catalog-import@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/plugin-home@0.8.9-next.1 + - @backstage/plugin-scaffolder@1.31.1-next.1 + - @backstage/plugin-scaffolder-react@1.16.1-next.1 + - @backstage/app-defaults@1.6.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.0 + - @backstage/frontend-defaults@0.2.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-api-docs@0.12.8-next.1 + - @backstage/plugin-app@0.1.10-next.0 + - @backstage/plugin-app-visualizer@0.1.20-next.0 + - @backstage/plugin-auth-react@0.1.15 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.1 + - @backstage/plugin-kubernetes@0.12.8-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.1 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-search@1.4.27-next.1 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-signals@0.0.20-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## example-backend@0.0.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.1 + - @backstage/plugin-notifications-backend@0.5.7-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.1 + - @backstage/plugin-scaffolder-backend@2.0.0-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-backend@2.0.1-next.1 + - @backstage/plugin-kubernetes-backend@0.19.7-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.7.2-next.1 + - @backstage/plugin-search-backend-module-catalog@0.3.5-next.1 + - @backstage/plugin-techdocs-backend@2.0.3-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-app-backend@0.5.3-next.1 + - @backstage/plugin-auth-backend@0.25.1-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4-next.1 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9-next.1 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.2.11-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1-next.1 + - @backstage/plugin-devtools-backend@0.5.6-next.1 + - @backstage/plugin-events-backend@0.5.3-next.1 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1-next.1 + - @backstage/plugin-permission-backend@0.7.1-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-proxy-backend@0.6.3-next.1 + - @backstage/plugin-search-backend@2.0.3-next.1 + - @backstage/plugin-search-backend-module-explore@0.3.3-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-signals-backend@0.3.5-next.1 + +## e2e-test@0.2.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.0-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/errors@1.2.7 + +## @internal/scaffolder@0.0.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.16.1-next.1 + - @backstage/frontend-plugin-api@0.10.3-next.0 + +## techdocs-cli-embedded-app@0.2.109-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.32.2-next.0 + - @backstage/plugin-techdocs@1.13.0-next.1 + - @backstage/plugin-catalog@1.31.0-next.1 + - @backstage/app-defaults@1.6.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/integration-react@1.2.7 + - @backstage/test-utils@1.7.8 + - @backstage/theme@0.6.6 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## @internal/plugin-todo-list-backend@1.0.40-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 diff --git a/docs/releases/v1.40.0-next.2-changelog.md b/docs/releases/v1.40.0-next.2-changelog.md new file mode 100644 index 0000000000..ed14cbf003 --- /dev/null +++ b/docs/releases/v1.40.0-next.2-changelog.md @@ -0,0 +1,1539 @@ +# Release v1.40.0-next.2 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.40.0-next.2](https://backstage.github.io/upgrade-helper/?to=1.40.0-next.2) + +## @backstage/plugin-scaffolder-backend@2.0.0-next.2 + +### Major Changes + +- 5863b04: **BREAKING CHANGES** + + - The `createBuiltinActions` method has been removed, as this should no longer be needed with the new backend system route, and was only useful when passing the default list of actions again in the old backend system. You should be able to rely on the default behaviour of the new backend system which is to merge the actions. + + - The `createCatalogRegisterAction` and `createFetchCatalogEntityAction` actions no longer require an `AuthService`, and now accepts a `CatalogService` instead of `CatalogClient`. + + Unless you're providing your own override action to the default, this should be a non-breaking change. + + You can migrate using the following if you're getting typescript errors: + + ```ts + import { catalogServiceRef } from '@backstage/plugin-catalog-node'; + import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; + + export const myModule = createBackendModule({ + pluginId: 'scaffolder', + moduleId: 'test', + register({ registerInit }) { + registerInit({ + deps: { + scaffolder: scaffolderActionsExtensionPoint, + catalog: catalogServiceRef, + }, + async init({ scaffolder, catalog }) { + scaffolder.addActions( + createCatalogRegisterAction({ + catalog, + }), + createFetchCatalogEntityAction({ + catalog, + integrations, + }), + ); + }, + }); + }, + }); + ``` + +### Patch Changes + +- 89a941d: Migrating to latest action format + +- 023629e: Enable usage of secrets within 'each' step of software templates. For example, you can now structure your `each` step like this: + + each: + [ + { name: "Service1", token: "${{ secrets.token1 }}" }, + { name: "Service2", token: "${{ secrets.token2 }}" }, + ] + +- e92e481: Add tests for Scaffolder + +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.2-next.2 + - @backstage/plugin-scaffolder-backend-module-github@0.8.0-next.2 + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.10-next.2 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.11-next.2 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.2 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.2 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.10-next.2 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.10-next.2 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/backend-defaults@0.11.0-next.2 + +### Minor Changes + +- 3ccb7fc: Enhanced error handling in the auditor service factory to pass errors as objects. Aligned WinstonRootAuditorService with the default service factory's error handling. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@1.2.4-next.2 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/cli@0.33.0-next.1 + +### Minor Changes + +- eef0e83: Internal update to promote the modular CLI entrypoint to stable. + +### Patch Changes + +- d07fe35: Added user feedback when opening config docs in browser. The command now clearly indicates what it's doing and provides fallback instructions if the browser fails to open. +- d6d63c7: Updating the scaffolder action boilerplate to use new `zod` schema +- e36e855: Added `backstage.pluginId` field in `package.json` to all default plugin package templates for the `new` command. +- Updated dependencies + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.1.10 + - @backstage/integration@1.17.0 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog@1.31.0-next.2 + +### Minor Changes + +- 406acb6: Add support to customize the about card icon links via `EntityIconLinkBlueprint` and provide a default catalog view catalog source, launch scaffolder template and read techdocs docs icon links extensions. + + **BREAKING ALPHA** + + The `Scaffolder` launch template and `TechDocs` read documentation icons have been extracted from the default `Catalog` about card links and are now provided respectively by the `Scaffolder` and `TechDocs` plugins in the new frontend system. It means that they will not be available unless you install the `TechDocs` and `Scaffolder` plugins. Also If you are using translation for these icon link titles other than the default, you should now translate them using the scaffolder translation reference or the TechDocs translation reference (the translation keys are still the same, `aboutCard.viewTechdocs` and `aboutCard.launchTemplate`). + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder-common@1.5.11 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.0-next.2 + +### Minor Changes + +- 8a150bf: **BREAKING**: `BitbucketCloudEntityProvider` now accepts a `CatalogService` instead of a `CatalogApi`. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.0-next.2 + +### Minor Changes + +- 42bb3b8: **BREAKING CHANGE**: User and Group discovery will default to ingesting all users in sub groups that belong to the specified root group in config. Disable by setting `restrictUsersToGroup: true` in app-config under your module settings. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-react@1.19.0-next.2 + +### Minor Changes + +- 406acb6: Introduces a new `EntityIconLinkBlueprint` that customizes the `About` card icon links on the `Catalog` entity page. + + The blueprint currently accepts a `useProps` hook as `param` and this function returns the following props that will be passed to the icon link component: + + | Name | Description | Type | Default Value | + | ---------- | --------------------------------------------------- | ------------- | ------------- | + | `icon` | The icon to display. | `JSX.Element` | N/A | + | `label` | The label for the element. | `string` | N/A | + | `title` | The title for the element. | `string` | N/A | + | `disabled` | Whether the element is disabled. | `boolean` | `false` | + | `href` | The URL to navigate to when the element is clicked. | `string` | N/A | + | `onClick` | A function to call when the element is clicked. | `() => void` | N/A | + + Here is an usage example: + + ```tsx + import { EntityIconLinkBlueprint } from '@backstage/plugin-catalog-react/alpha'; + //... + + EntityIconLinkBlueprint.make({ + name: 'my-icon-link', + params: { + useProps() { + const { t } = useTranslationRef(myIconLinkTranslationRef); + return { + label: t('myIconLink.label'), + icon: , + href: '/my-plugin', + }; + }, + }, + }); + ``` + + Additionally, the `app-config.yaml` file allows you to override some of the default icon link parameters, including `label` and `title` values. Here's how to set them: + + ```yaml + app: + extensions: + - entity-icon-link:my-plugin/my-icon-link: + config: + label: 'My Custom Icon Link label' + ``` + + Finally, you can disable all links if you want to hide the About card header completely (useful, for example, when links are displayed on separate cards). The header is hidden when no icon links extensions are enabled. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-test-utils@0.3.3-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-scaffolder@1.32.0-next.2 + +### Minor Changes + +- 3c59ece: **New Frontend System Only:** + The `Scaffolder` plugin is now responsible for providing an entity icon link extension to launch templates from the catalog entity page. + +### Patch Changes + +- b00c160: Remove React import form notification and scaffolder plugin +- 95a1d72: Added appropriate message when global templating function metadata is absent. +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-backend-module-github@0.8.0-next.2 + +### Minor Changes + +- 5863b04: **BREAKING CHANGES** + + The `createGithubEnvironmentAction` action no longer requires an `AuthService`, and now accepts a `CatalogService` instead of `CatalogClient`. + + Unless you're providing your own override action to the default, this should be a non-breaking change. + + You can migrate using the following if you're getting typescript errors: + + ```ts + import { catalogServiceRef } from '@backstage/plugin-catalog-node'; + import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; + + export const myModule = createBackendModule({ + pluginId: 'scaffolder', + moduleId: 'test', + register({ registerInit }) { + registerInit({ + deps: { + scaffolder: scaffolderActionsExtensionPoint, + catalog: catalogServiceRef, + }, + async init({ scaffolder, catalog }) { + scaffolder.addActions( + createGithubEnvironmentAction({ + catalog, + }), + ); + }, + }); + }, + }); + ``` + +### Patch Changes + +- 575c76b: Migrate to using new actions +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + +## @backstage/plugin-scaffolder-node@0.9.0-next.2 + +### Minor Changes + +- 5863b04: **BREAKING CHANGES** + + The legacy methods to define `createTemplateActions` have been replaced with the new native `zod` approaches for defining input and output schemas. + + You can migrate actions that look like the following with the below examples: + + ```ts + // really old legacy json schema + createTemplateAction<{ repoUrl: string }, { repoOutput: string }>({ + id: 'test', + schema: { + input: { + type: 'object' + required: ['repoUrl'] + properties: { + repoUrl: { + type: 'string', + description: 'repository url description' + } + } + } + } + }); + + // old zod method + createTemplateAction({ + id: 'test' + schema: { + input: { + repoUrl: z.string({ description: 'repository url description' }) + } + } + }) + + // new method: + createTemplateAction({ + id: 'test', + schema: { + input: { + repoUrl: z => z.string({ description: 'repository url description' }) + } + } + }) + + // or for more complex zod types like unions + createTemplateAction({ + id: 'test', + schema: { + input: z => z.object({ + repoUrl: z.string({ description: 'repository url description' }) + }) + } + }) + ``` + + This breaking change also means that `logStream` has been removed entirely from `ActionsContext`, and that the `logger` is now just a `LoggerService` implementation instead. There is no replacement for the `logStream`, if you wish to still keep using a `logStream` we recommend that you create your own stream that writes to `ctx.logger` instead. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.0-next.2 + +### Minor Changes + +- 3cea7ee: **BREAKING CHANGES** + + Because of the removal of the `logStream` property to the `ActionsContext` this has been removed from the `createMockActionContext` method. + + You can remove this as it's no longer supported in the scaffolder actions. + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-test-utils@1.6.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/types@1.2.1 + +## @backstage/plugin-techdocs@1.13.0-next.2 + +### Minor Changes + +- 3c59ece: **New Frontend System Only:** + The `TechDocs` plugin is now responsible for providing an entity icon link extension to read documentation from the catalog entity page. + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/theme@0.6.6 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + +## @backstage/app-defaults@1.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/backend-app-api@1.2.4-next.2 + +### Patch Changes + +- bb9a501: Fixed a bug where occasionally the initialization order of multiple modules consuming a single extension point could happen in the wrong order. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/backend-dynamic-feature-service@0.7.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/plugin-catalog-backend@2.0.1-next.2 + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-events-backend@0.5.3-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/backend-test-utils@1.6.0-next.2 + +### Patch Changes + +- 12c1fd4: Make the `user` credentials mock behave more like production +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/backend-app-api@1.2.4-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/canon@0.5.0-next.2 + +### Patch Changes + +- 44df879: Add min-width: 0; by default on every Flex components in Canon to help support truncated texts inside flex elements. +- ee6ffe6: Fix styling for the title4 prop on the Heading component in Canon. +- f2f814a: Added a render prop to the Button component in Canon to use it as a link. + +## @backstage/core-compat-api@0.4.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/core-plugin-api@1.10.7 + - @backstage/version-bridge@1.0.11 + +## @backstage/core-components@0.17.3-next.0 + +### Patch Changes + +- 6232160: table actions header support i18n +- Updated dependencies + - @backstage/config@1.3.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/version-bridge@1.0.11 + +## @backstage/create-app@0.7.0-next.2 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.15 + +## @backstage/dev-utils@1.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/catalog-model@1.7.4 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/theme@0.6.6 + +## @backstage/frontend-app-api@0.11.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/frontend-defaults@0.2.3-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/frontend-defaults@0.2.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/plugin-app@0.1.10-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-app-api@0.11.3-next.1 + +## @backstage/frontend-dynamic-feature-loader@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/config@1.3.2 + +## @backstage/frontend-plugin-api@0.10.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/frontend-test-utils@0.3.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/plugin-app@0.1.10-next.1 + - @backstage/config@1.3.2 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/test-utils@1.7.8 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/repo-tools@0.14.0-next.2 + +### Patch Changes + +- 4bff5d0: Fixed a bug where linting would fail with the generated clients when defining top-level `enum` schema values. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + +## @techdocs/cli@1.9.4-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/plugin-techdocs-node@1.13.4-next.1 + +## @backstage/plugin-api-docs@0.12.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-app@0.1.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/core-plugin-api@1.10.7 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-app-visualizer@0.1.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/core-plugin-api@1.10.7 + +## @backstage/plugin-auth-react@0.1.16-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + +## @backstage/plugin-catalog-backend@2.0.1-next.2 + +### Patch Changes + +- 2cac8b0: You can now specify an optional value when applying the `HAS_LABEL` permission rule, similar to the `HAS_ANNOTATION` permission rule. +- Updated dependencies + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/plugin-catalog-backend-module-aws@0.4.12-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-catalog-backend-module-github@0.9.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-backend-module-github@0.9.1-next.2 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-gitlab@0.7.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/plugin-catalog-backend@2.0.1-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-catalog-backend-module-logs@0.1.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/plugin-catalog-graph@0.4.20-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog-import@0.13.1-next.2 + +### Patch Changes + +- 5d7c539: Catalog import plugin full support i18n +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + +## @backstage/plugin-config-schema@0.1.69-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-devtools@0.1.28-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/plugin-devtools-common@0.1.16 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-devtools-backend@0.5.6-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-devtools-common@0.1.16 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## @backstage/plugin-home@0.8.9-next.2 + +### Patch Changes + +- 0ebad54: Fixed the `WelcomeTitle` to properly default to the previous value of `inherit` +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/plugin-home-react@0.1.27-next.0 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/theme@0.6.6 + +## @backstage/plugin-home-react@0.1.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + +## @backstage/plugin-kubernetes@0.12.8-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/plugin-kubernetes-react@0.5.8-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-kubernetes-react@0.5.8-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-plugin-api@1.10.7 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-permission-react@0.4.34 + +## @backstage/plugin-kubernetes-react@0.5.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-notifications@0.5.6-next.2 + +### Patch Changes + +- b00c160: Remove React import form notification and scaffolder plugin +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/plugin-signals-react@0.0.13 + +## @backstage/plugin-notifications-backend@0.5.7-next.2 + +### Patch Changes + +- 8a150bf: Internal changes to switch to the non-alpha `catalogServiceRef` +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/plugin-notifications-node@0.2.16-next.1 + - @backstage/plugin-signals-node@0.1.21-next.1 + +## @backstage/plugin-notifications-backend-module-email@0.3.10-next.2 + +### Patch Changes + +- 8a150bf: Internal changes to switch to the non-alpha `catalogServiceRef` +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/plugin-notifications-node@0.2.16-next.1 + +## @backstage/plugin-org@0.6.40-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-org-react@0.1.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-plugin-api@1.10.7 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.2 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.2 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.0 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.2-next.2 + +### Patch Changes + +- a296637: Migrate to new action format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.2 + +### Patch Changes + +- 3f56115: Removed `octokit` dependency as it was not being used +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/plugin-notifications-common@0.0.9-next.0 + - @backstage/plugin-notifications-node@0.2.16-next.1 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.10-next.2 + +### Patch Changes + +- a579693: Migrate to new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.10-next.2 + +### Patch Changes + +- 6c6fb4a: Migrate to new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.11-next.2 + +### Patch Changes + +- b392a34: Migrate to new actions format +- Updated dependencies + - @backstage/plugin-scaffolder-node-test-utils@0.3.0-next.2 + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-react@1.16.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-plugin-api@1.10.7 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-search@1.4.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend@2.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-react@1.9.1-next.1 + +### Patch Changes + +- 869fa46: SearchBar clear button support i18n +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/core-plugin-api@1.10.7 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-signals@0.0.20-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/core-plugin-api@1.10.7 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.13 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.49-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/test-utils@1.7.8 + +## @backstage/plugin-techdocs-backend@2.0.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-client@1.10.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-node@1.17.1-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.1 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + - @backstage/plugin-techdocs-node@1.13.4-next.1 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/core-plugin-api@1.10.7 + - @backstage/integration@1.17.0 + +## @backstage/plugin-techdocs-react@1.3.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-techdocs-common@0.1.1-next.0 + +## @backstage/plugin-user-settings@0.8.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/errors@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.13 + - @backstage/plugin-user-settings-common@0.0.1 + +## @backstage/plugin-user-settings-backend@0.3.3-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-signals-node@0.1.21-next.1 + - @backstage/plugin-user-settings-common@0.0.1 + +## example-app@0.2.110-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/cli@0.33.0-next.1 + - @backstage/canon@0.5.0-next.2 + - @backstage/plugin-notifications@0.5.6-next.2 + - @backstage/plugin-scaffolder@1.32.0-next.2 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-catalog-import@0.13.1-next.2 + - @backstage/plugin-home@0.8.9-next.2 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-api-docs@0.12.8-next.2 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-catalog-graph@0.4.20-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + - @backstage/plugin-devtools@0.1.28-next.2 + - @backstage/plugin-kubernetes@0.12.8-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + - @backstage/plugin-org@0.6.40-next.2 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/plugin-search@1.4.27-next.2 + - @backstage/plugin-signals@0.0.20-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/plugin-user-settings@0.8.23-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-search-common@1.2.18 + +## example-app-next@0.0.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/cli@0.33.0-next.1 + - @backstage/canon@0.5.0-next.2 + - @backstage/plugin-notifications@0.5.6-next.2 + - @backstage/plugin-scaffolder@1.32.0-next.2 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-catalog-import@0.13.1-next.2 + - @backstage/plugin-home@0.8.9-next.2 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-api-docs@0.12.8-next.2 + - @backstage/plugin-app@0.1.10-next.1 + - @backstage/plugin-app-visualizer@0.1.20-next.1 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-catalog-graph@0.4.20-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + - @backstage/plugin-kubernetes@0.12.8-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + - @backstage/plugin-org@0.6.40-next.2 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/plugin-search@1.4.27-next.2 + - @backstage/plugin-signals@0.0.20-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/plugin-user-settings@0.8.23-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/frontend-defaults@0.2.3-next.1 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-search-common@1.2.18 + +## app-next-example-plugin@0.0.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + +## example-backend@0.0.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-github@0.8.0-next.2 + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/plugin-scaffolder-backend@2.0.0-next.2 + - @backstage/plugin-notifications-backend@0.5.7-next.2 + - @backstage/plugin-catalog-backend@2.0.1-next.2 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-app-backend@0.5.3-next.1 + - @backstage/plugin-auth-backend@0.25.1-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4-next.1 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.2.11-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1-next.1 + - @backstage/plugin-devtools-backend@0.5.6-next.2 + - @backstage/plugin-events-backend@0.5.3-next.1 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1-next.1 + - @backstage/plugin-kubernetes-backend@0.19.7-next.1 + - @backstage/plugin-permission-backend@0.7.1-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-proxy-backend@0.6.3-next.1 + - @backstage/plugin-search-backend@2.0.3-next.2 + - @backstage/plugin-search-backend-module-catalog@0.3.5-next.1 + - @backstage/plugin-search-backend-module-explore@0.3.3-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-signals-backend@0.3.5-next.1 + - @backstage/plugin-techdocs-backend@2.0.3-next.2 + +## e2e-test@0.2.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.0-next.2 + - @backstage/cli-common@0.1.15 + - @backstage/errors@1.2.7 + +## @internal/frontend@0.0.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @internal/scaffolder@0.0.10-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + +## techdocs-cli-embedded-app@0.2.109-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/cli@0.33.0-next.1 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/test-utils@1.7.8 + - @backstage/theme@0.6.6 + +## @internal/plugin-todo-list@1.0.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 diff --git a/docs/releases/v1.40.0-next.3-changelog.md b/docs/releases/v1.40.0-next.3-changelog.md new file mode 100644 index 0000000000..6dfc2aa342 --- /dev/null +++ b/docs/releases/v1.40.0-next.3-changelog.md @@ -0,0 +1,166 @@ +# Release v1.40.0-next.3 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.40.0-next.3](https://backstage.github.io/upgrade-helper/?to=1.40.0-next.3) + +## @backstage/plugin-events-backend-module-kafka@0.1.0-next.0 + +### Minor Changes + +- b034b9d: Adds a new module `kafka` for plugin-events-backend + + The module introduces the `KafkaConsumerClient` which creates a Kafka client used to establish consumer connections. It also provides the `KafkaConsumingEventPublisher`, a consumer that subscribes to configured Kafka topics and publishes received messages to the Event Service. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## @backstage/cli@0.33.0-next.2 + +### Patch Changes + +- 8a0164c: Fix an issue where some commands were not usable because of missing dist files +- Updated dependencies + - @backstage/eslint-plugin@0.1.11-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.1 + +## @backstage/create-app@0.7.0-next.3 + +### Patch Changes + +- Bumped create-app version. +- Updated dependencies + - @backstage/cli-common@0.1.15 + +## @backstage/eslint-plugin@0.1.11-next.0 + +### Patch Changes + +- 098ef95: Fix custom rules package scanning performance. + +## example-app@0.2.110-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.33.0-next.2 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/canon@0.5.0-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-api-docs@0.12.8-next.2 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-graph@0.4.20-next.2 + - @backstage/plugin-catalog-import@0.13.1-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + - @backstage/plugin-devtools@0.1.28-next.2 + - @backstage/plugin-home@0.8.9-next.2 + - @backstage/plugin-kubernetes@0.12.8-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + - @backstage/plugin-notifications@0.5.6-next.2 + - @backstage/plugin-org@0.6.40-next.2 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder@1.32.0-next.2 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/plugin-search@1.4.27-next.2 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/plugin-signals@0.0.20-next.1 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/plugin-user-settings@0.8.23-next.2 + +## example-app-next@0.0.24-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.33.0-next.2 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/canon@0.5.0-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/frontend-defaults@0.2.3-next.1 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-api-docs@0.12.8-next.2 + - @backstage/plugin-app@0.1.10-next.1 + - @backstage/plugin-app-visualizer@0.1.20-next.1 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-graph@0.4.20-next.2 + - @backstage/plugin-catalog-import@0.13.1-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + - @backstage/plugin-home@0.8.9-next.2 + - @backstage/plugin-kubernetes@0.12.8-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + - @backstage/plugin-notifications@0.5.6-next.2 + - @backstage/plugin-org@0.6.40-next.2 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder@1.32.0-next.2 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/plugin-search@1.4.27-next.2 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/plugin-signals@0.0.20-next.1 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/plugin-user-settings@0.8.23-next.2 + +## e2e-test@0.2.29-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.0-next.3 + - @backstage/cli-common@0.1.15 + - @backstage/errors@1.2.7 + +## techdocs-cli-embedded-app@0.2.109-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.33.0-next.2 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/integration-react@1.2.7 + - @backstage/test-utils@1.7.8 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 diff --git a/docs/releases/v1.40.0.md b/docs/releases/v1.40.0.md new file mode 100644 index 0000000000..b5ef87ffe1 --- /dev/null +++ b/docs/releases/v1.40.0.md @@ -0,0 +1,190 @@ +--- +id: v1.40.0 +title: v1.40.0 +description: Backstage Release v1.40.0 +--- + +These are the release notes for the v1.40.0 release of [Backstage](https://backstage.io/). + +A huge thanks to the whole team of maintainers and contributors as well as the amazing Backstage Community for the hard work in getting this release developed and done. + +## Highlights + +### Scaffolder 2.0 Breaking Changes + +The deprecated legacy action formats have been removed and replaced with the new native `zod` formats. + +This also cleaned up some deprecated `logStream` and `WinstonLogger` usages in the old patterns. + +```ts +// really old legacy json schema +createTemplateAction<{ repoUrl: string }, { repoOutput: string }>({ + id: 'test', + schema: { + input: { + type: 'object' + required: ['repoUrl'] + properties: { + repoUrl: { + type: 'string', + description: 'repository url description' + } + } + } + } +}); + +// old zod method +createTemplateAction({ + id: 'test' + schema: { + input: { + repoUrl: z.string({ description: 'repository url description' }) + } + } +}) + +// new method: +createTemplateAction({ + id: 'test', + schema: { + input: { + repoUrl: z => z.string({ description: 'repository url description' }) + } + } +}) + +``` + +The `scaffolder-backend` plugin has been converted to being New Backend System only, which means a lot of the public API has been cleaned up. + +The `createRouter` and `createBuiltinActions` have been removed as they were only used in the legacy backend system. + +A lot of deprecated types which were re-exported in the `-backend` package from `-common` and `-node` have been removed, and can be fixed by importing them from the correct package. + +The deprecated `copyWithoutRender` option has been removed from `fetch:template` and should be renamed to `copyWithoutTemplating`. + +The re-exported action creators from the provider packages such as `createPublishAzureAction` and `createPublishGithubAction` should now be imported from the provider modules themselves. + +As always you can head over the latest changelogs for [`@backstage/plugin-scaffolder-backend`](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend/CHANGELOG.md) and [`@backstage/plugin-scaffolder-node`](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-node/CHANGELOG.md) +for more detailed information. + +There’s also a number of new deprecation for types which are currently exported from `plugin-scaffolder-node`. We’re going to be looking at re-working the Scaffolder architecture in the future, so we’re going to be removing these types in a future version to iterate on the new API surfaces. Stay tuned for more updates! + +### Actions Registry + +We’ve added two new `alpha` services which can be used to define distributed Actions across Backstage. Plugins can use the `ActionsRegistry` to define actions that are automatically installed with their associated plugin. + +On top of this Actions Registry is a new `mcp-actions` backend plugin, which will surface these actions as tools as an MCP server. This can be used to expose plugin Actions with your favourite AI tools, such as Cursor, Claude or ChatGPT. + +You can find out more information about the `ActionsRegistry` and MCP integration in [this RFC](https://github.com/backstage/backstage/issues/30218). + +We’re actively working on this area, therefore it’s currently highly experimental and could be subject to breaking changes in future releases. However we’d really appreciate some feedback if you want to try and create some Actions for your plugins and surface them in an MCP server! + +In the next release we’ll be looking to integrate these Actions with the Scaffolder allowing you to call these actions from a template. + +### TechDocs deep linking + +Introduced `backstage.io/techdocs-entity-path` annotation which allows deep linking into other TechDocs in conjunction with `backstage.io/techdocs-entity`. + +Contributed by [@csuich2](https://github.com/csuich2) in [#29760](https://github.com/backstage/backstage/pull/29760) + +### Catalog modules Breaking Changes + +- `BitbucketCloudEntityProvider` now accepts a `CatalogService` instead of `CatalogApi` +- User and Group discovery for GitLab will default to ingesting all users in sub groups that belong to the specified root group in config. Disable by setting `restrictUsersToGroup: true` in app-config under your module settings. + +### New Module drop: `@backstage/plugin-events-backend-module-kafka` + +The module introduces the `KafkaConsumerClient` which creates a Kafka client used to establish consumer connections. It also provides the `KafkaConsumingEventPublisher`, a consumer that subscribes to configured Kafka topics and publishes received messages to the Backstage events service where Backstage plugins can access them. + +Contributed by [@Jonas-Beck](https://github.com/Jonas-Beck) in [#29315](https://github.com/backstage/backstage/pull/29315) + +### New lint rule added + +A new lint rule `@backstage/no-mixed-plugin-imports` was added to the defaults. This enforces rules that were always true but until now were implicit: that you should not import across frontend and backend package boundaries, isomorphic packages should not import non-isomorphic, etc. + +This rule is initially only set at a warning level, to give you some time to react. You may see warnings appear in your build output that were not there before - do pay attention to them, because they may expose some issues that you had not yet noticed. + +We intend to make this rule be at an error level in a future release. + +The rule has an option `excludedTargetPackages` that lets you opt out of enforcement in specific packages. You can put something like this in your root `.eslintrc.js`: + +```js +module.exports = { + root: true, + plugins: ['@spotify', 'react', 'testing-library', '@backstage'], + rules: { + '@backstage/no-mixed-plugin-imports': [ + 'error', // if you want to opt in to strict checks early + { + excludedTargetPackages: [ + '@internal/plugin-foo', + // ... +``` + +Contributed by [@drodil](https://github.com/drodil) in [#30227](https://github.com/backstage/backstage/pull/30227) + +### CLI: movement toward `rspack` + +The `BACKSTAGE_CLI_EXPERIMENTAL_BUILD_CACHE` flag has been removed entirely. If you were using this flag, we encourage you to switch to `EXPERIMENTAL_RSPACK` instead. In the near future, we hope to make `rspack` the default out of the box. + +While making these changes, the experimental `FORCE_REACT_DEVELOPMENT` flag was removed as well. + +### Backend rate limiting + +The backend system now has builtin support for rate limiting of incoming requests, both for your entire backends and on a per-plugin basis. It can use different backing stores for its state, and in-memory and redis is currently implemented out of the box. + +You can read more about this opt-in feature in [the documentation](https://backstage.io/docs/backend-system/core-services/http-router) for the HTTP router service. + +Contributed by [@drodil](https://github.com/drodil) in [#28708](https://github.com/backstage/backstage/pull/28708) + +### New Frontend System plugin info + +Plugins in the new frontend system can now expose rich, extensible metadata about themselves. This data is accessible at runtime inside your app. This is for example useful for adding contact and support information, and much more - and you can even overlay your own data on top of what is provided by open-source plugins. + +You can read more about this in the [frontend app](https://backstage.io/docs/frontend-system/architecture/app) and [plugin](https://backstage.io/docs/frontend-system/architecture/plugins) architecture documentation. + +### Notifications retention + +Notifications that are stored by the notifications backend plugin now have a default retention of one year before being deleted. This helps keep the storage size in check over time. You can override this using the `notifications.retention` duration setting in your app-config. + +Contributed by [@drodil](https://github.com/drodil) in [#30206](https://github.com/backstage/backstage/pull/30206) + +### Lots of i18n work + +A bunch of work was done to enable i18n (translations) in several plugins! This affected at least the following: + +- core components +- the org plugin +- the catalog import plugin +- the home plugin +- the search plugin +- the user settings plugin + +Contributed by [@mario-mui](https://github.com/mario-mui) + +### Canon steams ahead + +While it’s still early days, we still want to call out that the canon design system work steams ahead with various controls added and improvements made. Hang tight! + +## Security Fixes + +This release does not contain any security fixes. + +## Upgrade path + +We recommend that you keep your Backstage project up to date with this latest release. For more guidance on how to upgrade, check out the documentation for [keeping Backstage updated](https://backstage.io/docs/getting-started/keeping-backstage-updated). + +## Links and References + +Below you can find a list of links and references to help you learn about and start using this new release. + +- [Backstage official website](https://backstage.io/), [documentation](https://backstage.io/docs/), and [getting started guide](https://backstage.io/docs/getting-started/) +- [GitHub repository](https://github.com/backstage/backstage) +- Backstage's [versioning and support policy](https://backstage.io/docs/overview/versioning-policy) +- [Community Discord](https://discord.gg/backstage-687207715902193673) for discussions and support +- [Changelog](https://github.com/backstage/backstage/tree/master/docs/releases/v1.40.0-changelog.md) +- Backstage [Demos](https://backstage.io/demos), [Blog](https://backstage.io/blog), [Roadmap](https://backstage.io/docs/overview/roadmap) and [Plugins](https://backstage.io/plugins) + +Sign up for our [newsletter](https://info.backstage.spotify.com/newsletter_subscribe) if you want to be informed about what is happening in the world of Backstage. diff --git a/docs/releases/v1.41.0-next.0-changelog.md b/docs/releases/v1.41.0-next.0-changelog.md new file mode 100644 index 0000000000..9988f3005b --- /dev/null +++ b/docs/releases/v1.41.0-next.0-changelog.md @@ -0,0 +1,1497 @@ +# Release v1.41.0-next.0 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.41.0-next.0](https://backstage.github.io/upgrade-helper/?to=1.41.0-next.0) + +## @backstage/plugin-catalog-backend@3.0.0-next.0 + +### Major Changes + +- 2339363: **BREAKING:** The experimental `catalog.useUrlReadersSearch` configuration flag (introduced in v1.36) has been removed. + + The `UrlReaderProcessor` now always uses the `search` method of `UrlReaders`. Built-in `UrlReaderService` implementations have been updated accordingly. + If you use custom `UrlReaderService` implementations, you need to adapt their `search` method to correctly handle both specific URLs and potential + search patterns (see changes on built-in readers [in the original PR](https://github.com/backstage/backstage/pull/28379/files#diff-68b0452f173ee54bdd40f7b5e047a9cb8bb59200425622c212c217b76dac1d1b)). + + Previous behavior was to call the `search` method only if the parsed Git URL's filename contained a wildcard and use `readUrl` otherwise. Each `UrlReaderService` must implement this logic in the `search` method instead. + + This allows each `UrlReaderService` implementation to check whether it's a search URL (that contains a wildcard pattern) or not using logic that is specific to each provider. + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/backend-test-utils@1.7.0-next.0 + +### Minor Changes + +- ead925a: Add a standard `toString` on credentials objects + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/backend-app-api@1.2.4 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/canon@0.6.0-next.0 + +### Minor Changes + +- 4c6d891: **BREAKING CHANGES** + + We’re updating our Button component to provide better support for button links. + + - We’re introducing a new `ButtonLink` component, which replaces the previous render prop pattern. + - To maintain naming consistency across components, `IconButton` is being renamed to `ButtonIcon`. + - Additionally, the render prop will be removed from all button-related components. + + These changes aim to simplify usage and improve clarity in our component API. + +### Patch Changes + +- 140f652: We are consolidating all css files into a single styles.css in Canon. +- 8154fb9: Add new SearchField component in Canon +- 6910892: Add new `RadioGroup` + `Radio` component to Canon +- a8a8514: We are transforming how we structure our class names and data attributes definitions for all components. They are now all set in the same place. +- 667b951: Added placeholder prop to TextField component. +- e71333a: adding export for ButtonLink so it's importable + +## @backstage/repo-tools@0.15.0-next.0 + +### Minor Changes + +- 1e7082e: Clear output directory before running `package-docs` and skip all internal packages. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/errors@1.2.7 + +## @backstage/app-defaults@1.6.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/backend-defaults@0.11.1-next.0 + +### Patch Changes + +- ead925a: Add a standard `toString` on credentials objects +- e0189b8: UrlReader: Fix handling of access tokens for GitLab readURL requests +- d1e4a6d: Fixed bug where the GitLab user token and GitLab integration token were being merged together +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-app-api@1.2.4 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + +## @backstage/backend-dynamic-feature-service@0.7.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.0-next.0 + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-events-backend@0.5.3 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/cli@0.33.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/eslint-plugin@0.1.11 + - @backstage/release-manifests@0.0.13 + - @backstage/types@1.2.1 + +## @backstage/core-compat-api@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/version-bridge@1.0.11 + +## @backstage/core-components@0.17.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/config@1.3.2 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/version-bridge@1.0.11 + +## @backstage/create-app@0.7.1-next.0 + +### Patch Changes + +- 2339363: **BREAKING:** The experimental `catalog.useUrlReadersSearch` configuration flag (introduced in v1.36) has been removed. + + The `UrlReaderProcessor` now always uses the `search` method of `UrlReaders`. Built-in `UrlReaderService` implementations have been updated accordingly. + If you use custom `UrlReaderService` implementations, you need to adapt their `search` method to correctly handle both specific URLs and potential + search patterns (see changes on built-in readers [in the original PR](https://github.com/backstage/backstage/pull/28379/files#diff-68b0452f173ee54bdd40f7b5e047a9cb8bb59200425622c212c217b76dac1d1b)). + + Previous behavior was to call the `search` method only if the parsed Git URL's filename contained a wildcard and use `readUrl` otherwise. Each `UrlReaderService` must implement this logic in the `search` method instead. + + This allows each `UrlReaderService` implementation to check whether it's a search URL (that contains a wildcard pattern) or not using logic that is specific to each provider. + +- Updated dependencies + - @backstage/cli-common@0.1.15 + +## @backstage/dev-utils@1.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.2.9-next.0 + - @backstage/theme@0.6.7-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/app-defaults@1.6.4-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + +## @backstage/frontend-app-api@0.11.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-defaults@0.2.4-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/frontend-defaults@0.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-app@0.1.11-next.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/frontend-app-api@0.11.4-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## @backstage/frontend-dynamic-feature-loader@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.2 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## @backstage/frontend-plugin-api@0.10.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/frontend-test-utils@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-app@0.1.11-next.0 + - @backstage/test-utils@1.7.10-next.0 + - @backstage/config@1.3.2 + - @backstage/frontend-app-api@0.11.4-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @backstage/integration@1.17.1-next.0 + +### Patch Changes + +- e0189b8: UrlReader: Fix handling of access tokens for GitLab readURL requests +- d1e4a6d: Fixed bug where the GitLab user token and GitLab integration token were being merged together +- Updated dependencies + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/integration-react@1.2.9-next.0 + +### Patch Changes + +- 998fd15: Separated gitlab `write_repository` and `api` scope to pass checks in `RefreshingAuthSessionManager` +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/config@1.3.2 + - @backstage/core-plugin-api@1.10.8 + +## @techdocs/cli@1.9.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-techdocs-node@1.13.5-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + +## @backstage/test-utils@1.7.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/theme@0.6.7-next.0 + +### Patch Changes + +- b68d269: Update uncomfortably bright color in recently visited and top visited home page cards + +## @backstage/plugin-api-docs@0.12.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog@1.31.1-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-app@0.1.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.2.9-next.0 + - @backstage/theme@0.6.7-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-app-visualizer@0.1.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## @backstage/plugin-auth-react@0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + +## @backstage/plugin-bitbucket-cloud-common@0.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + +## @backstage/plugin-catalog@1.31.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.2.9-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-search-react@1.9.2-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-scaffolder-common@1.5.11 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-techdocs-common@0.1.1 + +## @backstage/plugin-catalog-backend-module-aws@0.4.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-catalog-backend-module-azure@0.3.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-bitbucket-cloud-common@0.3.1-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-github@0.10.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.0-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-github@0.10.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/config@1.3.2 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend-module-gitlab@0.7.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.0-next.0 + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-catalog-backend-module-logs@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.0-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/catalog-model@1.7.4 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-graph@0.4.21-next.0 + +### Patch Changes + +- fe1a2f4: Catalog graph plugin support i18n +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-catalog-import@0.13.2-next.0 + +### Patch Changes + +- 406b8b8: Fixed bug with error message since ResponseError is now thrown from CatalogClient +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-catalog-react@1.19.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration-react@1.2.9-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/frontend-test-utils@0.3.4-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## @backstage/plugin-config-schema@0.1.70-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-devtools@0.1.29-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-devtools-common@0.1.16 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-devtools-backend@0.5.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config-loader@1.10.1 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-devtools-common@0.1.16 + - @backstage/plugin-permission-common@0.9.0 + +## @backstage/plugin-events-backend-module-github@0.4.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + - @backstage/config@1.3.2 + - @backstage/types@1.2.1 + +## @backstage/plugin-home@0.8.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-home-react@0.1.28-next.0 + +## @backstage/plugin-home-react@0.1.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## @backstage/plugin-kubernetes@0.12.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-kubernetes-react@0.5.9-next.0 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-kubernetes-cluster@0.0.27-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-kubernetes-common@0.9.5 + - @backstage/plugin-kubernetes-react@0.5.9-next.0 + - @backstage/plugin-permission-react@0.4.35 + +## @backstage/plugin-kubernetes-react@0.5.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-kubernetes-common@0.9.5 + +## @backstage/plugin-mcp-actions-backend@0.1.1-next.0 + +### Patch Changes + +- 6bc0799: Fixed the example in the README for generating a static token by adding a subject field +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/catalog-client@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-notifications@0.5.7-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-notifications-common@0.0.9 + - @backstage/plugin-signals-react@0.0.14 + +## @backstage/plugin-notifications-backend@0.5.8-next.0 + +### Patch Changes + +- 9a5a73f: Fix `addTopic` migration when `user_settings` present +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-notifications-node@0.2.16 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-notifications-common@0.0.9 + - @backstage/plugin-signals-node@0.1.21 + +## @backstage/plugin-org@0.6.41-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-catalog-common@1.1.4 + +## @backstage/plugin-org-react@0.1.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-plugin-api@1.10.8 + +## @backstage/plugin-scaffolder@1.32.1-next.0 + +### Patch Changes + +- 289e4a1: Filter MultiEntityPicker options based on rendered option value +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-scaffolder-react@1.17.1-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-backend@2.0.1-next.0 + +### Patch Changes + +- dbde180: An internal refactor which adds additional types to experimental checkpoints +- fc70b43: Replaced deprecated uses of `@backstage/backend-common` with the equivalents in `@backstage/backend-defaults` and `@backstage/backend-plugin-api`. +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.8.1-next.0 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.12-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.0 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.11-next.0 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.11-next.0 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.3-next.0 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.11-next.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-bitbucket-cloud-common@0.3.1-next.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.13-next.0 + +### Patch Changes + +- cf9ba6f: Fixing the typescript issue with using `z.unknown()` +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-github@0.8.1-next.0 + +### Patch Changes + +- f36bcf9: Added support for file deletion to `publish:github:pull-request` action. + + Example usage: + + ```diff + - action: publish:github:pull-request + id: clean-up-pr + input: + description: This is the description + + filesToDelete: + + - outdated/changelog.md + + - sample-file.txt + owner: owner + repo: repo + title: Title Goes Here + + ``` + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-notifications-node@0.2.16 + - @backstage/plugin-notifications-common@0.0.9 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node-test-utils@0.3.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-node@0.9.1-next.0 + +### Patch Changes + +- dbde180: An internal refactor which adds additional types to experimental checkpoints +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.1-next.0 + +### Patch Changes + +- dbde180: An internal refactor which adds additional types to experimental checkpoints +- Updated dependencies + - @backstage/backend-test-utils@1.7.0-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/types@1.2.1 + +## @backstage/plugin-scaffolder-react@1.17.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-scaffolder-common@1.5.11 + +## @backstage/plugin-search@1.4.28-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-search-react@1.9.2-next.0 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend@2.0.4-next.0 + +### Patch Changes + +- 69fb975: Error messages should not contain backend SQL query strings in the API response, this change will ensure that messages are logged and empty response is returned to the user +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-backend-module-techdocs@0.4.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-techdocs-node@1.13.5-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-search-react@1.9.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-search-common@1.2.18 + +## @backstage/plugin-signals@0.0.21-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.14 + +## @backstage/plugin-techdocs@1.13.2-next.0 + +### Patch Changes + +- 1debf7f: Fixed an issue causing TechDocs to not properly handle initial redirect. +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/theme@0.6.7-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-search-react@1.9.2-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-auth-react@0.1.17-next.0 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-techdocs-common@0.1.1 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.51-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.2-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/plugin-catalog@1.31.1-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/test-utils@1.7.10-next.0 + - @backstage/plugin-search-react@1.9.2-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + +## @backstage/plugin-techdocs-backend@2.0.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-catalog-node@1.17.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.4-next.0 + - @backstage/plugin-techdocs-node@1.13.5-next.0 + - @backstage/catalog-client@1.10.1 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-techdocs-common@0.1.1 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## @backstage/plugin-techdocs-node@1.13.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-techdocs-common@0.1.1 + +## @backstage/plugin-techdocs-react@1.3.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/version-bridge@1.0.11 + - @backstage/plugin-techdocs-common@0.1.1 + +## @backstage/plugin-user-settings@0.8.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/core-app-api@1.17.1 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/errors@1.2.7 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-react@0.0.14 + - @backstage/plugin-user-settings-common@0.0.1 + +## @backstage/plugin-user-settings-backend@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-signals-node@0.1.21 + - @backstage/plugin-user-settings-common@0.0.1 + +## example-app@0.2.111-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.2-next.0 + - @backstage/plugin-catalog-graph@0.4.21-next.0 + - @backstage/canon@0.6.0-next.0 + - @backstage/plugin-scaffolder@1.32.1-next.0 + - @backstage/plugin-catalog-import@0.13.2-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/theme@0.6.7-next.0 + - @backstage/cli@0.33.1-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.0 + - @backstage/plugin-catalog@1.31.1-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/app-defaults@1.6.4-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-home@0.8.10-next.0 + - @backstage/plugin-notifications@0.5.7-next.0 + - @backstage/plugin-scaffolder-react@1.17.1-next.0 + - @backstage/plugin-search-react@1.9.2-next.0 + - @backstage/plugin-signals@0.0.21-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/plugin-user-settings@0.8.24-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-app-api@0.11.4-next.0 + - @backstage/plugin-api-docs@0.12.9-next.0 + - @backstage/plugin-auth-react@0.1.17-next.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.0 + - @backstage/plugin-devtools@0.1.29-next.0 + - @backstage/plugin-kubernetes@0.12.9-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.27-next.0 + - @backstage/plugin-org@0.6.41-next.0 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-search@1.4.28-next.0 + - @backstage/plugin-search-common@1.2.18 + +## example-app-next@0.0.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.2-next.0 + - @backstage/plugin-catalog-graph@0.4.21-next.0 + - @backstage/canon@0.6.0-next.0 + - @backstage/plugin-scaffolder@1.32.1-next.0 + - @backstage/plugin-catalog-import@0.13.2-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/theme@0.6.7-next.0 + - @backstage/cli@0.33.1-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.0 + - @backstage/plugin-app@0.1.11-next.0 + - @backstage/plugin-catalog@1.31.1-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/app-defaults@1.6.4-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-home@0.8.10-next.0 + - @backstage/plugin-notifications@0.5.7-next.0 + - @backstage/plugin-scaffolder-react@1.17.1-next.0 + - @backstage/plugin-search-react@1.9.2-next.0 + - @backstage/plugin-signals@0.0.21-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/plugin-user-settings@0.8.24-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-app-api@0.11.4-next.0 + - @backstage/frontend-defaults@0.2.4-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-api-docs@0.12.9-next.0 + - @backstage/plugin-app-visualizer@0.1.21-next.0 + - @backstage/plugin-auth-react@0.1.17-next.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.0 + - @backstage/plugin-kubernetes@0.12.9-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.27-next.0 + - @backstage/plugin-org@0.6.41-next.0 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-search@1.4.28-next.0 + - @backstage/plugin-search-common@1.2.18 + +## app-next-example-plugin@0.0.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## example-backend@0.0.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.0-next.0 + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-scaffolder-backend@2.0.1-next.0 + - @backstage/plugin-notifications-backend@0.5.8-next.0 + - @backstage/plugin-mcp-actions-backend@0.1.1-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.8.1-next.0 + - @backstage/plugin-search-backend@2.0.4-next.0 + - @backstage/plugin-app-backend@0.5.3 + - @backstage/plugin-auth-backend@0.25.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-devtools-backend@0.5.7-next.0 + - @backstage/plugin-events-backend@0.5.3 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1 + - @backstage/plugin-kubernetes-backend@0.19.7 + - @backstage/plugin-permission-backend@0.7.1 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-proxy-backend@0.6.3 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-signals-backend@0.3.5 + - @backstage/plugin-techdocs-backend@2.0.4-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9 + - @backstage/plugin-catalog-backend-module-openapi@0.2.12-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9 + - @backstage/plugin-search-backend-module-catalog@0.3.5 + - @backstage/plugin-search-backend-module-explore@0.3.3 + - @backstage/plugin-search-backend-module-techdocs@0.4.4-next.0 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.12-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1 + - @backstage/plugin-permission-common@0.9.0 + +## e2e-test@0.2.30-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/create-app@0.7.1-next.0 + - @backstage/cli-common@0.1.15 + - @backstage/errors@1.2.7 + +## @internal/frontend@0.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/types@1.2.1 + - @backstage/version-bridge@1.0.11 + +## @internal/scaffolder@0.0.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-react@1.17.1-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## techdocs-cli-embedded-app@0.2.110-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.2-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/theme@0.6.7-next.0 + - @backstage/cli@0.33.1-next.0 + - @backstage/plugin-catalog@1.31.1-next.0 + - @backstage/app-defaults@1.6.4-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/test-utils@1.7.10-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + +## @internal/plugin-todo-list@1.0.41-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-plugin-api@1.10.8 diff --git a/docs/releases/v1.41.0-next.1-changelog.md b/docs/releases/v1.41.0-next.1-changelog.md new file mode 100644 index 0000000000..7efa9025d7 --- /dev/null +++ b/docs/releases/v1.41.0-next.1-changelog.md @@ -0,0 +1,2000 @@ +# Release v1.41.0-next.1 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.41.0-next.1](https://backstage.github.io/upgrade-helper/?to=1.41.0-next.1) + +## @backstage/app-defaults@1.6.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-permission-react@0.4.36-next.0 + +## @backstage/backend-app-api@1.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @backstage/backend-defaults@0.11.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/integration-aws-node@0.1.17-next.0 + - @backstage/backend-app-api@1.2.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/backend-dynamic-feature-service@0.7.2-next.1 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- 3d61c36: Fix wrong imports which lead to module initialization failures when enabling dynamic plugins. +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/plugin-app-node@0.1.35-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-catalog-backend@3.0.0-next.1 + - @backstage/plugin-events-backend@0.5.4-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/backend-openapi-utils@0.5.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/backend-openapi-utils@0.5.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @backstage/backend-plugin-api@1.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/backend-test-utils@1.7.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/backend-app-api@1.2.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/catalog-client@1.10.2-next.0 + +### Patch Changes + +- 6fb4143: allow arrays in the InMemoryCatalogClient to filter entities +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + +## @backstage/catalog-model@1.7.5-next.0 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup + +## @backstage/cli@0.33.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/integration@1.17.1-next.1 + +## @backstage/config@1.3.3-next.0 + +### Patch Changes + +- ff23618: Loosen the requirements for a key to be considered valid config. +- 3507fcd: Just some more circular dep cleanup + +## @backstage/config-loader@1.10.2-next.0 + +### Patch Changes + +- ff23618: Loosen the requirements for a key to be considered valid config. +- Updated dependencies + - @backstage/config@1.3.3-next.0 + +## @backstage/core-app-api@1.17.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/core-compat-api@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/core-components@0.17.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/core-plugin-api@1.10.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + +## @backstage/create-app@0.7.1-next.1 + +### Patch Changes + +- Bumped create-app version. + +## @backstage/dev-utils@1.1.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/app-defaults@1.6.4-next.1 + +## @backstage/frontend-app-api@0.11.4-next.1 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-defaults@0.2.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/frontend-defaults@0.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/frontend-app-api@0.11.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-app@0.1.11-next.1 + +## @backstage/frontend-dynamic-feature-loader@0.1.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/frontend-plugin-api@0.10.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/frontend-test-utils@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/frontend-app-api@0.11.4-next.1 + - @backstage/test-utils@1.7.10-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-app@0.1.11-next.1 + +## @backstage/integration@1.17.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + +## @backstage/integration-aws-node@0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + +## @backstage/integration-react@1.2.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/repo-tools@0.15.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @techdocs/cli@1.9.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/plugin-techdocs-node@1.13.5-next.1 + +## @backstage/test-utils@1.7.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-permission-react@0.4.36-next.0 + +## @backstage/plugin-api-docs@0.12.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-catalog@1.31.1-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-app@0.1.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-app-backend@0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-app-node@0.1.35-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-app-node@0.1.35-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @backstage/plugin-app-visualizer@0.1.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-auth-backend@0.25.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-auth-backend-module-atlassian-provider@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-auth0-provider@0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-aws-alb-provider@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-backend@0.25.2-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-azure-easyauth-provider@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-bitbucket-provider@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-bitbucket-server-provider@0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-cloudflare-access-provider@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-gcp-iap-provider@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-github-provider@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-gitlab-provider@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-google-provider@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-guest-provider@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-microsoft-provider@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-provider@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-oauth2-proxy-provider@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-oidc-provider@0.4.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-backend@0.25.2-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-okta-provider@0.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-onelogin-provider@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-pinniped-provider@0.3.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-backend-module-vmware-cloud-provider@0.5.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-auth-node@0.6.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @backstage/plugin-auth-react@0.1.17-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/plugin-catalog@1.31.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-scaffolder-common@1.5.12-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/plugin-search-react@1.9.2-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-catalog-backend@3.0.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/backend-openapi-utils@0.5.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-aws@0.4.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/integration@1.17.1-next.1 + - @backstage/integration-aws-node@0.1.17-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-kubernetes-common@0.9.6-next.0 + +## @backstage/plugin-catalog-backend-module-azure@0.3.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/backend-openapi-utils@0.5.5-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-kubernetes-common@0.9.6-next.0 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-catalog-backend-module-github@0.10.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-backend@3.0.0-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-backend-module-github@0.10.1-next.1 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.1-next.1 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.2-next.1 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- e2dd095: Fixed bug in `IncrementalIngestionEngine` by adding `burstLength` check when a burst completes +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-backend@3.0.0-next.1 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-ldap@0.11.7-next.0 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-catalog-backend-module-logs@0.1.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-backend@3.0.0-next.1 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-catalog-backend-module-msgraph@0.7.2-next.0 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.12-next.0 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-scaffolder-common@1.5.12-next.0 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-catalog-unprocessed-entities-common@0.0.9-next.0 + +## @backstage/plugin-catalog-common@1.1.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-catalog-graph@0.4.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-catalog-import@0.13.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-catalog-node@1.17.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + +## @backstage/plugin-catalog-react@1.19.1-next.1 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-test-utils@0.3.4-next.1 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-catalog-unprocessed-entities-common@0.0.9-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + +## @backstage/plugin-config-schema@0.1.70-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/plugin-devtools@0.1.29-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-devtools-common@0.1.17-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-devtools-backend@0.5.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-devtools-common@0.1.17-next.0 + +## @backstage/plugin-devtools-common@0.1.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + +## @backstage/plugin-events-backend@0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/backend-openapi-utils@0.5.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-aws-sqs@0.4.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-azure@0.2.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-cloud@0.2.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-bitbucket-server@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-gerrit@0.2.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-github@0.4.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-gitlab@0.3.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-google-pubsub@0.1.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-module-kafka@0.1.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-backend-test-utils@0.1.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-events-node@0.4.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @backstage/plugin-gateway-backend@1.0.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @backstage/plugin-home@0.8.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-home-react@0.1.28-next.1 + +## @backstage/plugin-home-react@0.1.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-kubernetes@0.12.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-kubernetes-common@0.9.6-next.0 + - @backstage/plugin-kubernetes-react@0.5.9-next.1 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-kubernetes-backend@0.19.8-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-kubernetes-node@0.3.2-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration-aws-node@0.1.17-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-kubernetes-common@0.9.6-next.0 + +## @backstage/plugin-kubernetes-cluster@0.0.27-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-kubernetes-common@0.9.6-next.0 + - @backstage/plugin-kubernetes-react@0.5.9-next.1 + +## @backstage/plugin-kubernetes-common@0.9.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + +## @backstage/plugin-kubernetes-node@0.3.2-next.0 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-kubernetes-common@0.9.6-next.0 + +## @backstage/plugin-kubernetes-react@0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-kubernetes-common@0.9.6-next.0 + +## @backstage/plugin-mcp-actions-backend@0.1.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-notifications@0.5.7-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-notifications-common@0.0.10-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-signals-react@0.0.15-next.0 + +## @backstage/plugin-notifications-backend@0.5.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-notifications-common@0.0.10-next.0 + - @backstage/plugin-signals-node@0.1.22-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-notifications-node@0.2.17-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-notifications-backend-module-email@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration-aws-node@0.1.17-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-notifications-common@0.0.10-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-notifications-node@0.2.17-next.0 + +## @backstage/plugin-notifications-backend-module-slack@0.1.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-notifications-common@0.0.10-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-notifications-node@0.2.17-next.0 + +## @backstage/plugin-notifications-common@0.0.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + +## @backstage/plugin-notifications-node@0.2.17-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-notifications-common@0.0.10-next.0 + - @backstage/plugin-signals-node@0.1.22-next.0 + +## @backstage/plugin-org@0.6.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-org-react@0.1.40-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/plugin-permission-backend@0.7.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-permission-backend-module-allow-all-policy@0.2.10-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-permission-common@0.9.1-next.0 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/config@1.3.3-next.0 + +## @backstage/plugin-permission-node@0.10.2-next.0 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## @backstage/plugin-permission-react@0.4.36-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/plugin-proxy-backend@0.6.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-proxy-node@0.1.6-next.0 + +## @backstage/plugin-proxy-node@0.1.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @backstage/plugin-scaffolder@1.32.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-scaffolder-common@1.5.12-next.0 + - @backstage/plugin-scaffolder-react@1.17.1-next.1 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-scaffolder-backend@2.0.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-scaffolder-backend-module-azure@0.2.11-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.12-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.1 + - @backstage/plugin-scaffolder-backend-module-gerrit@0.2.11-next.1 + - @backstage/plugin-scaffolder-backend-module-gitea@0.2.11-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.8.1-next.1 + - @backstage/plugin-scaffolder-backend-module-gitlab@0.9.3-next.1 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-scaffolder-common@1.5.12-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.10-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-scaffolder-backend-module-azure@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-bitbucket@0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.1 + - @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.1 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-cloud@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-confluence-to-markdown@0.3.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-cookiecutter@0.3.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-gcp@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-gerrit@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-gitea@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-github@0.8.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-notifications@0.1.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-notifications-common@0.0.10-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + - @backstage/plugin-notifications-node@0.2.17-next.0 + +## @backstage/plugin-scaffolder-backend-module-rails@0.5.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-sentry@0.2.11-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-backend-module-yeoman@0.4.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + - @backstage/plugin-scaffolder-node-test-utils@0.3.1-next.1 + +## @backstage/plugin-scaffolder-common@1.5.12-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + +## @backstage/plugin-scaffolder-node@0.9.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-scaffolder-common@1.5.12-next.0 + +## @backstage/plugin-scaffolder-node-test-utils@0.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/backend-test-utils@1.7.0-next.1 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + +## @backstage/plugin-scaffolder-react@1.17.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-scaffolder-common@1.5.12-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-search@1.4.28-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/plugin-search-react@1.9.2-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-search-backend@2.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/backend-openapi-utils@0.5.5-next.0 + +## @backstage/plugin-search-backend-module-catalog@0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-search-backend-module-elasticsearch@1.7.4-next.0 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/integration-aws-node@0.1.17-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-search-backend-module-explore@0.3.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-search-backend-module-pg@0.5.46-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-search-backend-module-stack-overflow-collator@0.3.11-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-search-backend-module-techdocs@0.4.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-techdocs-node@1.13.5-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-search-backend-node@1.3.13-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-search-common@1.2.19-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + +## @backstage/plugin-search-react@1.9.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-signals@0.0.21-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-signals-react@0.0.15-next.0 + +## @backstage/plugin-signals-backend@0.3.6-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-signals-node@0.1.22-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-signals-node@0.1.22-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## @backstage/plugin-signals-react@0.0.15-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-plugin-api@1.10.9-next.0 + +## @backstage/plugin-techdocs@1.13.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/plugin-search-react@1.9.2-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-auth-react@0.1.17-next.1 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.51-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/test-utils@1.7.10-next.1 + - @backstage/plugin-techdocs@1.13.2-next.1 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/plugin-catalog@1.31.1-next.1 + - @backstage/plugin-search-react@1.9.2-next.1 + +## @backstage/plugin-techdocs-backend@2.0.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/catalog-client@1.10.2-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/integration@1.17.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.4-next.1 + - @backstage/plugin-techdocs-node@1.13.5-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-catalog-node@1.17.2-next.0 + +## @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/integration@1.17.1-next.1 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-techdocs-node@1.13.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/integration-aws-node@0.1.17-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + +## @backstage/plugin-techdocs-react@1.3.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.1 + +## @backstage/plugin-user-settings@0.8.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-signals-react@0.0.15-next.0 + +## @backstage/plugin-user-settings-backend@0.3.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-signals-node@0.1.22-next.0 + +## example-app@0.2.111-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/frontend-app-api@0.11.4-next.1 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/cli@0.33.1-next.1 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-catalog-import@0.13.3-next.1 + - @backstage/plugin-home@0.8.10-next.1 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-techdocs@1.13.2-next.1 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/plugin-catalog@1.31.1-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-org@0.6.41-next.1 + - @backstage/plugin-scaffolder@1.32.1-next.1 + - @backstage/plugin-scaffolder-react@1.17.1-next.1 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/plugin-api-docs@0.12.9-next.1 + - @backstage/plugin-catalog-graph@0.4.21-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.1 + - @backstage/plugin-kubernetes@0.12.9-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.27-next.1 + - @backstage/plugin-user-settings@0.8.24-next.1 + - @backstage/app-defaults@1.6.4-next.1 + - @backstage/plugin-notifications@0.5.7-next.1 + - @backstage/plugin-search@1.4.28-next.1 + - @backstage/plugin-search-react@1.9.2-next.1 + - @backstage/plugin-signals@0.0.21-next.1 + - @backstage/plugin-auth-react@0.1.17-next.1 + - @backstage/plugin-devtools@0.1.29-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.1 + +## example-app-next@0.0.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/frontend-app-api@0.11.4-next.1 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/cli@0.33.1-next.1 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-defaults@0.2.4-next.1 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-catalog-import@0.13.3-next.1 + - @backstage/plugin-home@0.8.10-next.1 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-techdocs@1.13.2-next.1 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/plugin-catalog@1.31.1-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-org@0.6.41-next.1 + - @backstage/plugin-scaffolder@1.32.1-next.1 + - @backstage/plugin-scaffolder-react@1.17.1-next.1 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/plugin-api-docs@0.12.9-next.1 + - @backstage/plugin-catalog-graph@0.4.21-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.1 + - @backstage/plugin-kubernetes@0.12.9-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.27-next.1 + - @backstage/plugin-user-settings@0.8.24-next.1 + - @backstage/app-defaults@1.6.4-next.1 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/plugin-notifications@0.5.7-next.1 + - @backstage/plugin-search@1.4.28-next.1 + - @backstage/plugin-search-react@1.9.2-next.1 + - @backstage/plugin-signals@0.0.21-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-app@0.1.11-next.1 + - @backstage/plugin-app-visualizer@0.1.21-next.1 + - @backstage/plugin-auth-react@0.1.17-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.1 + +## example-backend@0.0.40-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/plugin-app-backend@0.5.4-next.0 + - @backstage/plugin-devtools-backend@0.5.7-next.1 + - @backstage/plugin-proxy-backend@0.6.4-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-backend@0.25.2-next.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.10-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-catalog-backend@3.0.0-next.1 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.4-next.0 + - @backstage/plugin-events-backend@0.5.4-next.0 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.2-next.0 + - @backstage/plugin-kubernetes-backend@0.19.8-next.0 + - @backstage/plugin-notifications-backend@0.5.8-next.1 + - @backstage/plugin-permission-backend@0.7.2-next.0 + - @backstage/plugin-scaffolder-backend@2.0.1-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.8.1-next.1 + - @backstage/plugin-search-backend@2.0.4-next.1 + - @backstage/plugin-search-backend-module-catalog@0.3.6-next.0 + - @backstage/plugin-search-backend-module-explore@0.3.4-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.4-next.1 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-signals-backend@0.3.6-next.0 + - @backstage/plugin-techdocs-backend@2.0.4-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.2-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.10-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.2.12-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.10-next.0 + - @backstage/plugin-mcp-actions-backend@0.1.1-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.5-next.0 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.12-next.1 + +## techdocs-cli-embedded-app@0.2.110-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/cli@0.33.1-next.1 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/test-utils@1.7.10-next.1 + - @backstage/plugin-techdocs@1.13.2-next.1 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/plugin-catalog@1.31.1-next.1 + - @backstage/app-defaults@1.6.4-next.1 + +## yarn-plugin-backstage@0.0.7-next.0 + +### Patch Changes + +- d6084b8: Fixed a bug that would prevent the yarn plugin from installing new dependencies with the `backstage:^` protocol. + +## @internal/plugin-todo-list@1.0.41-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + +## @internal/plugin-todo-list-backend@1.0.41-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + +## @internal/plugin-todo-list-common@1.0.26-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 diff --git a/docs/tooling/local-dev/debugging.md b/docs/tooling/local-dev/debugging.md index 662f04151a..6e12bb9f5f 100644 --- a/docs/tooling/local-dev/debugging.md +++ b/docs/tooling/local-dev/debugging.md @@ -65,7 +65,8 @@ In your `.vscode/launch.json`, add a new entry with the following, "runtimeExecutable": "yarn", // Specifies the runtime to execute the application. In this case, it uses `yarn` to run the script. "args": ["start", "--inspect"], // Arguments passed to the `yarn` command. Here, it runs `yarn start` with the `--inspect` flag to enable debugging. "skipFiles": ["/**"], // Tells the debugger to skip stepping into Node.js internal files during debugging. - "console": "integratedTerminal" // Specifies that the debugger should use the integrated terminal for input/output. + "console": "integratedTerminal", // Specifies that the debugger should use the integrated terminal for input/output. + "experimentalNetworking": "off" // Since Node.js 22.15.0 an additional parameter --experimental-network-inspection is added but currently not supported by Yarn } ] } diff --git a/docs/tutorials/configuring-plugin-databases.md b/docs/tutorials/configuring-plugin-databases.md index c6d9869d38..2bbe83557c 100644 --- a/docs/tutorials/configuring-plugin-databases.md +++ b/docs/tutorials/configuring-plugin-databases.md @@ -1,7 +1,6 @@ --- id: configuring-plugin-databases title: Configuring Plugin Databases -# prettier-ignore description: Guide on how to configure Backstage databases. --- diff --git a/docs/tutorials/manual-knex-rollback.md b/docs/tutorials/manual-knex-rollback.md index 14e00d6659..b0f67ba3e0 100644 --- a/docs/tutorials/manual-knex-rollback.md +++ b/docs/tutorials/manual-knex-rollback.md @@ -1,7 +1,6 @@ --- id: manual-knex-rollback title: Manual Rollback using Knex -# prettier-ignore description: Guide on how to rollback Knex migrations. --- diff --git a/docs/tutorials/setup-opentelemetry.md b/docs/tutorials/setup-opentelemetry.md index 23cd71b10f..2008e0c5e8 100644 --- a/docs/tutorials/setup-opentelemetry.md +++ b/docs/tutorials/setup-opentelemetry.md @@ -4,7 +4,7 @@ title: Setup OpenTelemetry description: Tutorial to setup OpenTelemetry metrics and traces exporters in Backstage --- -Backstage uses [OpenTelemetery](https://opentelemetry.io/) to instrument its components by reporting traces and metrics. +Backstage uses [OpenTelemetry](https://opentelemetry.io/) to instrument its components by reporting traces and metrics. This tutorial shows how to setup exporters in your Backstage backend package. For demonstration purposes we will use a Prometheus exporter, but you can adjust your solution to use another one that suits your needs; see for example the article on [OTLP exporters](https://opentelemetry.io/docs/instrumentation/js/exporters/). @@ -26,7 +26,7 @@ yarn --cwd packages/backend add \ In your `packages/backend/src` folder, create an `instrumentation.js` file. -```typescript title="in packages/backend/src/instrumentation.js" +```js title="in packages/backend/src/instrumentation.js" // Prevent from running more than once (due to worker threads) const { isMainThread } = require('node:worker_threads'); @@ -52,6 +52,42 @@ if (isMainThread) { You probably won't need all of the instrumentation inside `getNodeAutoInstrumentations()` so make sure to check the [documentation](https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node) and tweak it properly. +### Views + +The default histogram buckets for OpenTelemetry are in milliseconds, but the histograms that are created for Catalog processing emit metrics in second. You might want to adjust this to what fits your need. To do this you can use the [Views feature](https://opentelemetry.io/docs/concepts/signals/metrics/#views) like this: + +```js +const prometheus = new PrometheusExporter(); +const sdk = new NodeSDK({ + metricReader: prometheus, + views: [ + new View({ + instrumentName: 'catalog.test', + aggregation: new ExplicitBucketHistogramAggregation([ + 0.01, 0.1, 0.5, 1, 5, 10, 25, 50, 100, 500, 1000, + ]), + }), + ], +}); +``` + +The above will make all the histogram buckets use the same config. If you would like to take a more targeted approach you can do this: + +```js +const prometheus = new PrometheusExporter(); +const sdk = new NodeSDK({ + metricReader: prometheus, + views: [ + new View({ + instrumentName: 'catalog.test', + aggregation: new ExplicitBucketHistogramAggregation([ + 0, 0.01, 0.05, 0.1, 0.25, 0.5, 1, 2, 5, 10, 30, 60, 120, 300, 1000, + ]), + }), + ], +}); +``` + ## Local Development Setup It's important to setup the NodeSDK and the automatic instrumentation **before** @@ -67,13 +103,13 @@ For local development, you can add the required flag in your `packages/backend/p ... ``` -You can now start your Backstage instance as usual, using `yarn start`. +You can now start your Backstage instance as usual, using `yarn start` and you'll be able to see your metrics at: ## Production Setup In your `.dockerignore`, add this line: -``` +```text !packages/backend/src/instrumentation.js ``` diff --git a/docs/tutorials/switching-sqlite-postgres.md b/docs/tutorials/switching-sqlite-postgres.md index aec9ca2ee9..4fc405c61c 100644 --- a/docs/tutorials/switching-sqlite-postgres.md +++ b/docs/tutorials/switching-sqlite-postgres.md @@ -1,7 +1,6 @@ --- id: switching-sqlite-postgres title: Switching Backstage from SQLite to PostgreSQL -# prettier-ignore description: How to get ready for deploying Backstage to production with PostgreSQL --- diff --git a/docs/tutorials/using-backstage-proxy-within-plugin.md b/docs/tutorials/using-backstage-proxy-within-plugin.md index c82db9ff6c..58e973d891 100644 --- a/docs/tutorials/using-backstage-proxy-within-plugin.md +++ b/docs/tutorials/using-backstage-proxy-within-plugin.md @@ -1,7 +1,6 @@ --- id: using-backstage-proxy-within-plugin title: Using the Backstage Proxy from Within a Plugin -# prettier-ignore description: Guide on how to create a set of API bindings that interface with a backend via the backstage proxy --- diff --git a/microsite/blog/2020-05-22-phase-2-service-catalog.mdx b/microsite/blog/2020-05-22-phase-2-service-catalog.mdx index 81c99c7c07..9e681b9da3 100644 --- a/microsite/blog/2020-05-22-phase-2-service-catalog.mdx +++ b/microsite/blog/2020-05-22-phase-2-service-catalog.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Starting Phase 2: The Service Catalog" +title: 'Starting Phase 2: The Service Catalog' author: Stefan Ålund, Spotify authorURL: http://twitter.com/stalund authorImageURL: https://pbs.twimg.com/profile_images/121166861/6919c047c0d0edaace78c3009b28e917-user-full-200-130.generated_400x400.jpg diff --git a/microsite/blog/2020-09-08-announcing-tech-docs.mdx b/microsite/blog/2020-09-08-announcing-tech-docs.mdx index 4200ac0a65..9235eeb401 100644 --- a/microsite/blog/2020-09-08-announcing-tech-docs.mdx +++ b/microsite/blog/2020-09-08-announcing-tech-docs.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Announcing TechDocs: Spotify’s docs-like-code plugin for Backstage" +title: 'Announcing TechDocs: Spotify’s docs-like-code plugin for Backstage' author: Gary Niemen, Spotify authorURL: https://github.com/garyniemen --- diff --git a/microsite/blog/2020-10-22-cost-insights-plugin.mdx b/microsite/blog/2020-10-22-cost-insights-plugin.mdx index 1ffddd3303..293cd1c927 100644 --- a/microsite/blog/2020-10-22-cost-insights-plugin.mdx +++ b/microsite/blog/2020-10-22-cost-insights-plugin.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "New Cost Insights plugin: The engineer’s solution to taming cloud costs" +title: 'New Cost Insights plugin: The engineer’s solution to taming cloud costs' author: Janisa Anandamohan, Spotify authorURL: https://twitter.com/janisa_a --- diff --git a/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.mdx b/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.mdx index c1232a5f12..1303f0dd15 100644 --- a/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.mdx +++ b/microsite/blog/2021-01-12-new-backstage-feature-kubernetes-for-service-owners.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "New Backstage feature: Kubernetes for Service owners" +title: 'New Backstage feature: Kubernetes for Service owners' author: Matthew Clarke, Spotify authorURL: https://github.com/mclarke47 --- diff --git a/microsite/blog/2021-06-24-announcing-backstage-search-platform.mdx b/microsite/blog/2021-06-24-announcing-backstage-search-platform.mdx index bb30a3b9ec..8ac14b14d4 100644 --- a/microsite/blog/2021-06-24-announcing-backstage-search-platform.mdx +++ b/microsite/blog/2021-06-24-announcing-backstage-search-platform.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Announcing the Backstage Search platform: a customizable search tool built just for you" +title: 'Announcing the Backstage Search platform: a customizable search tool built just for you' author: Emma Indal, Spotify authorURL: https://www.linkedin.com/in/emma-indal --- diff --git a/microsite/blog/2022-03-17-backstage-1.0.mdx b/microsite/blog/2022-03-17-backstage-1.0.mdx index 6f9dd3ee09..3cade0d79f 100644 --- a/microsite/blog/2022-03-17-backstage-1.0.mdx +++ b/microsite/blog/2022-03-17-backstage-1.0.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "New release: Backstage 1.0" +title: 'New release: Backstage 1.0' author: Francesco Corti, Spotify authorURL: https://github.com/fcorti/ authorImageURL: https://avatars.githubusercontent.com/u/6010860?v=4 diff --git a/microsite/blog/2022-05-13-techdocs-addon-framework.mdx b/microsite/blog/2022-05-13-techdocs-addon-framework.mdx index 7f2a588834..37d746b3c2 100644 --- a/microsite/blog/2022-05-13-techdocs-addon-framework.mdx +++ b/microsite/blog/2022-05-13-techdocs-addon-framework.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Introducing the TechDocs Addon Framework" +title: 'Introducing the TechDocs Addon Framework' author: Gary Niemen, Spotify authorURL: https://github.com/garyniemen/ authorImageURL: https://avatars.githubusercontent.com/u/65337273?v=4 diff --git a/microsite/blog/2022-07-19-releasing-backstage-search-1.0.mdx b/microsite/blog/2022-07-19-releasing-backstage-search-1.0.mdx index 1936dd4fc3..9ff3539b0d 100644 --- a/microsite/blog/2022-07-19-releasing-backstage-search-1.0.mdx +++ b/microsite/blog/2022-07-19-releasing-backstage-search-1.0.mdx @@ -1,5 +1,4 @@ --- -# prettier-ignore title: Releasing Backstage Search 1.0 author: Emma Indal, Spotify authorURL: https://www.linkedin.com/in/emma-indal diff --git a/microsite/blog/2022-08-23-backstage-security-audit.mdx b/microsite/blog/2022-08-23-backstage-security-audit.mdx index 6b9f2f6463..9c6de6eeeb 100644 --- a/microsite/blog/2022-08-23-backstage-security-audit.mdx +++ b/microsite/blog/2022-08-23-backstage-security-audit.mdx @@ -1,5 +1,4 @@ --- -# prettier-ignore title: Backstage Security Audit & Updates author: Patrik Oldsberg, Spotify authorURL: https://github.com/Rugvip diff --git a/microsite/blog/2022-09-08-fyi-plugin-analytics-api.mdx b/microsite/blog/2022-09-08-fyi-plugin-analytics-api.mdx index aff30752ec..b07dfffc06 100644 --- a/microsite/blog/2022-09-08-fyi-plugin-analytics-api.mdx +++ b/microsite/blog/2022-09-08-fyi-plugin-analytics-api.mdx @@ -1,5 +1,4 @@ --- -# prettier-ignore title: FYI 📣 The Plugin Analytics API author: Eric Peterson, Spotify authorURL: https://github.com/iamEAP diff --git a/microsite/blog/2023-07-08-stash-adopter-post.mdx b/microsite/blog/2023-07-08-stash-adopter-post.mdx index 6c1edea764..c5fe9e03b4 100644 --- a/microsite/blog/2023-07-08-stash-adopter-post.mdx +++ b/microsite/blog/2023-07-08-stash-adopter-post.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Adopter Spotlight: How Stash simplified monitoring, ownership and true app health with microservices" +title: 'Adopter Spotlight: How Stash simplified monitoring, ownership and true app health with microservices' author: Taylor Webber, Staff Engineer, Stash --- diff --git a/microsite/blog/2023-07-28-frontside-adopter-post.mdx b/microsite/blog/2023-07-28-frontside-adopter-post.mdx index c6f3cba403..5ea73fb089 100644 --- a/microsite/blog/2023-07-28-frontside-adopter-post.mdx +++ b/microsite/blog/2023-07-28-frontside-adopter-post.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Five common traits of successful Backstage adopters" +title: 'Five common traits of successful Backstage adopters' author: Taras Mankovski, CXO, Frontside --- diff --git a/microsite/blog/2023-08-17-expedia-proof-of-value-metrics-2.mdx b/microsite/blog/2023-08-17-expedia-proof-of-value-metrics-2.mdx index 9c6e67fcf1..f7f6ddfe77 100644 --- a/microsite/blog/2023-08-17-expedia-proof-of-value-metrics-2.mdx +++ b/microsite/blog/2023-08-17-expedia-proof-of-value-metrics-2.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Expedia Group shares Backstage proof of value metrics 2.0" +title: 'Expedia Group shares Backstage proof of value metrics 2.0' author: Guillermo Manzo, Expedia Group authorURL: https://www.linkedin.com/in/guillermomanzo --- diff --git a/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx b/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx index 8b4f332d54..bd479a6a86 100644 --- a/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx +++ b/microsite/blog/2023-09-29-chicago-traiding-company-adopter-spotlight.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Adopter Spotlight: How Chicago Trading Company saved 18 months of developer effort with Backstage" +title: 'Adopter Spotlight: How Chicago Trading Company saved 18 months of developer effort with Backstage' author: Tiffany Cox, Spotify --- diff --git a/microsite/blog/2023-11-15-backstagecon-kubecon-23.mdx b/microsite/blog/2023-11-15-backstagecon-kubecon-23.mdx index 7b7f7c0f0b..cdb2d9e582 100644 --- a/microsite/blog/2023-11-15-backstagecon-kubecon-23.mdx +++ b/microsite/blog/2023-11-15-backstagecon-kubecon-23.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Wrap up: BackstageCon ‘23, KubeCon + Cloud Native NA" +title: 'Wrap up: BackstageCon ‘23, KubeCon + Cloud Native NA' author: Jorge Lainfiesta, Spotify authorURL: https://www.linkedin.com/in/jrlainfiesta/ authorImageURL: https://avatars.githubusercontent.com/u/4451393?v=4 diff --git a/microsite/blog/2024-03-27-backstagecon-kubecon-24.mdx b/microsite/blog/2024-03-27-backstagecon-kubecon-24.mdx index 2164a8732e..6dd8691d82 100644 --- a/microsite/blog/2024-03-27-backstagecon-kubecon-24.mdx +++ b/microsite/blog/2024-03-27-backstagecon-kubecon-24.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Backstage in Paris: Wrapping up BackstageCon and KubeCon + CloudNativeCon Europe 2024" +title: 'Backstage in Paris: Wrapping up BackstageCon and KubeCon + CloudNativeCon Europe 2024' author: André Wanlin, Spotify authorURL: https://github.com/awanlin authorImageURL: https://avatars.githubusercontent.com/u/67169551?v=4 diff --git a/microsite/blog/2024-04-19-community-plugins.mdx b/microsite/blog/2024-04-19-community-plugins.mdx index 49d1765bce..801a2f7437 100644 --- a/microsite/blog/2024-04-19-community-plugins.mdx +++ b/microsite/blog/2024-04-19-community-plugins.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Introducing the Backstage Community Plugins Repository" +title: 'Introducing the Backstage Community Plugins Repository' author: Ben Lambert, Spotify authorURL: https://github.com/benjdlambert authorImageURL: https://avatars.githubusercontent.com/u/3645856?v=4 diff --git a/microsite/blog/2024-06-27-backstage-engineer-journey.mdx b/microsite/blog/2024-06-27-backstage-engineer-journey.mdx index d7fac5fd46..9180a4b6d7 100644 --- a/microsite/blog/2024-06-27-backstage-engineer-journey.mdx +++ b/microsite/blog/2024-06-27-backstage-engineer-journey.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "1,186 days with Backstage: A journey through the eyes of a developer" +title: '1,186 days with Backstage: A journey through the eyes of a developer' author: Camila Loiola, Spotify authorURL: https://github.com/camilaibs authorImageURL: https://avatars.githubusercontent.com/u/6290749?v=4 diff --git a/microsite/blog/2024-12-09-kubecon-slc-24.mdx b/microsite/blog/2024-12-09-kubecon-slc-24.mdx index c3fa2f70a8..c77d82d1aa 100644 --- a/microsite/blog/2024-12-09-kubecon-slc-24.mdx +++ b/microsite/blog/2024-12-09-kubecon-slc-24.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Backstage in Salt Lake City: Highlights from BackstageCon and KubeCon + CloudNativeCon North America 2024" +title: 'Backstage in Salt Lake City: Highlights from BackstageCon and KubeCon + CloudNativeCon North America 2024' author: André Wanlin, Spotify & Camila Loiola, Spotify --- diff --git a/microsite/blog/2024-12-17-backstage-security-audit-2024.mdx b/microsite/blog/2024-12-17-backstage-security-audit-2024.mdx index f9a1afef9e..5d4294b6c6 100644 --- a/microsite/blog/2024-12-17-backstage-security-audit-2024.mdx +++ b/microsite/blog/2024-12-17-backstage-security-audit-2024.mdx @@ -1,5 +1,4 @@ --- -# prettier-ignore title: The 2024 Backstage Security Audit author: Patrik Oldsberg, Spotify authorURL: https://github.com/Rugvip diff --git a/microsite/blog/2024-12-18-backstage-wrapped-2024.mdx b/microsite/blog/2024-12-18-backstage-wrapped-2024.mdx index a136d644b5..f0e4eb8a05 100644 --- a/microsite/blog/2024-12-18-backstage-wrapped-2024.mdx +++ b/microsite/blog/2024-12-18-backstage-wrapped-2024.mdx @@ -1,5 +1,4 @@ --- -# prettier-ignore title: "Backstage Wrapped 2024: The year's Top 5 milestones and highlights" author: Patrik Oldsberg, Spotify & Ben Lambert, Spotify --- diff --git a/microsite/blog/2025-04-29-backstagecon-kubecon-25-london.mdx b/microsite/blog/2025-04-29-backstagecon-kubecon-25-london.mdx index 99da880900..3eca9563a9 100644 --- a/microsite/blog/2025-04-29-backstagecon-kubecon-25-london.mdx +++ b/microsite/blog/2025-04-29-backstagecon-kubecon-25-london.mdx @@ -1,6 +1,5 @@ --- -# prettier-ignore -title: "Backstage in London: Highlights from BackstageCon and KubeCon + CloudNativeCon Europe 2025" +title: 'Backstage in London: Highlights from BackstageCon and KubeCon + CloudNativeCon Europe 2025' author: André Wanlin, Spotify authorURL: https://github.com/awanlin authorImageURL: https://avatars.githubusercontent.com/u/67169551?v=4 diff --git a/microsite/data/plugins/daily-weather-update.yaml b/microsite/data/plugins/daily-weather-update.yaml new file mode 100644 index 0000000000..4118a4d5d6 --- /dev/null +++ b/microsite/data/plugins/daily-weather-update.yaml @@ -0,0 +1,10 @@ +--- +title: Daily Weather +author: Infosys Limited +authorUrl: https://github.com/Infosys +category: Utility +description: The Daily Weather Plugin for Backstage provides real-time weather information for a specified location using the Weatherstack API. +documentation: https://github.com/Infosys/daily-weather-plugin/tree/main/plugins/weather +iconUrl: https://github.com/Infosys/daily-weather-plugin/blob/main/plugins/weather/src/docs/plugin-logo.png?raw=true +npmPackageName: '@infosys_ltd/daily-weather-plugin' +addedDate: '2025-04-16' diff --git a/microsite/data/plugins/hetzner-cloud.yaml b/microsite/data/plugins/hetzner-cloud.yaml new file mode 100644 index 0000000000..6f1fbe3f25 --- /dev/null +++ b/microsite/data/plugins/hetzner-cloud.yaml @@ -0,0 +1,10 @@ +--- +title: Hetzner Cloud +author: Gluo NV +authorUrl: https://github.com/gluobe +category: Infrastructure +description: Integrate Hetzner Cloud resources into Backstage. +documentation: https://github.com/gluobe/hetzner-backstage-plugin/blob/main/README.md +iconUrl: https://avatars.githubusercontent.com/u/18439789?s=200&v=4 +npmPackageName: '@gluo-nv/backstage-plugin-hetzner' +addedDate: '2025-06-03' diff --git a/microsite/data/plugins/spacelift-io.yaml b/microsite/data/plugins/spacelift-io.yaml new file mode 100644 index 0000000000..fe9b48139f --- /dev/null +++ b/microsite/data/plugins/spacelift-io.yaml @@ -0,0 +1,10 @@ +--- +title: Spacelift.io +author: Spacelift.io +authorUrl: https://spacelift.io/ +category: Infrastructure +description: The Spacelift plugin allows you to manage your infrastructure directly from Backstage. Visualize your IaC stacks and trigger runs with ease. +documentation: https://docs.spacelift.io/integrations/external-integrations/backstage +iconUrl: https://avatars.githubusercontent.com/u/53318513?s=200&v=4 +npmPackageName: '@spacelift-io/backstage-integration-frontend' +addedDate: '2025-06-10' diff --git a/microsite/data/plugins/stackoverflow-teams.yaml b/microsite/data/plugins/stackoverflow-teams.yaml new file mode 100644 index 0000000000..cfe08757d3 --- /dev/null +++ b/microsite/data/plugins/stackoverflow-teams.yaml @@ -0,0 +1,10 @@ +--- +title: Stack Overflow for Teams +author: EstoesMoises +authorUrl: https://github.com/estoesmoises/ +category: Discovery +description: Provide seamless access to Stack Overflow Teams most relevant data, allowing you to display the top users, top tags, and top questions directly within Backstage. It also allows to securely create SO Teams questions from Backstage. +documentation: https://github.com/StackExchange/backstage-stackoverflow/blob/main/README.md +iconUrl: /img/stack-overflow-logo.svg +npmPackageName: 'backstage-plugin-stack-overflow-teams' +addedDate: '2025-06-10' diff --git a/microsite/data/plugins/wheel-of-names.yaml b/microsite/data/plugins/wheel-of-names.yaml new file mode 100644 index 0000000000..0377742ab0 --- /dev/null +++ b/microsite/data/plugins/wheel-of-names.yaml @@ -0,0 +1,10 @@ +--- +title: Wheel of Names +author: intive +authorUrl: https://www.intive.com/ +category: Utility +description: This plugin provides a customizable spinning wheel that can be used for random selection, decision making, or just for fun in your Backstage instance. +documentation: https://github.com/backstage/community-plugins/blob/main/workspaces/wheel-of-names/plugins/wheel-of-names/README.md +iconUrl: /img/wheel-of-names.svg +npmPackageName: '@backstage-community/plugin-wheel-of-names' +addedDate: '2025-05-21' diff --git a/microsite/docusaurus.config.ts b/microsite/docusaurus.config.ts index d71483ab8f..d7538cd12d 100644 --- a/microsite/docusaurus.config.ts +++ b/microsite/docusaurus.config.ts @@ -483,7 +483,7 @@ const config: Config = { copyright: `

Made with ❤️ at Spotify

`, }, algolia: { - apiKey: '1f0ba86672ccfc3576faa94583e5b318', + apiKey: '60d2643a9c6306463f15f8c3556e7f2e', // Owned by @Rugvip indexName: 'crawler_Backstage Docusaurus 2', appId: 'JCMFNHCHI8', searchParameters: {}, diff --git a/microsite/sidebars.ts b/microsite/sidebars.ts index 1f8d3defb7..eef7ef5ee9 100644 --- a/microsite/sidebars.ts +++ b/microsite/sidebars.ts @@ -330,7 +330,7 @@ export default { { type: 'category', label: 'Gitea', - items: ['integrations/gitea/locations'], + items: ['integrations/gitea/locations', 'integrations/gitea/discovery'], }, { type: 'category', @@ -462,6 +462,8 @@ export default { 'backend-system/core-services/token-manager', 'backend-system/core-services/url-reader', 'backend-system/core-services/user-info', + 'backend-system/core-services/actions-registry', + 'backend-system/core-services/actions', ], }, ], diff --git a/microsite/static/img/wheel-of-names.svg b/microsite/static/img/wheel-of-names.svg new file mode 100644 index 0000000000..d6f19a06fb --- /dev/null +++ b/microsite/static/img/wheel-of-names.svg @@ -0,0 +1,4 @@ + + + + diff --git a/microsite/yarn.lock b/microsite/yarn.lock index e6454c4e82..40a000df33 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -4430,12 +4430,12 @@ __metadata: linkType: hard "brace-expansion@npm:^1.1.7": - version: 1.1.11 - resolution: "brace-expansion@npm:1.1.11" + version: 1.1.12 + resolution: "brace-expansion@npm:1.1.12" dependencies: balanced-match: "npm:^1.0.0" concat-map: "npm:0.0.1" - checksum: 10/faf34a7bb0c3fcf4b59c7808bc5d2a96a40988addf2e7e09dfbb67a2251800e0d14cd2bfc1aa79174f2f5095c54ff27f46fb1289fe2d77dac755b5eb3434cc07 + checksum: 10/12cb6d6310629e3048cadb003e1aca4d8c9bb5c67c3c321bafdd7e7a50155de081f78ea3e0ed92ecc75a9015e784f301efc8132383132f4f7904ad1ac529c562 languageName: node linkType: hard @@ -5942,11 +5942,11 @@ __metadata: linkType: hard "docusaurus-pushfeedback@npm:^1.0.0": - version: 1.0.3 - resolution: "docusaurus-pushfeedback@npm:1.0.3" + version: 1.0.5 + resolution: "docusaurus-pushfeedback@npm:1.0.5" peerDependencies: "@docusaurus/core": 3.x - checksum: 10/ee80ae0c1fc079b2c317cab86d83ba50cce18938a6ce0ac647aad25dc68fc0ad659e55c11e93d0e7c23270c503c3cb300111dfbdd04785ef7aaf6fb123b57eae + checksum: 10/5323af7f1c7b4590744ea9099cacb49087d98c48c11e2ed957ed744d6210a3d82fa0cc42ef0f011f25b0d08c2d0040065c8a2b641c7c9160532ceb51ad41475c languageName: node linkType: hard diff --git a/mkdocs.yml b/mkdocs.yml index 688ca1a078..eea5fc9c40 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -126,6 +126,9 @@ nav: - GitLab: - Locations: 'integrations/gitlab/locations.md' - Discovery: 'integrations/gitlab/discovery.md' + - Gitea: + - Locations: 'integrations/gitea/locations.md' + - Discovery: 'integrations/gitea/discovery.md' - Google GCS: - Locations: 'integrations/google-cloud-storage/locations.md' - LDAP: diff --git a/package.json b/package.json index 35c1d8e24b..c6b82cdcc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "root", - "version": "1.39.0", + "version": "1.41.0-next.1", "backstage": { "cli": { "new": { @@ -40,6 +40,7 @@ "postinstall": "husky || true", "lint": "backstage-cli repo lint --since origin/master", "lint:all": "backstage-cli repo lint", + "lint:circular-deps": "madge --circular .", "lint:docs": "node ./scripts/check-docs-quality", "lint:peer-deps": "backstage-repo-tools peer-deps", "lint:type-deps": "backstage-repo-tools type-deps", @@ -108,7 +109,8 @@ "csstype@npm:^3.0.2": "3.0.9", "csstype@npm:^3.1.2": "3.0.9", "csstype@npm:^3.1.3": "3.0.9", - "jest-haste-map@^29.7.0": "patch:jest-haste-map@npm%3A29.7.0#./.yarn/patches/jest-haste-map-npm-29.7.0-e3be419eff.patch" + "jest-haste-map@^29.7.0": "patch:jest-haste-map@npm%3A29.7.0#./.yarn/patches/jest-haste-map-npm-29.7.0-e3be419eff.patch", + "GendocuPublicApis": "npm:gendocu-public-apis@^1.0.0" }, "dependencies": { "@backstage/errors": "workspace:^", @@ -122,6 +124,7 @@ "@backstage/codemods": "workspace:*", "@backstage/create-app": "workspace:*", "@backstage/e2e-test-utils": "workspace:*", + "@backstage/eslint-plugin": "workspace:*", "@backstage/repo-tools": "workspace:*", "@changesets/cli": "^2.14.0", "@octokit/rest": "^19.0.3", @@ -143,6 +146,7 @@ "fs-extra": "^11.2.0", "husky": "^9.0.0", "lint-staged": "^15.0.0", + "madge": "^8.0.0", "minimist": "^1.2.5", "node-gyp": "^10.0.0", "prettier": "^2.2.1", @@ -156,5 +160,22 @@ "packageManager": "yarn@4.8.1", "engines": { "node": "20 || 22" + }, + "madge": { + "fileExtensions": [ + "ts", + "tsx", + "js", + "jsx" + ], + "detectiveOptions": { + "ts": { + "skipTypeImports": true + }, + "tsx": { + "skipTypeImports": true + } + }, + "tsConfig": "./tsconfig.json" } } diff --git a/packages/app-defaults/CHANGELOG.md b/packages/app-defaults/CHANGELOG.md index b798c5a20e..7801ca54a5 100644 --- a/packages/app-defaults/CHANGELOG.md +++ b/packages/app-defaults/CHANGELOG.md @@ -1,5 +1,48 @@ # @backstage/app-defaults +## 1.6.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/plugin-permission-react@0.4.36-next.0 + +## 1.6.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/theme@0.6.7-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/plugin-permission-react@0.4.35 + +## 1.6.3 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/core-plugin-api@1.10.8 + - @backstage/core-app-api@1.17.1 + - @backstage/theme@0.6.6 + - @backstage/plugin-permission-react@0.4.35 + +## 1.6.3-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-permission-react@0.4.34 + ## 1.6.2 ### Patch Changes diff --git a/packages/app-defaults/package.json b/packages/app-defaults/package.json index 3969bf8a2e..4c9feb7699 100644 --- a/packages/app-defaults/package.json +++ b/packages/app-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/app-defaults", - "version": "1.6.2", + "version": "1.6.4-next.1", "description": "Provides the default wiring of a Backstage App", "backstage": { "role": "web-library" diff --git a/packages/app-next-example-plugin/CHANGELOG.md b/packages/app-next-example-plugin/CHANGELOG.md index aca60c550b..f74cafd0bd 100644 --- a/packages/app-next-example-plugin/CHANGELOG.md +++ b/packages/app-next-example-plugin/CHANGELOG.md @@ -1,5 +1,36 @@ # app-next-example-plugin +## 0.0.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.4-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.0 + +## 0.0.24 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3 + - @backstage/frontend-plugin-api@0.10.3 + +## 0.0.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + +## 0.0.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/frontend-plugin-api@0.10.3-next.0 + ## 0.0.23 ### Patch Changes diff --git a/packages/app-next-example-plugin/package.json b/packages/app-next-example-plugin/package.json index 71622bff6a..a63559a9f7 100644 --- a/packages/app-next-example-plugin/package.json +++ b/packages/app-next-example-plugin/package.json @@ -1,6 +1,6 @@ { "name": "app-next-example-plugin", - "version": "0.0.23", + "version": "0.0.25-next.0", "description": "Backstage internal example plugin", "backstage": { "role": "frontend-plugin", diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index ab9a0067db..d0b92f88c7 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,314 @@ # example-app-next +## 0.0.25-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/frontend-app-api@0.11.4-next.1 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/cli@0.33.1-next.1 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/frontend-defaults@0.2.4-next.1 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-catalog-import@0.13.3-next.1 + - @backstage/plugin-home@0.8.10-next.1 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-techdocs@1.13.2-next.1 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/plugin-catalog@1.31.1-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-org@0.6.41-next.1 + - @backstage/plugin-scaffolder@1.32.1-next.1 + - @backstage/plugin-scaffolder-react@1.17.1-next.1 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/plugin-api-docs@0.12.9-next.1 + - @backstage/plugin-catalog-graph@0.4.21-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.1 + - @backstage/plugin-kubernetes@0.12.9-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.27-next.1 + - @backstage/plugin-user-settings@0.8.24-next.1 + - @backstage/app-defaults@1.6.4-next.1 + - @backstage/core-compat-api@0.4.4-next.1 + - @backstage/plugin-notifications@0.5.7-next.1 + - @backstage/plugin-search@1.4.28-next.1 + - @backstage/plugin-search-react@1.9.2-next.1 + - @backstage/plugin-signals@0.0.21-next.1 + - @backstage/frontend-plugin-api@0.10.4-next.1 + - @backstage/plugin-app@0.1.11-next.1 + - @backstage/plugin-app-visualizer@0.1.21-next.1 + - @backstage/plugin-auth-react@0.1.17-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.1 + +## 0.0.25-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.2-next.0 + - @backstage/plugin-catalog-graph@0.4.21-next.0 + - @backstage/canon@0.6.0-next.0 + - @backstage/plugin-scaffolder@1.32.1-next.0 + - @backstage/plugin-catalog-import@0.13.2-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/theme@0.6.7-next.0 + - @backstage/cli@0.33.1-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.0 + - @backstage/plugin-app@0.1.11-next.0 + - @backstage/plugin-catalog@1.31.1-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/app-defaults@1.6.4-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-home@0.8.10-next.0 + - @backstage/plugin-notifications@0.5.7-next.0 + - @backstage/plugin-scaffolder-react@1.17.1-next.0 + - @backstage/plugin-search-react@1.9.2-next.0 + - @backstage/plugin-signals@0.0.21-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/plugin-user-settings@0.8.24-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-compat-api@0.4.4-next.0 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-app-api@0.11.4-next.0 + - @backstage/frontend-defaults@0.2.4-next.0 + - @backstage/frontend-plugin-api@0.10.4-next.0 + - @backstage/plugin-api-docs@0.12.9-next.0 + - @backstage/plugin-app-visualizer@0.1.21-next.0 + - @backstage/plugin-auth-react@0.1.17-next.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.0 + - @backstage/plugin-kubernetes@0.12.9-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.27-next.0 + - @backstage/plugin-org@0.6.41-next.0 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-search@1.4.28-next.0 + - @backstage/plugin-search-common@1.2.18 + +## 0.0.24 + +### Patch Changes + +- Updated dependencies + - @backstage/canon@0.5.0 + - @backstage/core-components@0.17.3 + - @backstage/cli@0.33.0 + - @backstage/plugin-scaffolder-react@1.17.0 + - @backstage/plugin-scaffolder@1.32.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18 + - @backstage/plugin-app-visualizer@0.1.20 + - @backstage/plugin-catalog-import@0.13.1 + - @backstage/plugin-catalog-graph@0.4.20 + - @backstage/plugin-notifications@0.5.6 + - @backstage/plugin-user-settings@0.8.23 + - @backstage/plugin-kubernetes@0.12.8 + - @backstage/plugin-api-docs@0.12.8 + - @backstage/plugin-techdocs@1.13.0 + - @backstage/plugin-catalog@1.31.0 + - @backstage/plugin-signals@0.0.20 + - @backstage/plugin-search@1.4.27 + - @backstage/plugin-home@0.8.9 + - @backstage/plugin-app@0.1.10 + - @backstage/plugin-org@0.6.40 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-plugin-api@0.10.3 + - @backstage/frontend-app-api@0.11.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/frontend-defaults@0.2.3 + - @backstage/plugin-search-react@1.9.1 + - @backstage/app-defaults@1.6.3 + - @backstage/integration-react@1.2.8 + - @backstage/plugin-auth-react@0.1.16 + - @backstage/plugin-kubernetes-cluster@0.0.26 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-compat-api@0.4.3 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-search-common@1.2.18 + +## 0.0.24-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.33.0-next.2 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/canon@0.5.0-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/frontend-defaults@0.2.3-next.1 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-api-docs@0.12.8-next.2 + - @backstage/plugin-app@0.1.10-next.1 + - @backstage/plugin-app-visualizer@0.1.20-next.1 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-graph@0.4.20-next.2 + - @backstage/plugin-catalog-import@0.13.1-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + - @backstage/plugin-home@0.8.9-next.2 + - @backstage/plugin-kubernetes@0.12.8-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + - @backstage/plugin-notifications@0.5.6-next.2 + - @backstage/plugin-org@0.6.40-next.2 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder@1.32.0-next.2 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/plugin-search@1.4.27-next.2 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/plugin-signals@0.0.20-next.1 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/plugin-user-settings@0.8.23-next.2 + +## 0.0.24-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/cli@0.33.0-next.1 + - @backstage/canon@0.5.0-next.2 + - @backstage/plugin-notifications@0.5.6-next.2 + - @backstage/plugin-scaffolder@1.32.0-next.2 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-catalog-import@0.13.1-next.2 + - @backstage/plugin-home@0.8.9-next.2 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-api-docs@0.12.8-next.2 + - @backstage/plugin-app@0.1.10-next.1 + - @backstage/plugin-app-visualizer@0.1.20-next.1 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-catalog-graph@0.4.20-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + - @backstage/plugin-kubernetes@0.12.8-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + - @backstage/plugin-org@0.6.40-next.2 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/plugin-search@1.4.27-next.2 + - @backstage/plugin-signals@0.0.20-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/plugin-user-settings@0.8.23-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/frontend-defaults@0.2.3-next.1 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-search-common@1.2.18 + +## 0.0.24-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/canon@0.5.0-next.1 + - @backstage/cli@0.32.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.1 + - @backstage/plugin-techdocs@1.13.0-next.1 + - @backstage/plugin-org@0.6.40-next.1 + - @backstage/plugin-user-settings@0.8.23-next.1 + - @backstage/plugin-notifications@0.5.6-next.1 + - @backstage/plugin-catalog@1.31.0-next.1 + - @backstage/plugin-catalog-graph@0.4.20-next.1 + - @backstage/plugin-catalog-import@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/plugin-home@0.8.9-next.1 + - @backstage/plugin-scaffolder@1.31.1-next.1 + - @backstage/plugin-scaffolder-react@1.16.1-next.1 + - @backstage/app-defaults@1.6.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-compat-api@0.4.3-next.1 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.0 + - @backstage/frontend-defaults@0.2.3-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-api-docs@0.12.8-next.1 + - @backstage/plugin-app@0.1.10-next.0 + - @backstage/plugin-app-visualizer@0.1.20-next.0 + - @backstage/plugin-auth-react@0.1.15 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.1 + - @backstage/plugin-kubernetes@0.12.8-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.1 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-search@1.4.27-next.1 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-signals@0.0.20-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## 0.0.24-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.31.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.0 + - @backstage/plugin-app-visualizer@0.1.20-next.0 + - @backstage/plugin-catalog-import@0.13.1-next.0 + - @backstage/plugin-catalog-graph@0.4.20-next.0 + - @backstage/plugin-notifications@0.5.6-next.0 + - @backstage/plugin-user-settings@0.8.23-next.0 + - @backstage/plugin-kubernetes@0.12.8-next.0 + - @backstage/plugin-api-docs@0.12.8-next.0 + - @backstage/plugin-techdocs@1.13.0-next.0 + - @backstage/plugin-catalog@1.31.0-next.0 + - @backstage/plugin-signals@0.0.20-next.0 + - @backstage/plugin-search@1.4.27-next.0 + - @backstage/plugin-home@0.8.9-next.0 + - @backstage/plugin-app@0.1.10-next.0 + - @backstage/plugin-org@0.6.40-next.0 + - @backstage/frontend-plugin-api@0.10.3-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/frontend-defaults@0.2.3-next.0 + - @backstage/frontend-app-api@0.11.3-next.0 + - @backstage/canon@0.5.0-next.0 + - @backstage/core-compat-api@0.4.3-next.0 + - @backstage/plugin-scaffolder-react@1.16.1-next.0 + - @backstage/cli@0.32.1 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.0 + - @backstage/integration-react@1.2.7 + ## 0.0.23 ### Patch Changes diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index 0e6dd0a356..da233b0188 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -8,6 +8,20 @@ app: catalog.createComponent: catalog-import.importPage org.catalogIndex: catalog.catalogIndex + pluginOverrides: + - match: + pluginId: pages + info: + description: 'This description was overridden in packages/app-next/app-config.yaml' + - match: + pluginId: /^catalog(-.*)?$/ + info: + ownerEntityRefs: [cubic-belugas] + - match: + packageName: '@backstage/plugin-scaffolder' + info: + ownerEntityRefs: [cubic-belugas] + extensions: # - apis.plugin.graphiql.browse.gitlab: true # - graphiql-endpoint:graphiql/gitlab: true diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 9d8e7665af..6ac4c89632 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.23", + "version": "0.0.25-next.1", "backstage": { "role": "frontend" }, diff --git a/packages/app-next/src/App.tsx b/packages/app-next/src/App.tsx index 0ecb46e06a..43cc63d1a4 100644 --- a/packages/app-next/src/App.tsx +++ b/packages/app-next/src/App.tsx @@ -43,6 +43,7 @@ import kubernetesPlugin from '@backstage/plugin-kubernetes/alpha'; import { convertLegacyPlugin } from '@backstage/core-compat-api'; import { convertLegacyPageExtension } from '@backstage/core-compat-api'; import { convertLegacyEntityContentExtension } from '@backstage/plugin-catalog-react/alpha'; +import { pluginInfoResolver } from './pluginInfoResolver'; /* @@ -132,6 +133,7 @@ const app = createApp({ customHomePageModule, ...collectedLegacyPlugins, ], + pluginInfoResolver, /* Handled through config instead */ // bindRoutes({ bind }) { // bind(pagesPlugin.externalRoutes, { pageX: pagesPlugin.routes.pageX }); diff --git a/packages/app-next/src/examples/pagesPlugin.tsx b/packages/app-next/src/examples/pagesPlugin.tsx index ddd080c28b..33fc7d8c0b 100644 --- a/packages/app-next/src/examples/pagesPlugin.tsx +++ b/packages/app-next/src/examples/pagesPlugin.tsx @@ -21,7 +21,10 @@ import { createExternalRouteRef, useRouteRef, PageBlueprint, + FrontendPluginInfo, + useAppNode, } from '@backstage/frontend-plugin-api'; +import { useEffect, useState } from 'react'; import { Route, Routes } from 'react-router-dom'; const indexRouteRef = createRouteRef(); @@ -36,6 +39,22 @@ export const pageXRouteRef = createRouteRef(); // path: '/page2', // }); +function PluginInfo() { + const node = useAppNode(); + const [info, setInfo] = useState(undefined); + + useEffect(() => { + node?.spec.source?.info().then(setInfo); + }, [node]); + + return ( +
+

Plugin Info

+
{JSON.stringify(info, null, 2)}
+
+ ); +} + const IndexPage = PageBlueprint.make({ name: 'index', params: { @@ -64,6 +83,7 @@ const IndexPage = PageBlueprint.make({
Settings
+
); }; @@ -139,6 +159,10 @@ export const pagesPlugin = createFrontendPlugin({ // // OR // // 'page1' // }, + info: { + packageJson: () => import('../../package.json'), + manifest: () => import('../../catalog-info.yaml'), + }, routes: { page1: page1RouteRef, pageX: pageXRouteRef, diff --git a/packages/app-next/src/pluginInfoResolver.ts b/packages/app-next/src/pluginInfoResolver.ts new file mode 100644 index 0000000000..12f730875c --- /dev/null +++ b/packages/app-next/src/pluginInfoResolver.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2025 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 { Entity } from '@backstage/catalog-model'; +import { FrontendPluginInfoResolver } from '@backstage/frontend-app-api'; + +// This file shows an example of what it looks like to extend the plugin info +// resolution with custom logic and fields. In this case we're reading the +// `spec.type` field from the plugin manifest (catalog-info.yaml). +// +// Using module augmentation we extend the `FrontendPluginInfo` interface to +// include our custom fields. This makes these fields available throughout our project. + +declare module '@backstage/frontend-plugin-api' { + export interface FrontendPluginInfo { + /** + * **DO NOT USE** + * + * This field is added in the example app to showcase module augmentation + * for extending the plugin info in internal apps. It only exists as an + * example in this project. + */ + exampleFieldDoNotUse?: string; + } +} + +export const pluginInfoResolver: FrontendPluginInfoResolver = async ctx => { + const manifest = (await ctx.manifest?.()) as Entity | undefined; + const { info: defaultInfo } = await ctx.defaultResolver({ + packageJson: await ctx.packageJson(), + manifest: manifest, + }); + return { + info: { + ...defaultInfo, + exampleFieldDoNotUse: manifest?.spec?.type?.toString(), + }, + }; +}; diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index b59945d5cd..fdf8e4f942 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,286 @@ # example-app +## 0.2.111-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/frontend-app-api@0.11.4-next.1 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.1 + - @backstage/cli@0.33.1-next.1 + - @backstage/core-app-api@1.17.2-next.0 + - @backstage/core-components@0.17.4-next.1 + - @backstage/core-plugin-api@1.10.9-next.0 + - @backstage/integration-react@1.2.9-next.1 + - @backstage/plugin-catalog-import@0.13.3-next.1 + - @backstage/plugin-home@0.8.10-next.1 + - @backstage/plugin-permission-react@0.4.36-next.0 + - @backstage/plugin-techdocs@1.13.2-next.1 + - @backstage/plugin-techdocs-react@1.3.1-next.1 + - @backstage/plugin-catalog@1.31.1-next.1 + - @backstage/plugin-catalog-common@1.1.5-next.0 + - @backstage/plugin-org@0.6.41-next.1 + - @backstage/plugin-scaffolder@1.32.1-next.1 + - @backstage/plugin-scaffolder-react@1.17.1-next.1 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/plugin-api-docs@0.12.9-next.1 + - @backstage/plugin-catalog-graph@0.4.21-next.1 + - @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.1 + - @backstage/plugin-kubernetes@0.12.9-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.27-next.1 + - @backstage/plugin-user-settings@0.8.24-next.1 + - @backstage/app-defaults@1.6.4-next.1 + - @backstage/plugin-notifications@0.5.7-next.1 + - @backstage/plugin-search@1.4.28-next.1 + - @backstage/plugin-search-react@1.9.2-next.1 + - @backstage/plugin-signals@0.0.21-next.1 + - @backstage/plugin-auth-react@0.1.17-next.1 + - @backstage/plugin-devtools@0.1.29-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.1 + +## 0.2.111-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-techdocs@1.13.2-next.0 + - @backstage/plugin-catalog-graph@0.4.21-next.0 + - @backstage/canon@0.6.0-next.0 + - @backstage/plugin-scaffolder@1.32.1-next.0 + - @backstage/plugin-catalog-import@0.13.2-next.0 + - @backstage/integration-react@1.2.9-next.0 + - @backstage/theme@0.6.7-next.0 + - @backstage/cli@0.33.1-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.26-next.0 + - @backstage/plugin-catalog@1.31.1-next.0 + - @backstage/plugin-catalog-react@1.19.1-next.0 + - @backstage/app-defaults@1.6.4-next.0 + - @backstage/core-components@0.17.4-next.0 + - @backstage/plugin-home@0.8.10-next.0 + - @backstage/plugin-notifications@0.5.7-next.0 + - @backstage/plugin-scaffolder-react@1.17.1-next.0 + - @backstage/plugin-search-react@1.9.2-next.0 + - @backstage/plugin-signals@0.0.21-next.0 + - @backstage/plugin-techdocs-react@1.3.1-next.0 + - @backstage/plugin-user-settings@0.8.24-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-app-api@0.11.4-next.0 + - @backstage/plugin-api-docs@0.12.9-next.0 + - @backstage/plugin-auth-react@0.1.17-next.0 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.19-next.0 + - @backstage/plugin-devtools@0.1.29-next.0 + - @backstage/plugin-kubernetes@0.12.9-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.27-next.0 + - @backstage/plugin-org@0.6.41-next.0 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-search@1.4.28-next.0 + - @backstage/plugin-search-common@1.2.18 + +## 0.2.110 + +### Patch Changes + +- Updated dependencies + - @backstage/canon@0.5.0 + - @backstage/core-components@0.17.3 + - @backstage/cli@0.33.0 + - @backstage/plugin-scaffolder-react@1.17.0 + - @backstage/plugin-scaffolder@1.32.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18 + - @backstage/plugin-catalog-import@0.13.1 + - @backstage/plugin-catalog-graph@0.4.20 + - @backstage/plugin-notifications@0.5.6 + - @backstage/plugin-user-settings@0.8.23 + - @backstage/plugin-kubernetes@0.12.8 + - @backstage/plugin-api-docs@0.12.8 + - @backstage/plugin-devtools@0.1.28 + - @backstage/plugin-techdocs@1.13.0 + - @backstage/plugin-catalog@1.31.0 + - @backstage/plugin-signals@0.0.20 + - @backstage/plugin-search@1.4.27 + - @backstage/plugin-home@0.8.9 + - @backstage/plugin-org@0.6.40 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25 + - @backstage/core-plugin-api@1.10.8 + - @backstage/frontend-app-api@0.11.3 + - @backstage/plugin-catalog-react@1.19.0 + - @backstage/plugin-techdocs-react@1.3.0 + - @backstage/plugin-search-react@1.9.1 + - @backstage/app-defaults@1.6.3 + - @backstage/integration-react@1.2.8 + - @backstage/plugin-auth-react@0.1.16 + - @backstage/plugin-kubernetes-cluster@0.0.26 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.1 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.35 + - @backstage/plugin-search-common@1.2.18 + +## 0.2.110-next.3 + +### Patch Changes + +- Updated dependencies + - @backstage/cli@0.33.0-next.2 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/canon@0.5.0-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-components@0.17.3-next.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-api-docs@0.12.8-next.2 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-graph@0.4.20-next.2 + - @backstage/plugin-catalog-import@0.13.1-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + - @backstage/plugin-devtools@0.1.28-next.2 + - @backstage/plugin-home@0.8.9-next.2 + - @backstage/plugin-kubernetes@0.12.8-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + - @backstage/plugin-notifications@0.5.6-next.2 + - @backstage/plugin-org@0.6.40-next.2 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-scaffolder@1.32.0-next.2 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/plugin-search@1.4.27-next.2 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/plugin-signals@0.0.20-next.1 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/plugin-user-settings@0.8.23-next.2 + +## 0.2.110-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.3-next.0 + - @backstage/cli@0.33.0-next.1 + - @backstage/canon@0.5.0-next.2 + - @backstage/plugin-notifications@0.5.6-next.2 + - @backstage/plugin-scaffolder@1.32.0-next.2 + - @backstage/plugin-catalog@1.31.0-next.2 + - @backstage/plugin-techdocs@1.13.0-next.2 + - @backstage/plugin-catalog-react@1.19.0-next.2 + - @backstage/plugin-catalog-import@0.13.1-next.2 + - @backstage/plugin-home@0.8.9-next.2 + - @backstage/plugin-search-react@1.9.1-next.1 + - @backstage/app-defaults@1.6.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/plugin-api-docs@0.12.8-next.2 + - @backstage/plugin-auth-react@0.1.16-next.0 + - @backstage/plugin-catalog-graph@0.4.20-next.2 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.2 + - @backstage/plugin-devtools@0.1.28-next.2 + - @backstage/plugin-kubernetes@0.12.8-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.2 + - @backstage/plugin-org@0.6.40-next.2 + - @backstage/plugin-scaffolder-react@1.16.1-next.2 + - @backstage/plugin-search@1.4.27-next.2 + - @backstage/plugin-signals@0.0.20-next.1 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.2 + - @backstage/plugin-techdocs-react@1.3.0-next.1 + - @backstage/plugin-user-settings@0.8.23-next.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.1 + - @backstage/theme@0.6.6 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-search-common@1.2.18 + +## 0.2.110-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/canon@0.5.0-next.1 + - @backstage/cli@0.32.2-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.1 + - @backstage/plugin-techdocs@1.13.0-next.1 + - @backstage/plugin-org@0.6.40-next.1 + - @backstage/plugin-user-settings@0.8.23-next.1 + - @backstage/plugin-notifications@0.5.6-next.1 + - @backstage/plugin-catalog@1.31.0-next.1 + - @backstage/plugin-catalog-graph@0.4.20-next.1 + - @backstage/plugin-catalog-import@0.13.1-next.1 + - @backstage/plugin-catalog-react@1.18.1-next.1 + - @backstage/plugin-home@0.8.9-next.1 + - @backstage/plugin-scaffolder@1.31.1-next.1 + - @backstage/plugin-scaffolder-react@1.16.1-next.1 + - @backstage/app-defaults@1.6.2 + - @backstage/catalog-model@1.7.4 + - @backstage/config@1.3.2 + - @backstage/core-app-api@1.17.0 + - @backstage/core-components@0.17.2 + - @backstage/core-plugin-api@1.10.7 + - @backstage/frontend-app-api@0.11.3-next.0 + - @backstage/integration-react@1.2.7 + - @backstage/theme@0.6.6 + - @backstage/plugin-api-docs@0.12.8-next.1 + - @backstage/plugin-auth-react@0.1.15 + - @backstage/plugin-catalog-common@1.1.4 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.1 + - @backstage/plugin-devtools@0.1.28-next.1 + - @backstage/plugin-kubernetes@0.12.8-next.1 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.1 + - @backstage/plugin-permission-react@0.4.34 + - @backstage/plugin-search@1.4.27-next.1 + - @backstage/plugin-search-common@1.2.18 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-signals@0.0.20-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + +## 0.2.110-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder@1.31.1-next.0 + - @backstage/plugin-catalog-unprocessed-entities@0.2.18-next.0 + - @backstage/plugin-catalog-import@0.13.1-next.0 + - @backstage/plugin-catalog-graph@0.4.20-next.0 + - @backstage/plugin-notifications@0.5.6-next.0 + - @backstage/plugin-user-settings@0.8.23-next.0 + - @backstage/plugin-kubernetes@0.12.8-next.0 + - @backstage/plugin-api-docs@0.12.8-next.0 + - @backstage/plugin-devtools@0.1.28-next.0 + - @backstage/plugin-techdocs@1.13.0-next.0 + - @backstage/plugin-catalog@1.31.0-next.0 + - @backstage/plugin-signals@0.0.20-next.0 + - @backstage/plugin-search@1.4.27-next.0 + - @backstage/plugin-home@0.8.9-next.0 + - @backstage/plugin-org@0.6.40-next.0 + - @backstage/plugin-techdocs-react@1.3.0-next.0 + - @backstage/frontend-app-api@0.11.3-next.0 + - @backstage/canon@0.5.0-next.0 + - @backstage/plugin-scaffolder-react@1.16.1-next.0 + - @backstage/cli@0.32.1 + - @backstage/plugin-catalog-react@1.18.1-next.0 + - @backstage/plugin-search-react@1.9.1-next.0 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.25-next.0 + - @backstage/plugin-kubernetes-cluster@0.0.26-next.0 + - @backstage/integration-react@1.2.7 + ## 0.2.109 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 604443a0b2..b96d4f55ca 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.109", + "version": "0.2.111-next.1", "backstage": { "role": "frontend" }, diff --git a/packages/app/src/apis.ts b/packages/app/src/apis.ts index e39122337f..5d300d67cb 100644 --- a/packages/app/src/apis.ts +++ b/packages/app/src/apis.ts @@ -24,11 +24,14 @@ import { configApiRef, createApiFactory, discoveryApiRef, + fetchApiRef, } from '@backstage/core-plugin-api'; import { AuthProxyDiscoveryApi } from './AuthProxyDiscoveryApi'; import { formDecoratorsApiRef } from '@backstage/plugin-scaffolder/alpha'; import { DefaultScaffolderFormDecoratorsApi } from '@backstage/plugin-scaffolder/alpha'; import { mockDecorator } from './components/scaffolder/decorators'; +import { scaffolderApiRef } from '@backstage/plugin-scaffolder-react'; +import { ScaffolderClient } from '@backstage/plugin-scaffolder'; export const apis: AnyApiFactory[] = [ createApiFactory({ @@ -42,6 +45,22 @@ export const apis: AnyApiFactory[] = [ factory: ({ configApi }) => ScmIntegrationsApi.fromConfig(configApi), }), + createApiFactory({ + api: scaffolderApiRef, + deps: { + discoveryApi: discoveryApiRef, + fetchApi: fetchApiRef, + scmIntegrationsApi: scmIntegrationsApiRef, + }, + factory: ({ discoveryApi, fetchApi, scmIntegrationsApi }) => + new ScaffolderClient({ + useLongPollingLogs: true, + discoveryApi, + fetchApi, + scmIntegrationsApi, + }), + }), + createApiFactory({ api: formDecoratorsApiRef, deps: {}, diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index 6f2c85c934..cbf1bcb5f8 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -17,14 +17,9 @@ import { PropsWithChildren } from 'react'; import { makeStyles } from '@material-ui/core/styles'; import HomeIcon from '@material-ui/icons/Home'; -import RuleIcon from '@material-ui/icons/AssignmentTurnedIn'; -import MapIcon from '@material-ui/icons/MyLocation'; -import LayersIcon from '@material-ui/icons/Layers'; -import PlaylistPlayIcon from '@material-ui/icons/PlaylistPlay'; import CreateComponentIcon from '@material-ui/icons/AddCircleOutline'; import SearchIcon from '@material-ui/icons/Search'; import MenuIcon from '@material-ui/icons/Menu'; -import MoneyIcon from '@material-ui/icons/MonetizationOn'; import LogoFull from './LogoFull'; import LogoIcon from './LogoIcon'; import { @@ -48,10 +43,11 @@ import { } from '@backstage/core-components'; import { MyGroupsSidebarItem } from '@backstage/plugin-org'; import { SearchModal } from '../search/SearchModal'; -import Score from '@material-ui/icons/Score'; import { useApp } from '@backstage/core-plugin-api'; import BuildIcon from '@material-ui/icons/Build'; import { NotificationsSidebarItem } from '@backstage/plugin-notifications'; +import UpdateIcon from '@material-ui/icons/Update'; +import CategoryIcon from '@material-ui/icons/Category'; const useSidebarLogoStyles = makeStyles({ root: { @@ -93,7 +89,8 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( }> {/* Global nav, not org-specific */} - + + ) => ( to="docs" text="Docs" /> - - {/* End global nav */} - - - - - - + + } diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index 6c469e9a98..361929da12 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,49 @@ # @backstage/backend-app-api +## 1.2.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + +## 1.2.4 + +### Patch Changes + +- bb9a501: Fixed a bug where occasionally the initialization order of multiple modules consuming a single extension point could happen in the wrong order. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## 1.2.4-next.2 + +### Patch Changes + +- bb9a501: Fixed a bug where occasionally the initialization order of multiple modules consuming a single extension point could happen in the wrong order. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## 1.2.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + +## 1.2.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + ## 1.2.3 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index 8e894421f5..41abc33e1c 100644 --- a/packages/backend-app-api/package.json +++ b/packages/backend-app-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-app-api", - "version": "1.2.3", + "version": "1.2.5-next.0", "description": "Core API used by Backstage backend apps", "backstage": { "role": "node-library" diff --git a/packages/backend-app-api/src/lib/DependencyGraph.test.ts b/packages/backend-app-api/src/lib/DependencyGraph.test.ts index 394359e486..8aafcb21aa 100644 --- a/packages/backend-app-api/src/lib/DependencyGraph.test.ts +++ b/packages/backend-app-api/src/lib/DependencyGraph.test.ts @@ -514,5 +514,21 @@ describe('DependencyGraph', () => { }).parallelTopologicalTraversal(async id => id), ).rejects.toThrow('Circular dependency detected'); }); + + it('awaits all producers', async () => { + await expect( + DependencyGraph.fromMap({ + 1: { provides: ['a'] }, + 2: { provides: ['a'] }, + 3: { consumes: ['a'] }, + }).parallelTopologicalTraversal(async id => { + // Delaying 2 should not make 3 run, wait for 1 too first + if (id === '2') { + await new Promise(resolve => setTimeout(resolve, 100)); + } + return id; + }), + ).resolves.toEqual(['1', '2', '3']); + }); }); }); diff --git a/packages/backend-app-api/src/lib/DependencyGraph.ts b/packages/backend-app-api/src/lib/DependencyGraph.ts index 86fad3fbf2..8b3de48ff2 100644 --- a/packages/backend-app-api/src/lib/DependencyGraph.ts +++ b/packages/backend-app-api/src/lib/DependencyGraph.ts @@ -188,12 +188,25 @@ export class DependencyGraph { fn: (value: T) => Promise, ): Promise { const allProvided = this.#allProvided; - const producedSoFar = new Set(); const waiting = new Set(this.#nodes.values()); const visited = new Set>(); const results = new Array(); let inFlight = 0; // Keep track of how many callbacks are in flight, so that we know if we got stuck + // This keeps track of a counter of how many providers there are still left + // to be visited for each dependency. This needs to be a counter instead of + // a flag for the special case where there are several providers of a given + // value, even though there may be only one consumer of it. + const producedRemaining = new Map(); + for (const node of this.#nodes) { + for (const provided of node.provides) { + producedRemaining.set( + provided, + (producedRemaining.get(provided) ?? 0) + 1, + ); + } + } + // Find all nodes that have no dependencies that have not already been produced by visited nodes async function processMoreNodes() { if (waiting.size === 0) { @@ -203,7 +216,10 @@ export class DependencyGraph { for (const node of waiting) { let ready = true; for (const consumed of node.consumes) { - if (allProvided.has(consumed) && !producedSoFar.has(consumed)) { + if ( + allProvided.has(consumed) && + producedRemaining.get(consumed) !== 0 + ) { ready = false; continue; } @@ -234,7 +250,17 @@ export class DependencyGraph { const result = await fn(node.value); results.push(result); - node.provides.forEach(produced => producedSoFar.add(produced)); + node.provides.forEach(produced => { + const remaining = producedRemaining.get(produced); + if (!remaining) { + // This should be impossible, if the code that generates the map is correct + throw new Error( + `Internal error: Node provided superfluous dependency '${produced}'`, + ); + } + producedRemaining.set(produced, remaining - 1); + }); + inFlight -= 1; await processMoreNodes(); } diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts index 3b0596cd13..9e8a6579fd 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.test.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.test.ts @@ -1134,4 +1134,68 @@ describe('BackendInitializer', () => { backend.add(instanceMetadataPlugin); await backend.start(); }); + + it('should properly wait for all modules that consume an extension point to really finish, before starting the module that provides that extension point', async () => { + expect.assertions(3); + const backend = new BackendInitializer(baseFactories); + const ext = createExtensionPoint<{ hello: (message: string) => void }>({ + id: 'a', + }); + const plugin = createBackendPlugin({ + pluginId: 'test', + register(reg) { + reg.registerInit({ + deps: {}, + async init() {}, + }); + }, + }); + const producerModule = createBackendModule({ + pluginId: 'test', + moduleId: 'producer', + register(reg) { + const hello = jest.fn(); + reg.registerExtensionPoint(ext, { hello }); + reg.registerInit({ + deps: {}, + async init() { + // we must not have been initialized before both of the consuming modules have been initialized + expect(hello).toHaveBeenCalledTimes(2); + expect(hello).toHaveBeenNthCalledWith(1, 'fast'); + expect(hello).toHaveBeenNthCalledWith(2, 'slow'); + }, + }); + }, + }); + const fastConsumerModule = createBackendModule({ + pluginId: 'test', + moduleId: 'fast-consumer', + register(reg) { + reg.registerInit({ + deps: { x: ext }, + async init({ x }) { + x.hello('fast'); + }, + }); + }, + }); + const slowConsumerModule = createBackendModule({ + pluginId: 'test', + moduleId: 'slow-consumer', + register(reg) { + reg.registerInit({ + deps: { x: ext }, + async init({ x }) { + await new Promise(resolve => setTimeout(resolve, 100)); + x.hello('slow'); + }, + }); + }, + }); + await backend.add(plugin); + await backend.add(producerModule); + await backend.add(fastConsumerModule); + await backend.add(slowConsumerModule); + await backend.start(); + }); }); diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 136513ee03..480a1bc4a6 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,146 @@ # @backstage/backend-defaults +## 0.11.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/integration@1.17.1-next.1 + - @backstage/integration-aws-node@0.1.17-next.0 + - @backstage/backend-app-api@1.2.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## 0.11.1-next.0 + +### Patch Changes + +- ead925a: Add a standard `toString` on credentials objects +- e0189b8: UrlReader: Fix handling of access tokens for GitLab readURL requests +- d1e4a6d: Fixed bug where the GitLab user token and GitLab integration token were being merged together +- Updated dependencies + - @backstage/integration@1.17.1-next.0 + - @backstage/backend-app-api@1.2.4 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + +## 0.11.0 + +### Minor Changes + +- 3ccb7fc: Enhanced error handling in the auditor service factory to pass errors as objects. Aligned WinstonRootAuditorService with the default service factory's error handling. + +### Patch Changes + +- 1220cf8: Added new rate limit middleware to allow rate limiting requests to the backend + + If you are using the `configure` callback of the root HTTP router service and do NOT call `applyDefaults()` inside it, please see [the relevant changes](https://github.com/backstage/backstage/pull/28708/files#diff-86ad1b6a694dd250823aee39d410428dd837c9d9a04ca8c33bd1081fbe3f22af) that were made, to see if you want to apply them as well to your custom configuration. + Rate limiting can be turned on by adding the following configuration to `app-config.yaml`: + + ```yaml + backend: + rateLimit: + window: 6s + incomingRequestLimit: 100 + ``` + + Plugin specific rate limiting can be configured by adding the following configuration to `app-config.yaml`: + + ```yaml + backend: + rateLimit: + global: false # This will disable the global rate limiting + plugin: + catalog: + window: 6s + incomingRequestLimit: 100 + ``` + +- c999c25: Added some default implementations for the experimental `ActionsService` and `ActionsRegistryService` under `/alpha` that allow registration of actions for a particular plugin. +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-app-api@1.2.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-node@0.10.1 + +## 0.11.0-next.2 + +### Minor Changes + +- 3ccb7fc: Enhanced error handling in the auditor service factory to pass errors as objects. Aligned WinstonRootAuditorService with the default service factory's error handling. + +### Patch Changes + +- Updated dependencies + - @backstage/backend-app-api@1.2.4-next.2 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## 0.10.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-app-api@1.2.4-next.1 + - @backstage/backend-dev-utils@0.1.5 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/integration@1.17.0 + - @backstage/integration-aws-node@0.1.16 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## 0.10.1-next.0 + +### Patch Changes + +- c999c25: Added some default implementations for the `ActionsService` and `ActionsRegistryService` that allow registration of actions for a particular plugin. +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-app-api@1.2.4-next.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + ## 0.10.0 ### Minor Changes diff --git a/packages/backend-defaults/config.d.ts b/packages/backend-defaults/config.d.ts index 14732bbccd..167a8935f9 100644 --- a/packages/backend-defaults/config.d.ts +++ b/packages/backend-defaults/config.d.ts @@ -121,6 +121,16 @@ export interface Config { }; }; + /** + * Options used by the default actions service. + */ + actions?: { + /** + * List of plugin sources to load actions from. + */ + pluginSources?: string[]; + }; + /** * Options used by the default auth, httpAuth and userInfo services. */ @@ -780,6 +790,92 @@ export interface Config { headers?: { [name: string]: string }; }; + /** + * Rate limiting options. Defining this as `true` will enable rate limiting with default values. + */ + rateLimit?: + | true + | { + store?: + | { + type: 'redis'; + connection: string; + } + | { + type: 'memory'; + }; + /** + * Enable/disable global rate limiting. If this is disabled, plugin specific rate limiting must be + * used. + */ + global?: boolean; + /** + * Time frame in milliseconds or as human duration for which requests are checked/remembered. + * Defaults to one minute. + */ + window?: string | HumanDuration; + /** + * The maximum number of connections to allow during the `window` before rate limiting the client. + * Defaults to 5. + */ + incomingRequestLimit?: number; + /** + * Whether to pass requests in case of store failure. + * Defaults to false. + */ + passOnStoreError?: boolean; + /** + * List of allowed IP addresses that are not rate limited. + * Defaults to [127.0.0.1, 0:0:0:0:0:0:0:1, ::1]. + */ + ipAllowList?: string[]; + /** + * Skip rate limiting for requests that have been successful. + * Defaults to false. + */ + skipSuccessfulRequests?: boolean; + /** + * Skip rate limiting for requests that have failed. + * Defaults to false. + */ + skipFailedRequests?: boolean; + /** Plugin specific rate limiting configuration */ + plugin?: { + [pluginId: string]: { + /** + * Time frame in milliseconds or as human duration for which requests are checked/remembered. + * Defaults to one minute. + */ + window?: string | HumanDuration; + /** + * The maximum number of connections to allow during the `window` before rate limiting the client. + * Defaults to 5. + */ + incomingRequestLimit?: number; + /** + * Whether to pass requests in case of store failure. + * Defaults to false. + */ + passOnStoreError?: boolean; + /** + * List of allowed IP addresses that are not rate limited. + * Defaults to [127.0.0.1, 0:0:0:0:0:0:0:1, ::1]. + */ + ipAllowList?: string[]; + /** + * Skip rate limiting for requests that have been successful. + * Defaults to false. + */ + skipSuccessfulRequests?: boolean; + /** + * Skip rate limiting for requests that have failed. + * Defaults to false. + */ + skipFailedRequests?: boolean; + }; + }; + }; + /** * Configuration related to URL reading, used for example for reading catalog info * files, scaffolder templates, and techdocs content. diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 600f68d3f4..be79c93121 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-defaults", - "version": "0.10.0", + "version": "0.11.1-next.1", "description": "Backend defaults used by Backstage backend apps", "backstage": { "role": "node-library" @@ -39,6 +39,7 @@ "./scheduler": "./src/entrypoints/scheduler/index.ts", "./urlReader": "./src/entrypoints/urlReader/index.ts", "./userInfo": "./src/entrypoints/userInfo/index.ts", + "./alpha": "./src/alpha/index.ts", "./package.json": "./package.json" }, "main": "src/index.ts", @@ -102,6 +103,9 @@ "userInfo": [ "src/entrypoints/userInfo/index.ts" ], + "alpha": [ + "src/alpha/index.ts" + ], "package.json": [ "package.json" ] @@ -160,6 +164,7 @@ "cron": "^3.0.0", "express": "^4.17.1", "express-promise-router": "^4.1.0", + "express-rate-limit": "^7.5.0", "fs-extra": "^11.2.0", "git-url-parse": "^15.0.0", "helmet": "^6.0.0", @@ -179,6 +184,7 @@ "pg": "^8.11.3", "pg-connection-string": "^2.3.0", "pg-format": "^1.0.4", + "rate-limit-redis": "^4.2.0", "raw-body": "^2.4.1", "selfsigned": "^2.0.0", "tar": "^6.1.12", @@ -188,7 +194,8 @@ "winston-transport": "^4.5.0", "yauzl": "^3.0.0", "yn": "^4.0.0", - "zod": "^3.22.4" + "zod": "^3.22.4", + "zod-to-json-schema": "^3.20.4" }, "devDependencies": { "@aws-sdk/util-stream-node": "^3.350.0", diff --git a/packages/backend-defaults/report-alpha.api.md b/packages/backend-defaults/report-alpha.api.md new file mode 100644 index 0000000000..58277b5e1e --- /dev/null +++ b/packages/backend-defaults/report-alpha.api.md @@ -0,0 +1,25 @@ +## API Report File for "@backstage/backend-defaults" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; +import { ActionsService } from '@backstage/backend-plugin-api/alpha'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @public (undocumented) +export const actionsRegistryServiceFactory: ServiceFactory< + ActionsRegistryService, + 'plugin', + 'singleton' +>; + +// @public (undocumented) +export const actionsServiceFactory: ServiceFactory< + ActionsService, + 'plugin', + 'singleton' +>; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-defaults/report-auditor.api.md b/packages/backend-defaults/report-auditor.api.md index 353b6f241f..cc00b5c349 100644 --- a/packages/backend-defaults/report-auditor.api.md +++ b/packages/backend-defaults/report-auditor.api.md @@ -8,6 +8,7 @@ import type { AuditorServiceCreateEventOptions } from '@backstage/backend-plugin import type { AuditorServiceEvent } from '@backstage/backend-plugin-api'; import type { AuditorServiceEventSeverityLevel } from '@backstage/backend-plugin-api'; import type { AuthService } from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; import type { Format } from 'logform'; import type { HttpAuthService } from '@backstage/backend-plugin-api'; import type { JsonObject } from '@backstage/types'; @@ -58,7 +59,7 @@ export type AuditorEventStatus = } | { status: 'failed'; - error: string; + error: Error; }; // @public @@ -95,6 +96,7 @@ export class WinstonRootAuditorService { // (undocumented) forPlugin(deps: { auth: AuthService; + config: Config; httpAuth: HttpAuthService; plugin: PluginMetadataService; }): AuditorService; diff --git a/packages/backend-defaults/report-rootHttpRouter.api.md b/packages/backend-defaults/report-rootHttpRouter.api.md index 826d592e8b..84424be39d 100644 --- a/packages/backend-defaults/report-rootHttpRouter.api.md +++ b/packages/backend-defaults/report-rootHttpRouter.api.md @@ -93,6 +93,7 @@ export class MiddlewareFactory { helmet(): RequestHandler; logging(): RequestHandler; notFound(): RequestHandler; + rateLimit(): RequestHandler; } // @public diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts index d618c94138..4b201fded3 100644 --- a/packages/backend-defaults/src/CreateBackend.ts +++ b/packages/backend-defaults/src/CreateBackend.ts @@ -35,6 +35,10 @@ import { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler'; import { urlReaderServiceFactory } from '@backstage/backend-defaults/urlReader'; import { userInfoServiceFactory } from '@backstage/backend-defaults/userInfo'; import { eventsServiceFactory } from '@backstage/plugin-events-node'; +import { + actionsRegistryServiceFactory, + actionsServiceFactory, +} from '@backstage/backend-defaults/alpha'; export const defaultServiceFactories = [ auditorServiceFactory, @@ -57,6 +61,10 @@ export const defaultServiceFactories = [ userInfoServiceFactory, urlReaderServiceFactory, eventsServiceFactory, + + // alpha services + actionsRegistryServiceFactory, + actionsServiceFactory, ]; /** diff --git a/packages/backend-defaults/src/alpha/entrypoints/actions/DefaultActionsService.ts b/packages/backend-defaults/src/alpha/entrypoints/actions/DefaultActionsService.ts new file mode 100644 index 0000000000..d8847c2187 --- /dev/null +++ b/packages/backend-defaults/src/alpha/entrypoints/actions/DefaultActionsService.ts @@ -0,0 +1,141 @@ +/* + * Copyright 2025 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 { + AuthService, + BackstageCredentials, + DiscoveryService, + LoggerService, + RootConfigService, +} from '@backstage/backend-plugin-api'; +import { ResponseError } from '@backstage/errors'; +import { JsonObject } from '@backstage/types'; +import { + ActionsService, + ActionsServiceAction, +} from '@backstage/backend-plugin-api/alpha'; + +export class DefaultActionsService implements ActionsService { + private constructor( + private readonly discovery: DiscoveryService, + private readonly config: RootConfigService, + private readonly logger: LoggerService, + private readonly auth: AuthService, + ) {} + + static create({ + discovery, + config, + logger, + auth, + }: { + discovery: DiscoveryService; + config: RootConfigService; + logger: LoggerService; + auth: AuthService; + }) { + return new DefaultActionsService(discovery, config, logger, auth); + } + + async list({ credentials }: { credentials: BackstageCredentials }) { + const pluginSources = + this.config.getOptionalStringArray('backend.actions.pluginSources') ?? []; + + const remoteActionsList = await Promise.all( + pluginSources.map(async source => { + try { + const response = await this.makeRequest({ + path: `/.backstage/actions/v1/actions`, + pluginId: source, + credentials, + }); + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + const { actions } = (await response.json()) as { + actions: ActionsServiceAction; + }; + + return actions; + } catch (error) { + this.logger.warn(`Failed to fetch actions from ${source}`, error); + return []; + } + }), + ); + + return { actions: remoteActionsList.flat() }; + } + + async invoke(opts: { + id: string; + input?: JsonObject; + credentials: BackstageCredentials; + }) { + const pluginId = this.pluginIdFromActionId(opts.id); + const response = await this.makeRequest({ + path: `/.backstage/actions/v1/actions/${encodeURIComponent( + opts.id, + )}/invoke`, + pluginId, + credentials: opts.credentials, + options: { + method: 'POST', + body: JSON.stringify(opts.input), + headers: { + 'Content-Type': 'application/json', + }, + }, + }); + + if (!response.ok) { + throw await ResponseError.fromResponse(response); + } + + const { output } = await response.json(); + return { output }; + } + + private async makeRequest(opts: { + path: string; + pluginId: string; + options?: RequestInit; + credentials: BackstageCredentials; + }) { + const { path, pluginId, credentials, options } = opts; + const baseUrl = await this.discovery.getBaseUrl(pluginId); + + const { token } = await this.auth.getPluginRequestToken({ + onBehalfOf: credentials, + targetPluginId: opts.pluginId, + }); + + return fetch(`${baseUrl}${path}`, { + ...options, + headers: { + ...options?.headers, + Authorization: `Bearer ${token}`, + }, + }); + } + + private pluginIdFromActionId(id: string): string { + const colonIndex = id.indexOf(':'); + if (colonIndex === -1) { + throw new Error(`Invalid action id: ${id}`); + } + return id.substring(0, colonIndex); + } +} diff --git a/packages/backend-defaults/src/alpha/entrypoints/actions/actionsServiceFactory.test.ts b/packages/backend-defaults/src/alpha/entrypoints/actions/actionsServiceFactory.test.ts new file mode 100644 index 0000000000..af2fcb0c12 --- /dev/null +++ b/packages/backend-defaults/src/alpha/entrypoints/actions/actionsServiceFactory.test.ts @@ -0,0 +1,346 @@ +/* + * Copyright 2025 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 { + mockCredentials, + mockServices, + registerMswTestHooks, + ServiceFactoryTester, + startTestBackend, +} from '@backstage/backend-test-utils'; +import { actionsRegistryServiceFactory } from '../actionsRegistry'; +import { httpRouterServiceFactory } from '../../../entrypoints/httpRouter'; +import { actionsServiceFactory } from './actionsServiceFactory'; +import { setupServer } from 'msw/node'; +import { rest } from 'msw'; +import { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { json } from 'express'; +import Router from 'express-promise-router'; +import request from 'supertest'; +import { ActionsServiceAction } from '@backstage/backend-plugin-api/alpha'; +import { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha'; +import { actionsServiceRef } from '@backstage/backend-plugin-api/alpha'; + +const server = setupServer(); + +describe('actionsServiceFactory', () => { + describe('client', () => { + registerMswTestHooks(server); + const mockActionsListEndpoint = jest.fn(); + const mockNotFoundActionsListEndpoint = jest.fn(); + + const defaultServices = [ + mockServices.rootConfig.factory({ + data: { + backend: { + actions: { + pluginSources: ['my-plugin', 'not-found-plugin'], + }, + }, + }, + }), + actionsServiceFactory, + httpRouterServiceFactory, + mockServices.httpAuth.factory({ + defaultCredentials: mockCredentials.service('user:default/mock'), + }), + mockServices.discovery.factory(), + actionsRegistryServiceFactory, + ]; + + const mockActionsDefinition: ActionsServiceAction = { + description: 'my mock description', + id: 'my-plugin:test', + name: 'testy', + title: 'Test', + schema: { + input: {}, + output: {}, + }, + attributes: { + destructive: false, + idempotent: false, + readOnly: false, + }, + }; + + beforeEach(() => { + server.use( + rest.get( + 'http://localhost:0/api/my-plugin/.backstage/actions/v1/actions', + mockActionsListEndpoint.mockImplementation((_req, res, ctx) => + res( + ctx.json({ + actions: [mockActionsDefinition], + }), + ), + ), + ), + rest.get( + 'http://localhost:0/api/not-found-plugin/.backstage/actions/v1/actions', + mockNotFoundActionsListEndpoint.mockImplementation((_req, res, ctx) => + res(ctx.status(404)), + ), + ), + ); + }); + + describe('list', () => { + it('should list all plugins in config to find actions and handle failures gracefully', async () => { + const subject = await ServiceFactoryTester.from(actionsServiceFactory, { + dependencies: defaultServices, + }).getSubject(); + + const { actions } = await subject.list({ + credentials: mockCredentials.service('user:default/mock'), + }); + + expect(actions).toEqual([mockActionsDefinition]); + + expect(mockActionsListEndpoint).toHaveBeenCalledTimes(1); + expect(mockNotFoundActionsListEndpoint).toHaveBeenCalledTimes(1); + }); + }); + + describe('invoke', () => { + it('should invoke the action and return the output', async () => { + server.use( + rest.post( + 'http://localhost:0/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + (_req, res, ctx) => res(ctx.json({ output: { ok: true } })), + ), + ); + const subject = await ServiceFactoryTester.from(actionsServiceFactory, { + dependencies: defaultServices, + }).getSubject(); + + const { output } = await subject.invoke({ + id: 'my-plugin:test', + credentials: mockCredentials.service('user:default/mock'), + }); + + expect(output).toEqual({ ok: true }); + }); + + it('should throw a 404 if the action does not exist', async () => { + server.use( + rest.post( + 'http://localhost:0/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + (_req, res, ctx) => res(ctx.status(404)), + ), + ); + + const subject = await ServiceFactoryTester.from(actionsServiceFactory, { + dependencies: defaultServices, + }).getSubject(); + + await expect( + subject.invoke({ + id: 'my-plugin:test', + credentials: mockCredentials.service('user:default/mock'), + }), + ).rejects.toThrow('404'); + }); + + it('should throw a 400 if the action returns an invalid input', async () => { + server.use( + rest.post( + 'http://localhost:0/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + (_req, res, ctx) => res(ctx.status(400)), + ), + ); + + const subject = await ServiceFactoryTester.from(actionsServiceFactory, { + dependencies: defaultServices, + }).getSubject(); + + await expect( + subject.invoke({ + id: 'my-plugin:test', + credentials: mockCredentials.service('user:default/mock'), + }), + ).rejects.toThrow('400'); + }); + }); + + describe('integration', () => { + beforeAll(() => { + // disable the msw server for this test. + server.close(); + }); + + const features = [ + actionsServiceFactory, + httpRouterServiceFactory, + mockServices.httpAuth.factory({ + defaultCredentials: mockCredentials.service('user:default/mock'), + }), + actionsRegistryServiceFactory, + mockServices.rootConfig.factory({ + data: { + backend: { + actions: { pluginSources: ['plugin-with-action'] }, + }, + }, + }), + + createBackendPlugin({ + pluginId: 'plugin-with-action', + register({ registerInit }) { + registerInit({ + deps: { actionsRegistry: actionsRegistryServiceRef }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'with-validation', + title: 'Test', + description: 'Test', + schema: { + input: z => + z.object({ + name: z.string(), + }), + output: z => + z.object({ + ok: z.boolean(), + string: z.string(), + }), + }, + action: async ({ input }) => { + return { + output: { + ok: true, + string: `hello ${input.name}`, + }, + }; + }, + }); + }, + }); + }, + }), + createBackendPlugin({ + pluginId: 'test-harness', + register({ registerInit }) { + registerInit({ + deps: { + actionsService: actionsServiceRef, + router: coreServices.httpRouter, + httpAuth: coreServices.httpAuth, + }, + async init({ actionsService, router, httpAuth }) { + const innerRouter = Router(); + innerRouter.use(json()); + router.use(innerRouter); + + innerRouter.post('/invoke', async (req, res) => { + const { id, input } = req.body; + const response = await actionsService.invoke({ + id, + input, + credentials: await httpAuth.credentials(req), + }); + res.json(response); + }); + + innerRouter.get('/actions', async (req, res) => { + const response = await actionsService.list({ + credentials: await httpAuth.credentials(req), + }); + + res.json(response); + }); + }, + }); + }, + }), + ]; + + it('should list the actions and return the output', async () => { + const { server: testHarnessServer } = await startTestBackend({ + features, + }); + + const { body, status } = await request(testHarnessServer).get( + '/api/test-harness/actions', + ); + + expect(status).toBe(200); + expect(body).toEqual({ + actions: [ + { + description: 'Test', + id: 'plugin-with-action:with-validation', + name: 'with-validation', + schema: { + input: { + $schema: 'http://json-schema.org/draft-07/schema#', + additionalProperties: false, + properties: { + name: { + type: 'string', + }, + }, + required: ['name'], + type: 'object', + }, + output: { + $schema: 'http://json-schema.org/draft-07/schema#', + additionalProperties: false, + properties: { + ok: { + type: 'boolean', + }, + string: { + type: 'string', + }, + }, + required: ['ok', 'string'], + type: 'object', + }, + }, + attributes: { + destructive: true, + idempotent: false, + readOnly: false, + }, + title: 'Test', + }, + ], + }); + }); + + it('should invoke the action and return the output', async () => { + const { server: testHarnessServer } = await startTestBackend({ + features, + }); + + const { body, status } = await request(testHarnessServer) + .post('/api/test-harness/invoke') + .send({ + id: 'plugin-with-action:with-validation', + input: { + name: 'world', + }, + }); + + expect(body).toEqual({ output: { ok: true, string: 'hello world' } }); + expect(status).toBe(200); + }); + }); + }); +}); diff --git a/packages/backend-defaults/src/alpha/entrypoints/actions/actionsServiceFactory.ts b/packages/backend-defaults/src/alpha/entrypoints/actions/actionsServiceFactory.ts new file mode 100644 index 0000000000..4325da7d13 --- /dev/null +++ b/packages/backend-defaults/src/alpha/entrypoints/actions/actionsServiceFactory.ts @@ -0,0 +1,39 @@ +/* + * Copyright 2025 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 { createServiceFactory } from '@backstage/backend-plugin-api'; +import { coreServices } from '@backstage/backend-plugin-api'; +import { DefaultActionsService } from './DefaultActionsService'; +import { actionsServiceRef } from '@backstage/backend-plugin-api/alpha'; + +/** + * @public + */ +export const actionsServiceFactory = createServiceFactory({ + service: actionsServiceRef, + deps: { + discovery: coreServices.discovery, + config: coreServices.rootConfig, + logger: coreServices.logger, + auth: coreServices.auth, + }, + factory: ({ discovery, config, logger, auth }) => + DefaultActionsService.create({ + discovery, + config, + logger, + auth, + }), +}); diff --git a/plugins/scaffolder-backend/src/lib/templating/index.ts b/packages/backend-defaults/src/alpha/entrypoints/actions/index.ts similarity index 83% rename from plugins/scaffolder-backend/src/lib/templating/index.ts rename to packages/backend-defaults/src/alpha/entrypoints/actions/index.ts index 1f9e5eb855..bc34150a5f 100644 --- a/plugins/scaffolder-backend/src/lib/templating/index.ts +++ b/packages/backend-defaults/src/alpha/entrypoints/actions/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * Copyright 2025 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. @@ -13,5 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -export type { TemplateFilter, TemplateGlobal } from './SecureTemplater'; +export { actionsServiceFactory } from './actionsServiceFactory'; diff --git a/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts new file mode 100644 index 0000000000..2284935787 --- /dev/null +++ b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts @@ -0,0 +1,166 @@ +/* + * Copyright 2025 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 { + AuthService, + HttpAuthService, + LoggerService, + PluginMetadataService, +} from '@backstage/backend-plugin-api'; +import PromiseRouter from 'express-promise-router'; +import { Router, json } from 'express'; +import { z, AnyZodObject } from 'zod'; +import zodToJsonSchema from 'zod-to-json-schema'; +import { + ActionsRegistryActionOptions, + ActionsRegistryService, +} from '@backstage/backend-plugin-api/alpha'; +import { + ForwardedError, + InputError, + NotAllowedError, + NotFoundError, +} from '@backstage/errors'; + +export class DefaultActionsRegistryService implements ActionsRegistryService { + private actions: Map> = + new Map(); + + private constructor( + private readonly logger: LoggerService, + private readonly httpAuth: HttpAuthService, + private readonly auth: AuthService, + private readonly metadata: PluginMetadataService, + ) {} + + static create({ + httpAuth, + logger, + auth, + metadata, + }: { + httpAuth: HttpAuthService; + logger: LoggerService; + auth: AuthService; + metadata: PluginMetadataService; + }): DefaultActionsRegistryService { + return new DefaultActionsRegistryService(logger, httpAuth, auth, metadata); + } + + createRouter(): Router { + const router = PromiseRouter(); + router.use(json()); + + router.get('/.backstage/actions/v1/actions', (_, res) => { + return res.json({ + actions: Array.from(this.actions.entries()).map(([id, action]) => ({ + id, + ...action, + attributes: { + // Inspired by the @modelcontextprotocol/sdk defaults for the hints. + // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812 + destructive: action.attributes?.destructive ?? true, + idempotent: action.attributes?.idempotent ?? false, + readOnly: action.attributes?.readOnly ?? false, + }, + schema: { + input: action.schema?.input + ? zodToJsonSchema(action.schema.input(z)) + : zodToJsonSchema(z.object({})), + output: action.schema?.output + ? zodToJsonSchema(action.schema.output(z)) + : zodToJsonSchema(z.object({})), + }, + })), + }); + }); + + router.post( + '/.backstage/actions/v1/actions/:actionId/invoke', + async (req, res) => { + const credentials = await this.httpAuth.credentials(req); + if (this.auth.isPrincipal(credentials, 'user')) { + if (!credentials.principal.actor) { + throw new NotAllowedError( + `Actions must be invoked by a service, not a user`, + ); + } + } else if (this.auth.isPrincipal(credentials, 'none')) { + throw new NotAllowedError( + `Actions must be invoked by a service, not an anonymous request`, + ); + } + + const action = this.actions.get(req.params.actionId); + + if (!action) { + throw new NotFoundError(`Action "${req.params.actionId}" not found`); + } + + const input = action.schema?.input + ? action.schema.input(z).safeParse(req.body) + : ({ success: true, data: undefined } as const); + + if (!input.success) { + throw new InputError( + `Invalid input to action "${req.params.actionId}"`, + input.error, + ); + } + + try { + const result = await action.action({ + input: input.data, + credentials, + logger: this.logger, + }); + + const output = action.schema?.output + ? action.schema.output(z).safeParse(result?.output) + : ({ success: true, data: result?.output } as const); + + if (!output.success) { + throw new InputError( + `Invalid output from action "${req.params.actionId}"`, + output.error, + ); + } + + res.json({ output: output.data }); + } catch (error) { + throw new ForwardedError( + `Failed execution of action "${req.params.actionId}"`, + error, + ); + } + }, + ); + return router; + } + + register< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, + >(options: ActionsRegistryActionOptions): void { + const id = `${this.metadata.getId()}:${options.name}`; + + if (this.actions.has(id)) { + throw new Error(`Action with id "${id}" is already registered`); + } + + this.actions.set(id, options); + } +} diff --git a/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.test.ts b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.test.ts new file mode 100644 index 0000000000..79c103c284 --- /dev/null +++ b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.test.ts @@ -0,0 +1,538 @@ +/* + * Copyright 2025 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 { createBackendPlugin } from '@backstage/backend-plugin-api'; +import { + mockCredentials, + mockServices, + startTestBackend, +} from '@backstage/backend-test-utils'; +import { httpRouterServiceFactory } from '../../../entrypoints/httpRouter'; +import request from 'supertest'; +import { actionsRegistryServiceFactory } from './actionsRegistryServiceFactory'; +import { InputError } from '@backstage/errors'; +import { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha'; + +describe('actionsRegistryServiceFactory', () => { + const defaultServices = [ + actionsRegistryServiceFactory, + httpRouterServiceFactory, + mockServices.httpAuth.factory({ + defaultCredentials: mockCredentials.service('user:default/mock'), + }), + ]; + + describe('typescript tests', () => { + it('should properly infer the input types', () => { + createBackendPlugin({ + pluginId: 'my-plugin', + register(reg) { + reg.registerInit({ + deps: { + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'test', + title: 'Test', + description: 'Test', + schema: { + input: z => + z.object({ + test: z.string(), + }), + output: z => + z.object({ + ok: z.boolean(), + }), + }, + action: async ({ input: { test } }) => { + // @ts-expect-error - test is not a boolean + const _t: boolean = test; + return { output: { ok: true } }; + }, + }); + }, + }); + }, + }); + + expect(true).toBe(true); + }); + + it('should properly infer the output types', () => { + createBackendPlugin({ + pluginId: 'my-plugin', + register(reg) { + reg.registerInit({ + deps: { + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'test', + title: 'Test', + description: 'Test', + schema: { + input: z => + z.object({ + test: z.string(), + }), + output: z => + z.object({ + ok: z.boolean(), + }), + }, + // @ts-expect-error - ok is not a boolean + action: async () => { + return { output: { ok: 'bo' } }; + }, + }); + }, + }); + }, + }); + + expect(true).toBe(true); + }); + }); + + describe('/.backstage/actions/v1/actions', () => { + it('should allow registering of actions', async () => { + const pluginSubject = createBackendPlugin({ + pluginId: 'my-plugin', + register(reg) { + reg.registerInit({ + deps: { + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'test', + title: 'Test', + description: 'Test', + schema: { + input: z => + z.object({ + name: z.string(), + }), + output: z => + z.object({ + ok: z.boolean(), + }), + }, + action: async () => ({ output: { ok: true } }), + }); + }, + }); + }, + }); + + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + const { body, status } = await request(server).get( + '/api/my-plugin/.backstage/actions/v1/actions', + ); + + expect(status).toBe(200); + + expect(body).toMatchObject({ + actions: [ + { + name: 'test', + title: 'Test', + description: 'Test', + schema: { + input: { + type: 'object', + properties: { + name: { + type: 'string', + }, + }, + }, + output: { + type: 'object', + properties: { + ok: { + type: 'boolean', + }, + }, + }, + }, + }, + ], + }); + }); + + it('should set default attributes', async () => { + const pluginSubject = createBackendPlugin({ + pluginId: 'my-plugin', + register(reg) { + reg.registerInit({ + deps: { + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'test', + title: 'Test', + description: 'Test', + schema: { + input: z => z.object({}), + output: z => z.object({}), + }, + action: async () => ({ output: { ok: true } }), + }); + }, + }); + }, + }); + + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + const { body, status } = await request(server).get( + '/api/my-plugin/.backstage/actions/v1/actions', + ); + + expect(status).toBe(200); + + expect(body).toMatchObject({ + actions: [ + { + name: 'test', + attributes: { + destructive: true, + idempotent: false, + readOnly: false, + }, + }, + ], + }); + }); + + it('should allow setting attributes', async () => { + const pluginSubject = createBackendPlugin({ + pluginId: 'my-plugin', + register(reg) { + reg.registerInit({ + deps: { + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'test', + title: 'Test', + description: 'Test', + attributes: { + destructive: false, + idempotent: true, + readOnly: true, + }, + schema: { + input: z => z.object({}), + output: z => z.object({}), + }, + action: async () => ({ output: { ok: true } }), + }); + }, + }); + }, + }); + + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + const { body, status } = await request(server).get( + '/api/my-plugin/.backstage/actions/v1/actions', + ); + + expect(status).toBe(200); + + expect(body).toMatchObject({ + actions: [ + { + name: 'test', + title: 'Test', + description: 'Test', + attributes: { + destructive: false, + idempotent: true, + readOnly: true, + }, + }, + ], + }); + }); + + it('should forces registration of input and output schema as objects', async () => { + const pluginSubject = createBackendPlugin({ + pluginId: 'my-plugin', + register(reg) { + reg.registerInit({ + deps: { + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'test', + title: 'Test', + description: 'Test', + schema: { + // @ts-expect-error - z.undefined is not a valid schema + input: z => z.undefined(), + // @ts-expect-error - z.string is not a valid schema + output: z => z.string(), + }, + // @ts-expect-error - output is not a valid, needs to be an object + action: async () => ({ output: 'ok' }), + }); + }, + }); + }, + }); + + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + const { body, status } = await request(server).get( + '/api/my-plugin/.backstage/actions/v1/actions', + ); + + expect(status).toBe(200); + + expect(body).toMatchObject({ + actions: [ + { + name: 'test', + title: 'Test', + description: 'Test', + schema: { + input: {}, + output: {}, + }, + }, + ], + }); + }); + }); + + describe('/.backstage/actions/v1/actions/:actionId/invoke', () => { + const mockAction = jest.fn(); + + beforeEach(() => { + mockAction.mockResolvedValue({ output: { ok: true } }); + }); + + const pluginSubject = createBackendPlugin({ + pluginId: 'my-plugin', + register(reg) { + reg.registerInit({ + deps: { + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'test', + title: 'Test', + description: 'Test', + schema: { + input: z => + z.object({ + name: z.string(), + }), + output: z => + z.object({ + ok: z.boolean(), + }), + }, + action: mockAction, + }); + }, + }); + }, + }); + + it('should throw an error if the action is not found', async () => { + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + const { body, status } = await request(server).post( + '/api/my-plugin/.backstage/actions/v1/actions/test/invoke', + ); + + expect(status).toBe(404); + expect(body).toMatchObject({ + error: { + message: 'Action "test" not found', + }, + }); + }); + + it('should throw an error if the action input does not match the schema', async () => { + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + const { body, status } = await request(server) + .post( + '/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + ) + .send({ + name: 123, + }); + + expect(status).toBe(400); + expect(body).toMatchObject({ + error: { + message: expect.stringMatching( + 'Invalid input to action "my-plugin:test"', + ), + }, + }); + }); + + it('should call the action with the input', async () => { + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + await request(server) + .post( + '/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + ) + .send({ + name: 'test', + }); + + expect(mockAction).toHaveBeenCalledWith({ + input: { + name: 'test', + }, + credentials: { + $$type: '@backstage/BackstageCredentials', + principal: { + type: 'service', + subject: 'user:default/mock', + }, + }, + logger: expect.anything(), + }); + }); + + it('should throw an error if the action is invoked by a user', async () => { + const testServices = [ + actionsRegistryServiceFactory, + httpRouterServiceFactory, + mockServices.httpAuth.factory({ + defaultCredentials: mockCredentials.user(), + }), + ]; + + const { server } = await startTestBackend({ + features: [pluginSubject, ...testServices], + }); + + const { body, status } = await request(server) + .post( + '/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + ) + .send({ + name: 'test', + }); + + expect(status).toBe(403); + expect(body).toMatchObject({ + error: { + message: 'Actions must be invoked by a service, not a user', + }, + }); + }); + + it('should validate the output of the action if provided', async () => { + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + mockAction.mockResolvedValue({ ok: 'blob' }); + + const { body, status } = await request(server) + .post( + '/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + ) + .send({ + name: 'test', + }); + + expect(status).toBe(400); + expect(body).toMatchObject({ + error: { + message: expect.stringMatching( + 'Invalid output from action "my-plugin:test"', + ), + }, + }); + }); + + it('should return the output of the action', async () => { + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + const { body, status } = await request(server) + .post( + '/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + ) + .send({ + name: 'test', + }); + + expect(status).toBe(200); + expect(body).toMatchObject({ output: { ok: true } }); + }); + + it('should return the error from the action if it throws', async () => { + const { server } = await startTestBackend({ + features: [pluginSubject, ...defaultServices], + }); + + mockAction.mockRejectedValue(new InputError('test')); + + const { body, status } = await request(server) + .post( + '/api/my-plugin/.backstage/actions/v1/actions/my-plugin:test/invoke', + ) + .send({ + name: 'test', + }); + + expect(status).toBe(400); + expect(body).toMatchObject({ + error: { + message: expect.stringContaining( + 'Failed execution of action "my-plugin:test"', + ), + }, + }); + }); + }); +}); diff --git a/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.ts b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.ts new file mode 100644 index 0000000000..8c19b8148c --- /dev/null +++ b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.ts @@ -0,0 +1,48 @@ +/* + * Copyright 2025 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 { + coreServices, + createServiceFactory, +} from '@backstage/backend-plugin-api'; +import { DefaultActionsRegistryService } from './DefaultActionsRegistryService'; +import { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha'; + +/** + * @public + */ +export const actionsRegistryServiceFactory = createServiceFactory({ + service: actionsRegistryServiceRef, + deps: { + metadata: coreServices.pluginMetadata, + httpRouter: coreServices.httpRouter, + httpAuth: coreServices.httpAuth, + logger: coreServices.logger, + auth: coreServices.auth, + }, + factory: ({ metadata, httpRouter, httpAuth, logger, auth }) => { + const actionsRegistryService = DefaultActionsRegistryService.create({ + httpAuth, + logger, + auth, + metadata, + }); + + httpRouter.use(actionsRegistryService.createRouter()); + + return actionsRegistryService; + }, +}); diff --git a/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/index.ts b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/index.ts new file mode 100644 index 0000000000..ac65dd7a90 --- /dev/null +++ b/packages/backend-defaults/src/alpha/entrypoints/actionsRegistry/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2025 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 { actionsRegistryServiceFactory } from './actionsRegistryServiceFactory'; diff --git a/packages/backend-defaults/src/alpha/index.ts b/packages/backend-defaults/src/alpha/index.ts new file mode 100644 index 0000000000..13bb439acd --- /dev/null +++ b/packages/backend-defaults/src/alpha/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2025 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 { actionsRegistryServiceFactory } from './entrypoints/actionsRegistry'; +export { actionsServiceFactory } from './entrypoints/actions'; diff --git a/packages/backend-defaults/src/entrypoints/auditor/DefaultAuditorService.test.ts b/packages/backend-defaults/src/entrypoints/auditor/DefaultAuditorService.test.ts index c960a1daa2..ac32c9e911 100644 --- a/packages/backend-defaults/src/entrypoints/auditor/DefaultAuditorService.test.ts +++ b/packages/backend-defaults/src/entrypoints/auditor/DefaultAuditorService.test.ts @@ -83,7 +83,7 @@ describe('DefaultAuditorService', () => { expect(logFn).toHaveBeenLastCalledWith({ eventId: 'test-event', status: 'failed', - error: error.toString(), + error, plugin: 'test', severityLevel: 'low', actor: {}, @@ -135,7 +135,7 @@ describe('DefaultAuditorService', () => { initiated: 'test', failed: 'test', }, - error: error.toString(), + error, plugin: 'test', severityLevel: 'low', actor: {}, diff --git a/packages/backend-defaults/src/entrypoints/auditor/DefaultAuditorService.ts b/packages/backend-defaults/src/entrypoints/auditor/DefaultAuditorService.ts index 79e206e305..b13565d841 100644 --- a/packages/backend-defaults/src/entrypoints/auditor/DefaultAuditorService.ts +++ b/packages/backend-defaults/src/entrypoints/auditor/DefaultAuditorService.ts @@ -48,7 +48,7 @@ export type AuditorEventStatus = | { status: 'succeeded' } | { status: 'failed'; - error: string; + error: Error; }; /** @@ -195,7 +195,7 @@ export class DefaultAuditorService implements AuditorService { await this.log({ ...options, ...params, - error: String(params.error), + error: params.error, meta: { ...options.meta, ...params?.meta }, status: 'failed', }); diff --git a/packages/backend-defaults/src/entrypoints/auditor/WinstonRootAuditorService.test.ts b/packages/backend-defaults/src/entrypoints/auditor/WinstonRootAuditorService.test.ts index 2d9a959c64..d8ffda2473 100644 --- a/packages/backend-defaults/src/entrypoints/auditor/WinstonRootAuditorService.test.ts +++ b/packages/backend-defaults/src/entrypoints/auditor/WinstonRootAuditorService.test.ts @@ -32,6 +32,7 @@ describe('WinstonRootAuditorService', () => { plugin: { getId: () => 'test-plugin', }, + config: mockServices.rootConfig.mock(), }); expect(childLogger).toBeInstanceOf(DefaultAuditorService); }); @@ -45,6 +46,7 @@ describe('WinstonRootAuditorService', () => { plugin: { getId: () => pluginId, }, + config: mockServices.rootConfig.mock(), }); // workaround to spy on private method const auditorSpy = jest.spyOn(auditor as any, 'log'); @@ -68,6 +70,7 @@ describe('WinstonRootAuditorService', () => { plugin: { getId: () => pluginId, }, + config: mockServices.rootConfig.mock(), }); // workaround to spy on private method const auditorSpy = jest.spyOn(auditor as any, 'log'); @@ -95,6 +98,7 @@ describe('WinstonRootAuditorService', () => { plugin: { getId: () => pluginId, }, + config: mockServices.rootConfig.mock(), }); // workaround to spy on private method const auditorSpy = jest.spyOn(auditor as any, 'log'); @@ -111,7 +115,7 @@ describe('WinstonRootAuditorService', () => { eventId: 'test-event', meta: {}, status: 'failed', - error: error.toString(), + error, }); }); @@ -124,6 +128,7 @@ describe('WinstonRootAuditorService', () => { plugin: { getId: () => pluginId, }, + config: mockServices.rootConfig.mock(), }); // workaround to spy on private method const auditorSpy = jest.spyOn(auditor as any, 'log'); @@ -163,7 +168,7 @@ describe('WinstonRootAuditorService', () => { initiated: 'test', failed: 'test', }, - error: error.toString(), + error, }); }); }); diff --git a/packages/backend-defaults/src/entrypoints/auditor/WinstonRootAuditorService.ts b/packages/backend-defaults/src/entrypoints/auditor/WinstonRootAuditorService.ts index 6ea5d02606..67a28cf74b 100644 --- a/packages/backend-defaults/src/entrypoints/auditor/WinstonRootAuditorService.ts +++ b/packages/backend-defaults/src/entrypoints/auditor/WinstonRootAuditorService.ts @@ -20,11 +20,13 @@ import type { HttpAuthService, PluginMetadataService, } from '@backstage/backend-plugin-api'; +import { Config } from '@backstage/config'; import type { JsonObject } from '@backstage/types'; import type { Format } from 'logform'; import * as winston from 'winston'; import { WinstonLogger } from '../rootLogger'; import { DefaultAuditorService } from './DefaultAuditorService'; +import { getSeverityLogLevelMappings } from './utils'; /** @public */ export const defaultFormatter = winston.format.combine( @@ -108,12 +110,28 @@ export class WinstonRootAuditorService { forPlugin(deps: { auth: AuthService; + config: Config; httpAuth: HttpAuthService; plugin: PluginMetadataService; }): AuditorService { - return DefaultAuditorService.create( - e => this.winstonLogger.info(`${e.plugin}.${e.eventId}`, e), - deps, - ); + const severityLogLevelMappings = getSeverityLogLevelMappings(deps.config); + + return DefaultAuditorService.create(event => { + if ('error' in event) { + const { error, ...rest } = event; + const childAuditLogger = this.winstonLogger.child(rest); + + childAuditLogger[severityLogLevelMappings[event.severityLevel]]( + `${event.plugin}.${event.eventId}`, + error, + ); + } else { + // the else statement is required for typechecking + this.winstonLogger[severityLogLevelMappings[event.severityLevel]]( + `${event.plugin}.${event.eventId}`, + event, + ); + } + }, deps); } } diff --git a/packages/backend-defaults/src/entrypoints/auditor/auditorServiceFactory.ts b/packages/backend-defaults/src/entrypoints/auditor/auditorServiceFactory.ts index 34ea627762..3c82f95ce6 100644 --- a/packages/backend-defaults/src/entrypoints/auditor/auditorServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/auditor/auditorServiceFactory.ts @@ -19,15 +19,7 @@ import { createServiceFactory, } from '@backstage/backend-plugin-api'; import { DefaultAuditorService } from './DefaultAuditorService'; -import { z } from 'zod'; -import { InputError } from '@backstage/errors'; - -const CONFIG_ROOT_KEY = 'backend.auditor'; - -const severityLogLevelMappingsSchema = z.record( - z.enum(['low', 'medium', 'high', 'critical']), - z.enum(['debug', 'info', 'warn', 'error']), -); +import { getSeverityLogLevelMappings } from './utils'; /** * Plugin-level auditing. @@ -49,47 +41,26 @@ export const auditorServiceFactory = createServiceFactory({ }, factory({ config, logger, plugin, auth, httpAuth }) { const auditLogger = logger.child({ isAuditEvent: true }); - const auditorConfig = config.getOptionalConfig(CONFIG_ROOT_KEY); - const severityLogLevelMappings = { - low: - auditorConfig?.getOptionalString('severityLogLevelMappings.low') ?? - 'debug', - medium: - auditorConfig?.getOptionalString('severityLogLevelMappings.medium') ?? - 'info', - high: - auditorConfig?.getOptionalString('severityLogLevelMappings.high') ?? - 'info', - critical: - auditorConfig?.getOptionalString('severityLogLevelMappings.critical') ?? - 'info', - } as Required>; - - const res = severityLogLevelMappingsSchema.safeParse( - severityLogLevelMappings, - ); - if (!res.success) { - const key = res.error.issues.at(0)?.path.at(0) as string; - const value = ( - res.error.issues.at(0) as unknown as Record - ).received as string; - const validKeys = ( - res.error.issues.at(0) as unknown as Record - ).options as string[]; - throw new InputError( - `The configuration value for 'backend.auditor.severityLogLevelMappings.${key}' was given an invalid value: '${value}'. Expected one of the following valid values: '${validKeys.join( - ', ', - )}'.`, - ); - } + const severityLogLevelMappings = getSeverityLogLevelMappings(config); return DefaultAuditorService.create( event => { - auditLogger[severityLogLevelMappings[event.severityLevel]]( - `${event.plugin}.${event.eventId}`, - event, - ); + if ('error' in event) { + const { error, ...rest } = event; + const childAuditLogger = auditLogger.child(rest); + + childAuditLogger[severityLogLevelMappings[event.severityLevel]]( + `${event.plugin}.${event.eventId}`, + error, + ); + } else { + // the else statement is required for typechecking + auditLogger[severityLogLevelMappings[event.severityLevel]]( + `${event.plugin}.${event.eventId}`, + event, + ); + } }, { plugin, auth, httpAuth }, ); diff --git a/packages/backend-defaults/src/entrypoints/auditor/types.ts b/packages/backend-defaults/src/entrypoints/auditor/types.ts new file mode 100644 index 0000000000..7827a31d1f --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auditor/types.ts @@ -0,0 +1,26 @@ +/* + * Copyright 2025 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 { z } from 'zod'; + +/** @internal */ +export const severityLogLevelMappingsSchema = z.record( + z.enum(['low', 'medium', 'high', 'critical']), + z.enum(['debug', 'info', 'warn', 'error']), +); + +/** @internal */ +export const CONFIG_ROOT_KEY = 'backend.auditor'; diff --git a/packages/backend-defaults/src/entrypoints/auditor/utils.ts b/packages/backend-defaults/src/entrypoints/auditor/utils.ts new file mode 100644 index 0000000000..719a227bf9 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/auditor/utils.ts @@ -0,0 +1,66 @@ +/* + * Copyright 2025 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 { Config } from '@backstage/config'; +import { InputError } from '@backstage/errors'; +import { z } from 'zod'; +import { CONFIG_ROOT_KEY, severityLogLevelMappingsSchema } from './types'; + +/** + * Gets the `backend.auditor.severityLogLevelMappings` configuration. + * + * @param config - The root Backstage {@link @backstage/config#Config} object. + * @returns The validated severity-to-log-level mappings. + * @throws error - {@link @backstage/errors#InputError} if the mapping configuration is invalid. + */ +export function getSeverityLogLevelMappings(config: Config) { + const auditorConfig = config.getOptionalConfig(CONFIG_ROOT_KEY); + + const severityLogLevelMappings = { + low: + auditorConfig?.getOptionalString('severityLogLevelMappings.low') ?? + 'debug', + medium: + auditorConfig?.getOptionalString('severityLogLevelMappings.medium') ?? + 'info', + high: + auditorConfig?.getOptionalString('severityLogLevelMappings.high') ?? + 'info', + critical: + auditorConfig?.getOptionalString('severityLogLevelMappings.critical') ?? + 'info', + } as Required>; + + const res = severityLogLevelMappingsSchema.safeParse( + severityLogLevelMappings, + ); + if (!res.success) { + const key = res.error.issues.at(0)?.path.at(0) as string; + const value = ( + res.error.issues.at(0) as unknown as Record + ).received as string; + const validKeys = ( + res.error.issues.at(0) as unknown as Record + ).options as string[]; + throw new InputError( + `The configuration value for 'backend.auditor.severityLogLevelMappings.${key}' was given an invalid value: '${value}'. Expected one of the following valid values: '${validKeys.join( + ', ', + )}'.`, + ); + } + + return severityLogLevelMappings; +} diff --git a/packages/backend-defaults/src/entrypoints/auth/helpers.test.ts b/packages/backend-defaults/src/entrypoints/auth/helpers.test.ts index 8454aa3ecc..fdc6e26c3a 100644 --- a/packages/backend-defaults/src/entrypoints/auth/helpers.test.ts +++ b/packages/backend-defaults/src/entrypoints/auth/helpers.test.ts @@ -42,6 +42,23 @@ describe('credentials', () => { }, }); + expect( + createCredentialsWithUserPrincipal( + 'user:default/mock', + 'my-token', + undefined, + 'my-actor', + ), + ).toEqual({ + $$type: '@backstage/BackstageCredentials', + version: 'v1', + principal: { + type: 'user', + userEntityRef: 'user:default/mock', + actor: { type: 'service', subject: 'my-actor' }, + }, + }); + expect(createCredentialsWithNonePrincipal()).toEqual({ $$type: '@backstage/BackstageCredentials', version: 'v1', @@ -64,4 +81,63 @@ describe('credentials', () => { ), ).not.toMatch(/my-token/); }); + + it('should have a serializable form both as strings and as JSON', () => { + const simpleService = createCredentialsWithServicePrincipal('my-service'); + expect(String(simpleService)).toMatchInlineSnapshot( + `"backstageCredentials{servicePrincipal{my-service}}"`, + ); + expect(JSON.stringify(simpleService)).toMatchInlineSnapshot( + `"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"service","subject":"my-service"}}"`, + ); + + const serviceWithAccessRestrictions = createCredentialsWithServicePrincipal( + 'my-service', + undefined, + { + permissionNames: ['perm'], + permissionAttributes: { + action: ['read'], + }, + }, + ); + expect(String(serviceWithAccessRestrictions)).toMatchInlineSnapshot( + `"backstageCredentials{servicePrincipal{my-service,accessRestrictions=cXWOJgUirHkHNZIowUi/YO5nwEwhTicC38iXi2XTYCk}}"`, + ); + expect(JSON.stringify(serviceWithAccessRestrictions)).toMatchInlineSnapshot( + `"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"service","subject":"my-service","accessRestrictions":{"permissionNames":["perm"],"permissionAttributes":{"action":["read"]}}}}"`, + ); + + const simpleUser = createCredentialsWithUserPrincipal( + 'user:default/mock', + 'my-token', + ); + expect(String(simpleUser)).toMatchInlineSnapshot( + `"backstageCredentials{userPrincipal{user:default/mock}}"`, + ); + expect(JSON.stringify(simpleUser)).toMatchInlineSnapshot( + `"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"user","userEntityRef":"user:default/mock"}}"`, + ); + + const userWithActor = createCredentialsWithUserPrincipal( + 'user:default/mock', + 'my-token', + undefined, + 'my-actor', + ); + expect(String(userWithActor)).toMatchInlineSnapshot( + `"backstageCredentials{userPrincipal{user:default/mock,actor={servicePrincipal{my-actor}}}}"`, + ); + expect(JSON.stringify(userWithActor)).toMatchInlineSnapshot( + `"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"user","userEntityRef":"user:default/mock","actor":{"type":"service","subject":"my-actor"}}}"`, + ); + + const none = createCredentialsWithNonePrincipal(); + expect(String(none)).toMatchInlineSnapshot( + `"backstageCredentials{nonePrincipal}"`, + ); + expect(JSON.stringify(none)).toMatchInlineSnapshot( + `"{"$$type":"@backstage/BackstageCredentials","version":"v1","principal":{"type":"none"}}"`, + ); + }); }); diff --git a/packages/backend-defaults/src/entrypoints/auth/helpers.ts b/packages/backend-defaults/src/entrypoints/auth/helpers.ts index 58e2bcff74..02840112a9 100644 --- a/packages/backend-defaults/src/entrypoints/auth/helpers.ts +++ b/packages/backend-defaults/src/entrypoints/auth/helpers.ts @@ -22,29 +22,34 @@ import { BackstageUserPrincipal, } from '@backstage/backend-plugin-api'; import { InternalBackstageCredentials } from './types'; +import { createHash } from 'crypto'; export function createCredentialsWithServicePrincipal( sub: string, token?: string, accessRestrictions?: BackstagePrincipalAccessRestrictions, ): InternalBackstageCredentials { - return Object.defineProperty( - { - $$type: '@backstage/BackstageCredentials', - version: 'v1', - principal: { - type: 'service', - subject: sub, - accessRestrictions, - }, - }, - 'token', - { + const principal = createServicePrincipal(sub, accessRestrictions); + const result = { + $$type: '@backstage/BackstageCredentials', + version: 'v1', + principal, + } as const; + Object.defineProperties(result, { + token: { enumerable: false, configurable: true, + writable: true, value: token, }, - ); + toString: { + enumerable: false, + configurable: true, + writable: true, + value: () => `backstageCredentials{${principal}}`, + }, + }); + return result; } export function createCredentialsWithUserPrincipal( @@ -53,36 +58,49 @@ export function createCredentialsWithUserPrincipal( expiresAt?: Date, actor?: string, ): InternalBackstageCredentials { - return Object.defineProperty( - { - $$type: '@backstage/BackstageCredentials', - version: 'v1', - expiresAt, - principal: { - type: 'user', - userEntityRef: sub, - ...(actor && { - actor: { type: 'service', subject: actor }, - }), - }, - }, - 'token', - { + const principal = createUserPrincipal( + sub, + actor ? createServicePrincipal(actor) : undefined, + ); + const result = { + $$type: '@backstage/BackstageCredentials', + version: 'v1', + expiresAt, + principal, + } as const; + Object.defineProperties(result, { + token: { enumerable: false, configurable: true, + writable: true, value: token, }, - ); + toString: { + enumerable: false, + configurable: true, + writable: true, + value: () => `backstageCredentials{${principal}}`, + }, + }); + return result; } export function createCredentialsWithNonePrincipal(): InternalBackstageCredentials { - return { + const principal = createNonePrincipal(); + const result = { $$type: '@backstage/BackstageCredentials', version: 'v1', - principal: { - type: 'none', + principal, + } as const; + Object.defineProperties(result, { + toString: { + enumerable: false, + configurable: true, + writable: true, + value: () => `backstageCredentials{${principal}}`, }, - }; + }); + return result; } export function toInternalBackstageCredentials( @@ -106,3 +124,74 @@ export function toInternalBackstageCredentials( return internalCredentials; } + +function createServicePrincipal( + sub: string, + accessRestrictions?: BackstagePrincipalAccessRestrictions, +): BackstageServicePrincipal { + const result = { + type: 'service', + subject: sub, + accessRestrictions, + } as const; + Object.defineProperties(result, { + toString: { + enumerable: false, + configurable: true, + writable: true, + value: () => { + let parts = sub; + if (accessRestrictions) { + const hash = createHash('sha256') + .update(JSON.stringify(accessRestrictions)) + .digest('base64') + .replace(/=+$/, ''); + parts += `,accessRestrictions=${hash}`; + } + return `servicePrincipal{${parts}}`; + }, + }, + }); + return result; +} + +function createUserPrincipal( + userEntityRef: string, + actor?: BackstageServicePrincipal, +): BackstageUserPrincipal { + const result = { + type: 'user', + userEntityRef, + actor, + } as const; + Object.defineProperties(result, { + toString: { + enumerable: false, + configurable: true, + writable: true, + value: () => { + let parts = userEntityRef; + if (actor) { + parts += `,actor={${actor}}`; + } + return `userPrincipal{${parts}}`; + }, + }, + }); + return result; +} + +function createNonePrincipal(): BackstageNonePrincipal { + const result = { + type: 'none', + } as const; + Object.defineProperties(result, { + toString: { + enumerable: false, + configurable: true, + writable: true, + value: () => 'nonePrincipal', + }, + }); + return result; +} diff --git a/packages/backend-defaults/src/entrypoints/httpRouter/http/createRateLimitMiddleware.ts b/packages/backend-defaults/src/entrypoints/httpRouter/http/createRateLimitMiddleware.ts new file mode 100644 index 0000000000..b139b212d2 --- /dev/null +++ b/packages/backend-defaults/src/entrypoints/httpRouter/http/createRateLimitMiddleware.ts @@ -0,0 +1,40 @@ +/* + * Copyright 2025 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 { NextFunction, Request, Response } from 'express'; +import { RateLimitStoreFactory } from '../../../lib/RateLimitStoreFactory.ts'; +import { Config } from '@backstage/config'; +import { rateLimitMiddleware } from '../../../lib/rateLimitMiddleware.ts'; + +export const createRateLimitMiddleware = (options: { + pluginId: string; + config: Config; +}) => { + const { pluginId, config } = options; + const configKey = `backend.rateLimit.plugin.${pluginId}`; + const enabled = config.has(configKey); + if (!enabled) { + return (_req: Request, _res: Response, next: NextFunction) => { + next(); + }; + } + + const rateLimitOptions = config.getConfig(configKey); + + return rateLimitMiddleware({ + store: RateLimitStoreFactory.create({ config, prefix: pluginId }), + config: rateLimitOptions, + }); +}; diff --git a/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.ts b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.ts index 1f2b989018..0fc70a07f0 100644 --- a/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.ts @@ -22,12 +22,13 @@ import { HttpRouterServiceAuthPolicy, } from '@backstage/backend-plugin-api'; import { - createLifecycleMiddleware, + createAuthIntegrationRouter, createCookieAuthRefreshMiddleware, createCredentialsBarrier, - createAuthIntegrationRouter, + createLifecycleMiddleware, } from './http'; import { MiddlewareFactory } from '../rootHttpRouter'; +import { createRateLimitMiddleware } from './http/createRateLimitMiddleware.ts'; /** * HTTP route registration for plugins. @@ -61,6 +62,8 @@ export const httpRouterServiceFactory = createServiceFactory({ }) { const router = PromiseRouter(); + router.use(createRateLimitMiddleware({ pluginId: plugin.getId(), config })); + rootHttpRouter.use(`/api/${plugin.getId()}`, router); const credentialsBarrier = createCredentialsBarrier({ diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory.ts index 1ff9bd15d1..80a10fe0eb 100644 --- a/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory.ts +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/http/MiddlewareFactory.ts @@ -15,15 +15,15 @@ */ import { - RootConfigService, LoggerService, + RootConfigService, } from '@backstage/backend-plugin-api'; import { - Request, - Response, ErrorRequestHandler, NextFunction, + Request, RequestHandler, + Response, } from 'express'; import cors from 'cors'; import helmet from 'helmet'; @@ -37,12 +37,14 @@ import { InputError, NotAllowedError, NotFoundError, + NotImplementedError, NotModifiedError, - ServiceUnavailableError, serializeError, + ServiceUnavailableError, } from '@backstage/errors'; -import { NotImplementedError } from '@backstage/errors'; import { applyInternalErrorFilter } from './applyInternalErrorFilter'; +import { RateLimitStoreFactory } from '../../../lib/RateLimitStoreFactory.ts'; +import { rateLimitMiddleware } from '../../../lib/rateLimitMiddleware.ts'; type LogMeta = { date: string; @@ -227,6 +229,47 @@ export class MiddlewareFactory { return cors(readCorsOptions(this.#config.getOptionalConfig('backend'))); } + /** + * Returns a middleware that implements rate limiting. + * + * @remarks + * + * Rate limiting is a common technique to prevent abuse of APIs. This middleware is + * configured using the config key `backend.rateLimit`. + * + * @returns An Express request handler + */ + rateLimit(): RequestHandler { + const enabled = this.#config.has('backend.rateLimit'); + if (!enabled) { + return (_req: Request, _res: Response, next: NextFunction) => { + next(); + }; + } + + const useDefaults = this.#config.getOptional('backend.rateLimit') === true; + const rateLimitOptions = useDefaults + ? undefined + : this.#config.getOptionalConfig('backend.rateLimit'); + + // Global rate limiting disabled + if ( + rateLimitOptions && + rateLimitOptions.getOptionalBoolean('global') === false + ) { + return (_req: Request, _res: Response, next: NextFunction) => { + next(); + }; + } + + return rateLimitMiddleware({ + store: useDefaults + ? undefined + : RateLimitStoreFactory.create({ config: this.#config }), + config: rateLimitOptions, + }); + } + /** * Express middleware to handle errors during request processing. * diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts index da7fcfe3f9..3b50515742 100644 --- a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts +++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts @@ -15,13 +15,13 @@ */ import { - RootConfigService, coreServices, createServiceFactory, LifecycleService, LoggerService, + RootConfigService, } from '@backstage/backend-plugin-api'; -import express, { RequestHandler, Express } from 'express'; +import express, { Express, RequestHandler } from 'express'; import type { Server } from 'node:http'; import { createHttpServer, @@ -121,6 +121,7 @@ const rootHttpRouterServiceFactoryWithOptions = ( app.use(middleware.cors()); app.use(middleware.compression()); app.use(middleware.logging()); + app.use(middleware.rateLimit()); app.use(healthRouter); app.use(routes); app.use(middleware.notFound()); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.test.ts index b7ccf165ad..337325f6f8 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.test.ts @@ -108,9 +108,6 @@ describe('GitlabUrlReader', () => { config: createConfig(), response: expect.objectContaining({ url: 'https://gitlab.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch', - headers: expect.objectContaining({ - 'private-token': '', - }), }), }, { @@ -119,7 +116,7 @@ describe('GitlabUrlReader', () => { response: expect.objectContaining({ url: 'https://gitlab.example.com/api/v4/projects/12345/repository/files/my%2Fpath%2Fto%2Ffile.yaml/raw?ref=branch', headers: expect.objectContaining({ - 'private-token': '0123456789', + authorization: 'Bearer 0123456789', }), }), }, @@ -252,10 +249,10 @@ describe('GitlabUrlReader', () => { it('should return the file when using a user token', async () => { worker.use( rest.get('*/api/v4/projects/user%2Fproject', (req, res, ctx) => { - if (req.headers.get('private-token') !== 'gl-user-token') { + if (req.headers.get('authorization') !== 'Bearer gl-user-token') { return res( - ctx.status(403), - ctx.json({ message: 'Not Authorized' }), + ctx.status(401), + ctx.json({ message: '401 Unauthorized' }), ); } return res(ctx.status(200), ctx.json({ id: 12345 })); @@ -571,10 +568,10 @@ describe('GitlabUrlReader', () => { it('should return the file when using a user token', async () => { worker.use( rest.get('*/api/v4/projects/user%2Fproject', (req, res, ctx) => { - if (req.headers.get('private-token') !== 'gl-user-token') { + if (req.headers.get('authorization') !== 'Bearer gl-user-token') { return res( - ctx.status(403), - ctx.json({ message: 'Not Authorized' }), + ctx.status(401), + ctx.json({ message: '401 Unauthorized' }), ); } return res(ctx.status(200), ctx.json({ id: 12345 })); @@ -737,10 +734,10 @@ describe('GitlabUrlReader', () => { (_, res, ctx) => res(ctx.status(200), ctx.json({ id: 12345 })), ), rest.get('*/api/v4/projects/user%2Fproject', (req, res, ctx) => { - if (req.headers.get('private-token') !== 'gl-user-token') { + if (req.headers.get('authorization') !== 'Bearer gl-user-token') { return res( - ctx.status(403), - ctx.json({ message: 'Not Authorized' }), + ctx.status(401), + ctx.json({ message: '401 Unauthorized' }), ); } return res(ctx.status(200), ctx.json({ id: 12345 })); @@ -798,10 +795,10 @@ describe('GitlabUrlReader', () => { (_, res, ctx) => res(ctx.status(404)), ), rest.get('*/api/v4/projects/user%2Fproject', (req, res, ctx) => { - if (req.headers.get('private-token') !== 'gl-user-token') { + if (req.headers.get('authorization') !== 'Bearer gl-user-token') { return res( - ctx.status(403), - ctx.json({ message: 'Not Authorized' }), + ctx.status(401), + ctx.json({ message: '401 Unauthorized' }), ); } return res(ctx.status(200), ctx.json({ id: 12345 })); @@ -857,21 +854,19 @@ describe('GitlabUrlReader', () => { beforeEach(() => { worker.use( rest.get('*/api/v4/projects/group%2Fproject', (req, res, ctx) => { - // the private-token header must be included on API calls - if (req.headers.get('private-token') !== 'gl-dummy-token') { + if (req.headers.get('authorization') !== 'Bearer gl-dummy-token') { return res( - ctx.status(403), - ctx.json({ message: 'Not Authorized' }), + ctx.status(401), + ctx.json({ message: '401 Unauthorized' }), ); } return res(ctx.status(200), ctx.json({ id: 12345 })); }), rest.get('*/api/v4/projects/user%2Fproject', (req, res, ctx) => { - // the private-token header must be included on API calls - if (req.headers.get('private-token') !== 'gl-user-token') { + if (req.headers.get('authorization') !== 'Bearer gl-user-token') { return res( - ctx.status(403), - ctx.json({ message: 'Not Authorized' }), + ctx.status(401), + ctx.json({ message: '401 Unauthorized' }), ); } return res(ctx.status(200), ctx.json({ id: 12345 })); diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts index 3e5497a307..11746fef0d 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/GitlabUrlReader.ts @@ -340,10 +340,7 @@ export class GitlabUrlReader implements UrlReaderService { ); } // Default to the old behavior of assuming the url is for a file - return getGitLabFileFetchUrl(target, { - ...this.integration.config, - ...(token && { token }), - }); + return getGitLabFileFetchUrl(target, this.integration.config, token); } // convert urls of the form: @@ -398,6 +395,12 @@ export class GitlabUrlReader implements UrlReaderService { ); const data = await result.json(); if (!result.ok) { + if (result.status === 401) { + throw new Error( + 'GitLab Error: 401 - Unauthorized. The access token used is either expired, or does not have permission to read the project', + ); + } + throw new Error(`Gitlab error: ${data.error}, ${data.error_description}`); } return Number(data.id); diff --git a/packages/backend-defaults/src/lib/RateLimitStoreFactory.test.ts b/packages/backend-defaults/src/lib/RateLimitStoreFactory.test.ts new file mode 100644 index 0000000000..684c204cb8 --- /dev/null +++ b/packages/backend-defaults/src/lib/RateLimitStoreFactory.test.ts @@ -0,0 +1,68 @@ +/* + * 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 { mockServices } from '@backstage/backend-test-utils'; +import { RateLimitStoreFactory } from './RateLimitStoreFactory.ts'; +import { RedisStore } from 'rate-limit-redis'; + +jest.mock('@keyv/redis', () => { + const Actual = jest.requireActual('@keyv/redis'); + return { + ...Actual, + __esModule: true, + default: jest.fn(() => { + return { + getClient: jest.fn(() => ({ + sendCommand: jest.fn().mockReturnValue('mock'), + })), + }; + }), + }; +}); + +describe('CacheRateLimitStoreFactory', () => { + afterEach(jest.clearAllMocks); + + it('should return undefined store with auto configuration if redis is not available', () => { + const config = mockServices.rootConfig({ + data: { + backend: { + rateLimit: { + store: undefined, + }, + }, + }, + }); + const store = RateLimitStoreFactory.create({ config }); + expect(store).toBeUndefined(); + }); + + it('should return redis store if configured explicitly', async () => { + const config = mockServices.rootConfig({ + data: { + backend: { + rateLimit: { + store: { + type: 'redis', + connection: 'redis://localhost:6379', + }, + }, + }, + }, + }); + const store = RateLimitStoreFactory.create({ config }); + expect(store).toBeInstanceOf(RedisStore); + }); +}); diff --git a/packages/backend-defaults/src/lib/RateLimitStoreFactory.ts b/packages/backend-defaults/src/lib/RateLimitStoreFactory.ts new file mode 100644 index 0000000000..9df6f03225 --- /dev/null +++ b/packages/backend-defaults/src/lib/RateLimitStoreFactory.ts @@ -0,0 +1,58 @@ +/* + * 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 { Config } from '@backstage/config'; +import type { Store } from 'express-rate-limit'; +import { RedisStore } from 'rate-limit-redis'; + +/** + * Creates a store for `express-rate-limit` based on the configuration. + * + * @internal + */ +export class RateLimitStoreFactory { + static create(options: { + config: Config; + prefix?: string; + }): Store | undefined { + const { config, prefix } = options; + const store = config.getOptionalConfig('backend.rateLimit.store'); + if (!store) { + return undefined; + } + const type = store.getString('type'); + switch (type) { + case 'redis': + return this.redis({ store, prefix }); + case 'memory': + default: + return undefined; + } + } + + private static redis(options: { store: Config; prefix?: string }): Store { + const { store, prefix } = options; + const connectionString = store.getString('connection'); + const KeyvRedis = require('@keyv/redis').default; + const keyv = new KeyvRedis(connectionString); + return new RedisStore({ + prefix, + sendCommand: async (...args: string[]) => { + const client = await keyv.getClient(); + return client.sendCommand(args); + }, + }); + } +} diff --git a/packages/backend-defaults/src/lib/rateLimitMiddleware.ts b/packages/backend-defaults/src/lib/rateLimitMiddleware.ts new file mode 100644 index 0000000000..57163b5908 --- /dev/null +++ b/packages/backend-defaults/src/lib/rateLimitMiddleware.ts @@ -0,0 +1,81 @@ +/* + * Copyright 2025 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 { RequestHandler } from 'express'; +import { rateLimit, Store } from 'express-rate-limit'; +import { Config, readDurationFromConfig } from '@backstage/config'; +import { durationToMilliseconds } from '@backstage/types'; + +export const rateLimitMiddleware = (options: { + store?: Store; + config?: Config; +}): RequestHandler => { + const { store, config } = options; + let windowMs: number = 60000; + if (config && config.has('window')) { + const windowDuration = readDurationFromConfig(config, { + key: 'window', + }); + windowMs = durationToMilliseconds(windowDuration); + } + const limit = config?.getOptionalNumber('incomingRequestLimit'); + const ipAllowList = config?.getOptionalStringArray('ipAllowList') ?? [ + '127.0.0.1', + '0:0:0:0:0:0:0:1', + '::1', + ]; + const skipSuccessfulRequests = config?.getOptionalBoolean( + 'skipSuccessfulRequests', + ); + const skipFailedRequests = config?.getOptionalBoolean('skipFailedRequests'); + const passOnStoreError = config?.getOptionalBoolean('passOnStoreError'); + + return rateLimit({ + windowMs, + limit, + skipSuccessfulRequests, + message: { + error: { + name: 'Error', + message: `Too many requests, please try again later`, + }, + response: { + statusCode: 429, + }, + }, + statusCode: 429, + skipFailedRequests, + passOnStoreError: passOnStoreError, + keyGenerator(req, _res): string { + if (!req.ip) { + return req.socket.remoteAddress!; + } + return req.ip; + }, + skip: (req, _res) => { + return ( + Boolean(req.ip && ipAllowList.includes(req.ip)) || + Boolean( + req.socket.remoteAddress && + ipAllowList.includes(req.socket.remoteAddress), + ) + ); + }, + validate: { + trustProxy: false, + }, + store, + }); +}; diff --git a/packages/backend-dynamic-feature-service/CHANGELOG.md b/packages/backend-dynamic-feature-service/CHANGELOG.md index 6620d59216..33f792bbb7 100644 --- a/packages/backend-dynamic-feature-service/CHANGELOG.md +++ b/packages/backend-dynamic-feature-service/CHANGELOG.md @@ -1,5 +1,148 @@ # @backstage/backend-dynamic-feature-service +## 0.7.2-next.1 + +### Patch Changes + +- 3507fcd: Just some more circular dep cleanup +- 3d61c36: Fix wrong imports which lead to module initialization failures when enabling dynamic plugins. +- Updated dependencies + - @backstage/config-loader@1.10.2-next.0 + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/plugin-app-node@0.1.35-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-catalog-backend@3.0.0-next.1 + - @backstage/plugin-events-backend@0.5.4-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.1 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-search-common@1.2.19-next.0 + - @backstage/backend-openapi-utils@0.5.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## 0.7.2-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.0-next.0 + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-scaffolder-node@0.9.1-next.0 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-events-backend@0.5.3 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-search-common@1.2.18 + +## 0.7.1 + +### Patch Changes + +- c83cd8b: Fixed some circular or otherwise unclear imports +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-scaffolder-node@0.9.0 + - @backstage/plugin-catalog-backend@2.1.0 + - @backstage/plugin-events-backend@0.5.3 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/backend-openapi-utils@0.5.4 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-search-common@1.2.18 + +## 0.7.1-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/plugin-catalog-backend@2.0.1-next.2 + - @backstage/plugin-scaffolder-node@0.9.0-next.2 + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-events-backend@0.5.3-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## 0.7.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-backend@2.0.1-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-openapi-utils@0.5.4-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/cli-node@0.2.13 + - @backstage/config@1.3.2 + - @backstage/config-loader@1.10.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-app-node@0.1.34-next.1 + - @backstage/plugin-events-backend@0.5.3-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-search-common@1.2.18 + +## 0.7.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-node@0.8.3-next.0 + - @backstage/plugin-catalog-backend@2.0.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-events-backend@0.5.3-next.0 + - @backstage/cli-node@0.2.13 + - @backstage/config-loader@1.10.1 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + - @backstage/backend-openapi-utils@0.5.4-next.0 + - @backstage/plugin-app-node@0.1.34-next.0 + ## 0.7.0 ### Minor Changes diff --git a/packages/backend-dynamic-feature-service/package.json b/packages/backend-dynamic-feature-service/package.json index 78876d99d9..267696387f 100644 --- a/packages/backend-dynamic-feature-service/package.json +++ b/packages/backend-dynamic-feature-service/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-dynamic-feature-service", - "version": "0.7.0", + "version": "0.7.2-next.1", "description": "Backstage dynamic feature service", "backstage": { "role": "node-library" diff --git a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/router.ts b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/router.ts index 9f1ef68a77..cf48bcfc95 100644 --- a/packages/backend-dynamic-feature-service/src/schema/openapi/generated/router.ts +++ b/packages/backend-dynamic-feature-service/src/schema/openapi/generated/router.ts @@ -18,7 +18,7 @@ // * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. * // ****************************************************************** import { createValidatedOpenApiRouterFromGeneratedEndpointMap } from '@backstage/backend-openapi-utils'; -import { EndpointMap } from './'; +import { EndpointMap } from './apis'; export const spec = { openapi: '3.0.3', diff --git a/packages/backend-dynamic-feature-service/src/server/frontendRemotesServer.ts b/packages/backend-dynamic-feature-service/src/server/frontendRemotesServer.ts index f1a245b1ac..a12804ba48 100644 --- a/packages/backend-dynamic-feature-service/src/server/frontendRemotesServer.ts +++ b/packages/backend-dynamic-feature-service/src/server/frontendRemotesServer.ts @@ -13,14 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { coreServices, createServiceFactory, createServiceRef, } from '@backstage/backend-plugin-api'; import { createRouter } from './router'; -import { dynamicPluginsServiceRef } from '@backstage/backend-dynamic-feature-service'; -import { spec } from '../schema/openapi'; +import { dynamicPluginsServiceRef } from '../manager/plugin-manager'; +import { spec } from '../schema/openapi/generated'; import { ManifestFileName } from '@module-federation/sdk'; import { RemoteInfo } from '../schema/openapi/generated/models'; import { JsonObject } from '@backstage/types'; diff --git a/packages/backend-dynamic-feature-service/src/server/router.ts b/packages/backend-dynamic-feature-service/src/server/router.ts index 61c97797e7..9e2fb59c59 100644 --- a/packages/backend-dynamic-feature-service/src/server/router.ts +++ b/packages/backend-dynamic-feature-service/src/server/router.ts @@ -19,8 +19,8 @@ import { RootConfigService, } from '@backstage/backend-plugin-api'; import express from 'express'; -import { createOpenApiRouter, spec } from '../schema/openapi'; -import { DynamicPluginProvider } from '@backstage/backend-dynamic-feature-service'; +import { createOpenApiRouter, spec } from '../schema/openapi/generated'; +import { DynamicPluginProvider } from '../manager/types'; import * as fs from 'fs'; import * as path from 'path'; import * as url from 'url'; diff --git a/packages/backend-openapi-utils/CHANGELOG.md b/packages/backend-openapi-utils/CHANGELOG.md index 5e070f5e8d..be2ac83634 100644 --- a/packages/backend-openapi-utils/CHANGELOG.md +++ b/packages/backend-openapi-utils/CHANGELOG.md @@ -1,5 +1,37 @@ # @backstage/backend-openapi-utils +## 0.5.5-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.1-next.0 + +## 0.5.4 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## 0.5.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + +## 0.5.4-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + ## 0.5.3 ### Patch Changes diff --git a/packages/backend-openapi-utils/package.json b/packages/backend-openapi-utils/package.json index 97be1762da..60b1afe052 100644 --- a/packages/backend-openapi-utils/package.json +++ b/packages/backend-openapi-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-openapi-utils", - "version": "0.5.3", + "version": "0.5.5-next.0", "description": "OpenAPI typescript support.", "backstage": { "role": "node-library" diff --git a/packages/backend-plugin-api/CHANGELOG.md b/packages/backend-plugin-api/CHANGELOG.md index 6edd3e2c78..16c295fbfa 100644 --- a/packages/backend-plugin-api/CHANGELOG.md +++ b/packages/backend-plugin-api/CHANGELOG.md @@ -1,5 +1,83 @@ # @backstage/backend-plugin-api +## 1.4.1-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + +## 1.4.0 + +### Minor Changes + +- 664c07a: Added `actionsRegistry` and `actions` experimental services to `/alpha` to allow registration of distributed actions from plugins, and the ability to invoke these actions. You can use these services by including them like the following: + + ```ts + import { + actionsRegistryServiceRef, + actionsServiceRef, + } from '@backstage/backend-plugin-api/alpha'; + + createBackendPlugin({ + pluginId: 'test-plugin', + register({ registerInit }) { + registerInit({ + deps: { + actions: actionsServiceRef, + actionsRegistry: actionsRegistryServiceRef, + }, + async init({ actions, actionsRegistry }) { + actionsRegistry.register({ + ..., + }); + + await actions.invoke(...); + }, + }); + }, + }); + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + +## 1.4.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/cli-common@0.1.15 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + +## 1.4.0-next.0 + +### Minor Changes + +- 664c07a: Added `coreServices.actionsRegistry` and `coreServices.actions` to allow registration of distributed actions from plugins, and the ability to invoke these actions + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + ## 1.3.1 ### Patch Changes diff --git a/packages/backend-plugin-api/package.json b/packages/backend-plugin-api/package.json index 17ff606187..ad54d1f2e9 100644 --- a/packages/backend-plugin-api/package.json +++ b/packages/backend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-plugin-api", - "version": "1.3.1", + "version": "1.4.1-next.0", "description": "Core API used by Backstage backend plugins", "backstage": { "role": "node-library" @@ -20,7 +20,7 @@ "license": "Apache-2.0", "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", + "./alpha": "./src/alpha/index.ts", "./testUtils": "./src/testUtils.ts", "./package.json": "./package.json" }, @@ -29,7 +29,7 @@ "typesVersions": { "*": { "alpha": [ - "src/alpha.ts" + "src/alpha/index.ts" ], "testUtils": [ "src/testUtils.ts" @@ -61,9 +61,12 @@ "@backstage/plugin-permission-node": "workspace:^", "@backstage/types": "workspace:^", "@types/express": "^4.17.6", + "@types/json-schema": "^7.0.6", "@types/luxon": "^3.0.0", + "json-schema": "^0.4.0", "knex": "^3.0.0", - "luxon": "^3.0.0" + "luxon": "^3.0.0", + "zod": "^3.22.4" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", diff --git a/packages/backend-plugin-api/report-alpha.api.md b/packages/backend-plugin-api/report-alpha.api.md index d485e2132e..9be7a29ed5 100644 --- a/packages/backend-plugin-api/report-alpha.api.md +++ b/packages/backend-plugin-api/report-alpha.api.md @@ -3,7 +3,105 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { AnyZodObject } from 'zod'; +import { BackstageCredentials } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; +import { JSONSchema7 } from 'json-schema'; +import { JsonValue } from '@backstage/types'; +import { LoggerService } from '@backstage/backend-plugin-api'; import { ServiceRef } from '@backstage/backend-plugin-api'; +import { z } from 'zod'; + +// @alpha (undocumented) +export type ActionsRegistryActionContext = { + input: z.infer; + logger: LoggerService; + credentials: BackstageCredentials; +}; + +// @alpha (undocumented) +export type ActionsRegistryActionOptions< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, +> = { + name: string; + title: string; + description: string; + schema: { + input: (zod: typeof z) => TInputSchema; + output: (zod: typeof z) => TOutputSchema; + }; + attributes?: { + destructive?: boolean; + idempotent?: boolean; + readOnly?: boolean; + }; + action: (context: ActionsRegistryActionContext) => Promise< + z.infer extends void + ? void + : { + output: z.infer; + } + >; +}; + +// @alpha (undocumented) +export interface ActionsRegistryService { + // (undocumented) + register< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, + >( + options: ActionsRegistryActionOptions, + ): void; +} + +// @alpha +export const actionsRegistryServiceRef: ServiceRef< + ActionsRegistryService, + 'plugin', + 'singleton' +>; + +// @alpha (undocumented) +export interface ActionsService { + // (undocumented) + invoke(opts: { + id: string; + input?: JsonObject; + credentials: BackstageCredentials; + }): Promise<{ + output: JsonValue; + }>; + // (undocumented) + list: (opts: { credentials: BackstageCredentials }) => Promise<{ + actions: ActionsServiceAction[]; + }>; +} + +// @alpha (undocumented) +export type ActionsServiceAction = { + id: string; + name: string; + title: string; + description: string; + schema: { + input: JSONSchema7; + output: JSONSchema7; + }; + attributes: { + readOnly: boolean; + destructive: boolean; + idempotent: boolean; + }; +}; + +// @alpha +export const actionsServiceRef: ServiceRef< + ActionsService, + 'plugin', + 'singleton' +>; // @alpha (undocumented) export type BackendFeatureMeta = @@ -23,7 +121,7 @@ export interface InstanceMetadataService { getInstalledFeatures: () => BackendFeatureMeta[]; } -// @alpha +// @alpha (undocumented) export const instanceMetadataServiceRef: ServiceRef< InstanceMetadataService, 'plugin', diff --git a/packages/backend-plugin-api/src/alpha/ActionsRegistryService.ts b/packages/backend-plugin-api/src/alpha/ActionsRegistryService.ts new file mode 100644 index 0000000000..9a7820e354 --- /dev/null +++ b/packages/backend-plugin-api/src/alpha/ActionsRegistryService.ts @@ -0,0 +1,69 @@ +/* + * Copyright 2025 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 { z, AnyZodObject } from 'zod'; +import { + LoggerService, + BackstageCredentials, +} from '@backstage/backend-plugin-api'; + +/** + * @alpha + */ +export type ActionsRegistryActionContext = { + input: z.infer; + logger: LoggerService; + credentials: BackstageCredentials; +}; + +/** + * @alpha + */ +export type ActionsRegistryActionOptions< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, +> = { + name: string; + title: string; + description: string; + schema: { + input: (zod: typeof z) => TInputSchema; + output: (zod: typeof z) => TOutputSchema; + }; + attributes?: { + destructive?: boolean; + idempotent?: boolean; + readOnly?: boolean; + }; + action: ( + context: ActionsRegistryActionContext, + ) => Promise< + z.infer extends void + ? void + : { output: z.infer } + >; +}; + +/** + * @alpha + */ +export interface ActionsRegistryService { + register< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, + >( + options: ActionsRegistryActionOptions, + ): void; +} diff --git a/packages/backend-plugin-api/src/alpha/ActionsService.ts b/packages/backend-plugin-api/src/alpha/ActionsService.ts new file mode 100644 index 0000000000..528b6cea67 --- /dev/null +++ b/packages/backend-plugin-api/src/alpha/ActionsService.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2025 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 { JsonObject, JsonValue } from '@backstage/types'; +import { JSONSchema7 } from 'json-schema'; +import { BackstageCredentials } from '@backstage/backend-plugin-api'; + +/** + * @alpha + */ +export type ActionsServiceAction = { + id: string; + name: string; + title: string; + description: string; + schema: { + input: JSONSchema7; + output: JSONSchema7; + }; + attributes: { + readOnly: boolean; + destructive: boolean; + idempotent: boolean; + }; +}; + +/** + * @alpha + */ +export interface ActionsService { + list: (opts: { + credentials: BackstageCredentials; + }) => Promise<{ actions: ActionsServiceAction[] }>; + invoke(opts: { + id: string; + input?: JsonObject; + credentials: BackstageCredentials; + }): Promise<{ output: JsonValue }>; +} diff --git a/packages/backend-plugin-api/src/services/definitions/InstanceMetadataService.ts b/packages/backend-plugin-api/src/alpha/InstanceMetadataService.ts similarity index 100% rename from packages/backend-plugin-api/src/services/definitions/InstanceMetadataService.ts rename to packages/backend-plugin-api/src/alpha/InstanceMetadataService.ts diff --git a/packages/backend-plugin-api/src/alpha.ts b/packages/backend-plugin-api/src/alpha/index.ts similarity index 60% rename from packages/backend-plugin-api/src/alpha.ts rename to packages/backend-plugin-api/src/alpha/index.ts index 6e91e10671..5bb69eb4e2 100644 --- a/packages/backend-plugin-api/src/alpha.ts +++ b/packages/backend-plugin-api/src/alpha/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Backstage Authors + * Copyright 2025 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. @@ -14,20 +14,21 @@ * limitations under the License. */ -import { createServiceRef } from '@backstage/backend-plugin-api'; - -/** - * EXPERIMENTAL: Instance metadata service. - * - * @alpha - */ -export const instanceMetadataServiceRef = createServiceRef< - import('./services/definitions/InstanceMetadataService').InstanceMetadataService ->({ - id: 'core.instanceMetadata', -}); - export type { BackendFeatureMeta, InstanceMetadataService, -} from './services/definitions/InstanceMetadataService'; +} from './InstanceMetadataService'; + +export type { + ActionsRegistryService, + ActionsRegistryActionOptions, + ActionsRegistryActionContext, +} from './ActionsRegistryService'; + +export type { ActionsService, ActionsServiceAction } from './ActionsService'; + +export { + actionsRegistryServiceRef, + actionsServiceRef, + instanceMetadataServiceRef, +} from './refs'; diff --git a/packages/backend-plugin-api/src/alpha/refs.ts b/packages/backend-plugin-api/src/alpha/refs.ts new file mode 100644 index 0000000000..81996679f7 --- /dev/null +++ b/packages/backend-plugin-api/src/alpha/refs.ts @@ -0,0 +1,56 @@ +/* + * Copyright 2025 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 { createServiceRef } from '@backstage/backend-plugin-api'; + +/** + * @alpha + */ +export const instanceMetadataServiceRef = createServiceRef< + import('./InstanceMetadataService').InstanceMetadataService +>({ + id: 'core.instanceMetadata', +}); + +/** + * Service for calling distributed actions + * + * See {@link ActionsService} + * and {@link https://backstage.io/docs/backend-system/core-services/actions | the service docs} + * for more information. + * + * @alpha + */ +export const actionsServiceRef = createServiceRef< + import('./ActionsService').ActionsService +>({ + id: 'alpha.core.actions', +}); + +/** + * Service for registering and managing distributed actions. + * + * See {@link ActionsRegistryService} + * and {@link https://backstage.io/docs/backend-system/core-services/actions-registry | the service docs} + * for more information. + * + * @alpha + */ +export const actionsRegistryServiceRef = createServiceRef< + import('./ActionsRegistryService').ActionsRegistryService +>({ + id: 'alpha.core.actionsRegistry', +}); diff --git a/packages/backend-plugin-api/src/services/definitions/ActionsRegistryService.ts b/packages/backend-plugin-api/src/services/definitions/ActionsRegistryService.ts new file mode 100644 index 0000000000..6c0936f85c --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/ActionsRegistryService.ts @@ -0,0 +1,67 @@ +/* + * Copyright 2025 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 { z, AnyZodObject } from 'zod'; +import { LoggerService } from './LoggerService'; +import { BackstageCredentials } from './AuthService'; + +/** + * @public + */ +export type ActionsRegistryActionContext = { + input: z.infer; + logger: LoggerService; + credentials: BackstageCredentials; +}; + +/** + * @public + */ +export type ActionsRegistryActionOptions< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, +> = { + name: string; + title: string; + description: string; + schema: { + input: (zod: typeof z) => TInputSchema; + output: (zod: typeof z) => TOutputSchema; + }; + attributes?: { + destructive?: boolean; + idempotent?: boolean; + readOnly?: boolean; + }; + action: ( + context: ActionsRegistryActionContext, + ) => Promise< + z.infer extends void + ? void + : { output: z.infer } + >; +}; + +/** + * @public + */ +export interface ActionsRegistryService { + register< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, + >( + options: ActionsRegistryActionOptions, + ): void; +} diff --git a/packages/backend-plugin-api/src/services/definitions/ActionsService.ts b/packages/backend-plugin-api/src/services/definitions/ActionsService.ts new file mode 100644 index 0000000000..d595008a42 --- /dev/null +++ b/packages/backend-plugin-api/src/services/definitions/ActionsService.ts @@ -0,0 +1,51 @@ +/* + * Copyright 2025 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 { JsonObject, JsonValue } from '@backstage/types'; +import { JSONSchema7 } from 'json-schema'; +import { BackstageCredentials } from './AuthService'; + +/** + * @public + */ +export type ActionsServiceAction = { + id: string; + name: string; + title: string; + description: string; + schema: { + input: JSONSchema7; + output: JSONSchema7; + }; + attributes: { + readOnly: boolean; + destructive: boolean; + idempotent: boolean; + }; +}; + +/** + * @public + */ +export interface ActionsService { + list: (opts: { + credentials: BackstageCredentials; + }) => Promise<{ actions: ActionsServiceAction[] }>; + invoke(opts: { + id: string; + input?: JsonObject; + credentials: BackstageCredentials; + }): Promise<{ output: JsonValue }>; +} diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts index d6346cbe4e..c811a513a8 100644 --- a/packages/backend-plugin-api/src/services/definitions/index.ts +++ b/packages/backend-plugin-api/src/services/definitions/index.ts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - export type { AuditorService, AuditorServiceCreateEventOptions, diff --git a/packages/backend-test-utils/CHANGELOG.md b/packages/backend-test-utils/CHANGELOG.md index 377e15237b..eb46d660b8 100644 --- a/packages/backend-test-utils/CHANGELOG.md +++ b/packages/backend-test-utils/CHANGELOG.md @@ -1,5 +1,127 @@ # @backstage/backend-test-utils +## 1.7.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config@1.3.3-next.0 + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/backend-app-api@1.2.5-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-events-node@0.4.13-next.0 + +## 1.7.0-next.0 + +### Minor Changes + +- ead925a: Add a standard `toString` on credentials objects + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/backend-app-api@1.2.4 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-events-node@0.4.12 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-permission-common@0.9.0 + +## 1.6.0 + +### Minor Changes + +- 6dfb7be: Added `mockServices.permissions()` that can return actual results. +- c999c25: Added an `actionsRegistryServiceMock` and `actionsServiceMock` to `/alpha` export for the experimental services. + + This allows you to write tests for your actions by doing something similar to the following: + + ```ts + import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha'; + + const mockActionsRegistry = actionsRegistryServiceMock(); + const mockCatalog = catalogServiceMock({ + entities: [ + ... + ], + }); + + createGetCatalogEntityAction({ + catalog: mockCatalog, + actionsRegistry: mockActionsRegistry, + }); + + await expect( + mockActionsRegistry.invoke({ + id: 'test:get-catalog-entity', + input: { name: 'test' }, + }), + ).resolves.toEqual(...) + ``` + +### Patch Changes + +- 12c1fd4: Make the `user` credentials mock behave more like production +- Updated dependencies + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/backend-app-api@1.2.4 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12 + - @backstage/plugin-permission-common@0.9.0 + +## 1.6.0-next.2 + +### Patch Changes + +- 12c1fd4: Make the `user` credentials mock behave more like production +- Updated dependencies + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/backend-app-api@1.2.4-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## 1.6.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/backend-app-api@1.2.4-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/config@1.3.2 + - @backstage/errors@1.2.7 + - @backstage/types@1.2.1 + - @backstage/plugin-events-node@0.4.12-next.1 + +## 1.6.0-next.0 + +### Minor Changes + +- c999c25: Added mock implementations for `ActionsService` and `ActionsRegistryService` + +### Patch Changes + +- Updated dependencies + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/backend-app-api@1.2.4-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-events-node@0.4.12-next.0 + ## 1.5.0 ### Minor Changes diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index e64938714f..593102cb67 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-test-utils", - "version": "1.5.0", + "version": "1.7.0-next.1", "description": "Test helpers library for Backstage backends", "backstage": { "role": "node-library" @@ -21,7 +21,8 @@ "license": "Apache-2.0", "exports": { ".": "./src/index.ts", - "./package.json": "./package.json" + "./package.json": "./package.json", + "./alpha": "./src/alpha/index.ts" }, "main": "src/index.ts", "types": "src/index.ts", @@ -29,6 +30,9 @@ "*": { "package.json": [ "package.json" + ], + "alpha": [ + "src/alpha/index.ts" ] } }, @@ -52,6 +56,7 @@ "@backstage/errors": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-events-node": "workspace:^", + "@backstage/plugin-permission-common": "workspace:^", "@backstage/types": "workspace:^", "@keyv/memcache": "^2.0.1", "@keyv/redis": "^4.0.1", @@ -72,7 +77,9 @@ "testcontainers": "^10.0.0", "textextensions": "^5.16.0", "uuid": "^11.0.0", - "yn": "^4.0.0" + "yn": "^4.0.0", + "zod": "^3.22.4", + "zod-to-json-schema": "^3.20.4" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/packages/backend-test-utils/report-alpha.api.md b/packages/backend-test-utils/report-alpha.api.md new file mode 100644 index 0000000000..ccbf96c0c7 --- /dev/null +++ b/packages/backend-test-utils/report-alpha.api.md @@ -0,0 +1,85 @@ +## API Report File for "@backstage/backend-test-utils" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { ActionsRegistryActionOptions } from '@backstage/backend-plugin-api/alpha'; +import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; +import { ActionsService } from '@backstage/backend-plugin-api/alpha'; +import { ActionsServiceAction } from '@backstage/backend-plugin-api/alpha'; +import { AnyZodObject } from 'zod'; +import { BackstageCredentials } from '@backstage/backend-plugin-api'; +import { JsonObject } from '@backstage/types'; +import { JsonValue } from '@backstage/types'; +import { LoggerService } from '@backstage/backend-plugin-api'; +import { ServiceFactory } from '@backstage/backend-plugin-api'; + +// @alpha (undocumented) +export function actionsRegistryServiceMock(options?: { + logger: LoggerService; +}): MockActionsRegistry; + +// @alpha (undocumented) +export namespace actionsRegistryServiceMock { + const // (undocumented) + factory: () => ServiceFactory< + ActionsRegistryService, + 'plugin', + 'singleton' + >; + const // (undocumented) + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; +} + +// @alpha (undocumented) +export namespace actionsServiceMock { + const // (undocumented) + factory: () => ServiceFactory; + const // (undocumented) + mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; +} + +// @alpha +export class MockActionsRegistry + implements ActionsRegistryService, ActionsService +{ + // (undocumented) + readonly actions: Map>; + // (undocumented) + static create(opts: { logger: LoggerService }): MockActionsRegistry; + // (undocumented) + invoke(opts: { + id: string; + input?: JsonObject; + credentials?: BackstageCredentials; + }): Promise<{ + output: JsonValue; + }>; + // (undocumented) + list(): Promise<{ + actions: ActionsServiceAction[]; + }>; + // (undocumented) + register< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, + >(options: ActionsRegistryActionOptions): void; +} + +// @alpha (undocumented) +export type ServiceMock = { + factory: ServiceFactory; +} & { + [Key in keyof TService]: TService[Key] extends ( + ...args: infer Args + ) => infer Return + ? TService[Key] & jest.MockInstance + : TService[Key]; +}; + +// (No @packageDocumentation comment for this package) +``` diff --git a/packages/backend-test-utils/report.api.md b/packages/backend-test-utils/report.api.md index 7edcf6e1b7..4853ca57c5 100644 --- a/packages/backend-test-utils/report.api.md +++ b/packages/backend-test-utils/report.api.md @@ -4,6 +4,7 @@ ```ts import { AuditorService } from '@backstage/backend-plugin-api'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { AuthService } from '@backstage/backend-plugin-api'; import { Backend } from '@backstage/backend-app-api'; import { BackendFeature } from '@backstage/backend-plugin-api'; @@ -275,14 +276,17 @@ export namespace mockServices { partialImpl?: Partial | undefined, ) => ServiceMock; } + export function permissions(options?: { + result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; + }): PermissionsService; // (undocumented) export namespace permissions { - const // (undocumented) - factory: () => ServiceFactory; - const // (undocumented) - mock: ( - partialImpl?: Partial | undefined, - ) => ServiceMock; + const factory: (options?: { + result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; + }) => ServiceFactory; + const mock: ( + partialImpl?: Partial | undefined, + ) => ServiceMock; } // (undocumented) export namespace permissionsRegistry { diff --git a/packages/backend-test-utils/src/next/index.ts b/packages/backend-test-utils/src/alpha/index.ts similarity index 96% rename from packages/backend-test-utils/src/next/index.ts rename to packages/backend-test-utils/src/alpha/index.ts index 572fb3a9e7..d891744260 100644 --- a/packages/backend-test-utils/src/next/index.ts +++ b/packages/backend-test-utils/src/alpha/index.ts @@ -14,5 +14,4 @@ * limitations under the License. */ -export * from './wiring'; export * from './services'; diff --git a/packages/backend-test-utils/src/alpha/services/ActionsRegistryServiceMock.ts b/packages/backend-test-utils/src/alpha/services/ActionsRegistryServiceMock.ts new file mode 100644 index 0000000000..faf89b393a --- /dev/null +++ b/packages/backend-test-utils/src/alpha/services/ActionsRegistryServiceMock.ts @@ -0,0 +1,49 @@ +/* + * Copyright 2025 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 { mockServices } from '../../services'; +import { LoggerService } from '@backstage/backend-plugin-api'; +import { MockActionsRegistry } from './MockActionsRegistry'; +import { simpleMock } from './simpleMock'; +import { + ActionsRegistryService, + actionsRegistryServiceRef, +} from '@backstage/backend-plugin-api/alpha'; +import { actionsRegistryServiceFactory } from '@backstage/backend-defaults/alpha'; + +/** + * @alpha + */ +export function actionsRegistryServiceMock(options?: { + logger: LoggerService; +}): MockActionsRegistry { + return MockActionsRegistry.create({ + logger: options?.logger ?? mockServices.logger.mock(), + }); +} + +/** + * @alpha + */ +export namespace actionsRegistryServiceMock { + export const factory = () => actionsRegistryServiceFactory; + + export const mock = simpleMock( + actionsRegistryServiceRef, + () => ({ + register: jest.fn(), + }), + ); +} diff --git a/packages/backend-test-utils/src/alpha/services/ActionsServiceMock.ts b/packages/backend-test-utils/src/alpha/services/ActionsServiceMock.ts new file mode 100644 index 0000000000..63abff4c37 --- /dev/null +++ b/packages/backend-test-utils/src/alpha/services/ActionsServiceMock.ts @@ -0,0 +1,34 @@ +/* + * Copyright 2025 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 { simpleMock } from './simpleMock'; +import { + ActionsService, + actionsServiceRef, +} from '@backstage/backend-plugin-api/alpha'; +import { actionsServiceFactory } from '@backstage/backend-defaults/alpha'; + +/** + * @alpha + */ +export namespace actionsServiceMock { + export const factory = () => actionsServiceFactory; + + export const mock = simpleMock(actionsServiceRef, () => ({ + invoke: jest.fn(), + list: jest.fn(), + })); +} diff --git a/packages/backend-test-utils/src/alpha/services/MockActionsRegistry.test.ts b/packages/backend-test-utils/src/alpha/services/MockActionsRegistry.test.ts new file mode 100644 index 0000000000..f604689c63 --- /dev/null +++ b/packages/backend-test-utils/src/alpha/services/MockActionsRegistry.test.ts @@ -0,0 +1,236 @@ +/* + * Copyright 2025 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 { + coreServices, + createBackendPlugin, +} from '@backstage/backend-plugin-api'; +import { startTestBackend } from '../../wiring'; +import { actionsRegistryServiceMock } from './ActionsRegistryServiceMock'; +import { mockCredentials } from '../../services'; +import { Router } from 'express'; +import supertest from 'supertest'; +import { + actionsRegistryServiceRef, + actionsServiceRef, +} from '@backstage/backend-plugin-api/alpha'; + +describe('MockActionsRegistry', () => { + it('should be able to register and invoke actions', async () => { + const registry = actionsRegistryServiceMock(); + + registry.register({ + name: 'my-demo-action', + title: 'Test', + description: 'Test', + schema: { + input: z => + z.object({ + name: z.string(), + }), + output: z => + z.object({ + name: z.string(), + }), + }, + action: async ({ input }) => ({ output: { name: input.name } }), + }); + + const result = await registry.invoke({ + id: 'test:my-demo-action', + input: { name: 'test' }, + }); + + expect(result).toEqual({ output: { name: 'test' } }); + }); + + it('should throw an error when the input is invalid to the action', async () => { + const registry = actionsRegistryServiceMock(); + + registry.register({ + name: 'my-demo-action', + title: 'Test', + description: 'Test', + schema: { + input: z => z.object({ name: z.string() }), + output: z => z.object({ name: z.string() }), + }, + action: async ({ input }) => ({ output: { name: input.name } }), + }); + + await expect( + registry.invoke({ id: 'test:my-demo-action', input: { name: 1 } }), + ).rejects.toThrow('Invalid input to action "test:my-demo-action"'); + }); + + it('should throw an error when the action is not found', async () => { + const registry = actionsRegistryServiceMock(); + + await expect(registry.invoke({ id: 'test' })).rejects.toThrow( + 'Action "test" not found, available actions: none', + ); + }); + + it('should throw an error when the action is not found with recommended actions', async () => { + const registry = actionsRegistryServiceMock(); + + registry.register({ + name: 'my-demo-action', + title: 'Test', + description: 'Test', + schema: { + input: z => z.object({ name: z.string() }), + output: z => z.object({ name: z.string() }), + }, + action: async ({ input }) => ({ output: { name: input.name } }), + }); + + await expect(registry.invoke({ id: 'test' })).rejects.toThrow( + 'Action "test" not found, available actions: "test:my-demo-action"', + ); + }); + + it('should throw an error when the output is invalid', async () => { + const registry = actionsRegistryServiceMock(); + + registry.register({ + name: 'my-demo-action', + title: 'Test', + description: 'Test', + schema: { + input: z => z.object({ name: z.number() }), + output: z => z.object({ name: z.string() }), + }, + // @ts-expect-error - we want to test the error case + action: async ({ input }) => ({ output: { name: input.name } }), + }); + + await expect( + registry.invoke({ id: 'test:my-demo-action', input: { name: 1 } }), + ).rejects.toThrow('Invalid output from action "test:my-demo-action"'); + }); + + it('should list the actions correctly', async () => { + const registry = actionsRegistryServiceMock(); + + registry.register({ + name: 'my-demo-action', + title: 'Test', + description: 'Test', + schema: { + input: z => z.object({ name: z.string() }), + output: z => z.object({ name: z.string() }), + }, + action: async ({ input }) => ({ output: { name: input.name } }), + }); + + const result = await registry.list(); + + expect(result).toMatchObject({ + actions: [ + { + id: 'test:my-demo-action', + name: 'my-demo-action', + title: 'Test', + description: 'Test', + attributes: { + destructive: true, + idempotent: false, + readOnly: false, + }, + schema: { + input: { + type: 'object', + properties: { + name: { type: 'string' }, + }, + }, + output: { + type: 'object', + properties: { + name: { type: 'string' }, + }, + }, + }, + }, + ], + }); + }); + + describe('actionsRegistryServiceMock + mockService.actionsRegistry', () => { + it('should be able to register and invoke actions', async () => { + const pluginWithAction = createBackendPlugin({ + pluginId: 'my-plugin', + register(reg) { + reg.registerInit({ + deps: { actionsRegistry: actionsRegistryServiceRef }, + async init({ actionsRegistry }) { + actionsRegistry.register({ + name: 'test', + title: 'Test', + description: 'Test', + schema: { + input: z => z.object({ name: z.string() }), + output: z => z.object({ name: z.string() }), + }, + action: async ({ input }) => { + expect(input).toEqual({ name: 'test' }); + return { output: { name: input.name } }; + }, + }); + }, + }); + }, + }); + + const pluginToCallAction = createBackendPlugin({ + pluginId: 'my-plugin-to-call-action', + register(reg) { + reg.registerInit({ + deps: { + actions: actionsServiceRef, + router: coreServices.httpRouter, + }, + async init({ actions, router }) { + const testRouter = Router(); + router.use(testRouter); + + testRouter.post('/test', async (_, res) => { + const { output } = await actions.invoke({ + id: 'my-plugin:test', + input: { name: 'test' }, + credentials: mockCredentials.service(), + }); + + res.json(output); + }); + }, + }); + }, + }); + + const { server } = await startTestBackend({ + features: [pluginWithAction, pluginToCallAction], + }); + + const { body, status } = await supertest(server).post( + '/api/my-plugin-to-call-action/test', + ); + + expect(status).toBe(200); + expect(body).toEqual({ name: 'test' }); + }); + }); +}); diff --git a/packages/backend-test-utils/src/alpha/services/MockActionsRegistry.ts b/packages/backend-test-utils/src/alpha/services/MockActionsRegistry.ts new file mode 100644 index 0000000000..49c80b7a3d --- /dev/null +++ b/packages/backend-test-utils/src/alpha/services/MockActionsRegistry.ts @@ -0,0 +1,168 @@ +/* + * Copyright 2025 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 { + BackstageCredentials, + LoggerService, +} from '@backstage/backend-plugin-api'; +import { ForwardedError, InputError, NotFoundError } from '@backstage/errors'; +import { JsonObject, JsonValue } from '@backstage/types'; +import { z, AnyZodObject } from 'zod'; +import zodToJsonSchema from 'zod-to-json-schema'; +import { mockCredentials } from '../../services'; +import { + ActionsRegistryActionOptions, + ActionsRegistryService, + ActionsService, + ActionsServiceAction, +} from '@backstage/backend-plugin-api/alpha'; + +/** + * A mock implementation of the ActionsRegistryService and ActionsService that can be used in tests. + * + * This is useful for testing actions that are registered with the ActionsRegistryService and ActionsService. + * + * The plugin ID is hardcoded to `testing` in the mock implementation. + * + * @example + * ```ts + * const actionsRegistry = mockServices.actionsRegistry(); + * + * actionsRegistry.register({ + * name: 'test', + * title: 'Test', + * description: 'Test', + * schema: { + * input: z.object({ name: z.string() }), + * output: z.object({ name: z.string() }), + * }, + * action: async ({ input }) => ({ output: { name: input.name } }), + * }); + * + * + * const result = await actionsRegistry.invoke({ + * id: 'testing:test', + * input: { name: 'test' }, + * }); + * + * expect(result).toEqual({ output: { name: 'test' } }); + * ``` + * + * @alpha + */ +export class MockActionsRegistry + implements ActionsRegistryService, ActionsService +{ + private constructor(private readonly logger: LoggerService) {} + + static create(opts: { logger: LoggerService }) { + return new MockActionsRegistry(opts.logger); + } + + readonly actions: Map> = + new Map(); + + async list(): Promise<{ actions: ActionsServiceAction[] }> { + return { + actions: Array.from(this.actions.entries()).map(([id, action]) => ({ + id, + name: action.name, + title: action.title, + description: action.description, + attributes: { + destructive: action.attributes?.destructive ?? true, + idempotent: action.attributes?.idempotent ?? false, + readOnly: action.attributes?.readOnly ?? false, + }, + schema: { + input: action.schema?.input + ? zodToJsonSchema(action.schema.input(z)) + : zodToJsonSchema(z.object({})), + output: action.schema?.output + ? zodToJsonSchema(action.schema.output(z)) + : zodToJsonSchema(z.object({})), + } as ActionsServiceAction['schema'], + })), + }; + } + + async invoke(opts: { + id: string; + input?: JsonObject; + credentials?: BackstageCredentials; + }): Promise<{ output: JsonValue }> { + const action = this.actions.get(opts.id); + + if (!action) { + const availableActionIds = Array.from(this.actions.keys()).join(', '); + throw new NotFoundError( + `Action "${opts.id}" not found, available actions: ${ + availableActionIds ? `"${availableActionIds}"` : 'none' + }`, + ); + } + + const input = action.schema?.input + ? action.schema.input(z).safeParse(opts.input) + : ({ success: true, data: undefined } as const); + + if (!input.success) { + throw new InputError(`Invalid input to action "${opts.id}"`, input.error); + } + + try { + const result = await action.action({ + input: input.data, + credentials: opts.credentials ?? mockCredentials.none(), + logger: this.logger, + }); + + const output = action.schema?.output + ? action.schema.output(z).safeParse(result?.output) + : ({ success: true, data: result?.output } as const); + + if (!output.success) { + throw new InputError( + `Invalid output from action "${opts.id}"`, + output.error, + ); + } + + return { output: output.data }; + } catch (error) { + throw new ForwardedError( + `Failed execution of action "${opts.id}"`, + error, + ); + } + } + + register< + TInputSchema extends AnyZodObject, + TOutputSchema extends AnyZodObject, + >(options: ActionsRegistryActionOptions): void { + // hardcode test: prefix similar to how the default actions registry does it + // and other places around the testing ecosystem: + // https://github.com/backstage/backstage/blob/a9219496d5c073aaa0b8caf32ece10455cf65e61/packages/backend-test-utils/src/next/services/mockServices.ts#L321 + // https://github.com/backstage/backstage/blob/861f162b4a39117b824669d67a951ed1db142e3d/packages/backend-test-utils/src/next/wiring/ServiceFactoryTester.ts#L99 + const id = `test:${options.name}`; + + if (this.actions.has(id)) { + throw new Error(`Action with id "${id}" is already registered`); + } + + this.actions.set(id, options); + } +} diff --git a/packages/backend-test-utils/src/alpha/services/index.ts b/packages/backend-test-utils/src/alpha/services/index.ts new file mode 100644 index 0000000000..ca9b3f23a0 --- /dev/null +++ b/packages/backend-test-utils/src/alpha/services/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2025 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 { actionsRegistryServiceMock } from './ActionsRegistryServiceMock'; +export { MockActionsRegistry } from './MockActionsRegistry'; +export { actionsServiceMock } from './ActionsServiceMock'; +export { type ServiceMock } from './simpleMock'; diff --git a/packages/backend-test-utils/src/alpha/services/simpleMock.ts b/packages/backend-test-utils/src/alpha/services/simpleMock.ts new file mode 100644 index 0000000000..d07b143f7a --- /dev/null +++ b/packages/backend-test-utils/src/alpha/services/simpleMock.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2025 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 { + createServiceFactory, + ServiceFactory, + ServiceRef, +} from '@backstage/backend-plugin-api'; + +/** @alpha */ +export type ServiceMock = { + factory: ServiceFactory; +} & { + [Key in keyof TService]: TService[Key] extends ( + ...args: infer Args + ) => infer Return + ? TService[Key] & jest.MockInstance + : TService[Key]; +}; + +/** @internal */ +export function simpleMock( + ref: ServiceRef, + mockFactory: () => jest.Mocked, +): (partialImpl?: Partial) => ServiceMock { + return partialImpl => { + const mock = mockFactory(); + if (partialImpl) { + for (const [key, impl] of Object.entries(partialImpl)) { + if (typeof impl === 'function') { + (mock as any)[key].mockImplementation(impl); + } else { + (mock as any)[key] = impl; + } + } + } + return Object.assign(mock, { + factory: createServiceFactory({ + service: ref, + deps: {}, + factory: () => mock, + }), + }) as ServiceMock; + }; +} diff --git a/packages/backend-test-utils/src/index.ts b/packages/backend-test-utils/src/index.ts index d8e0e2c4a6..7cc4546415 100644 --- a/packages/backend-test-utils/src/index.ts +++ b/packages/backend-test-utils/src/index.ts @@ -24,5 +24,6 @@ export * from './cache'; export * from './database'; export * from './msw'; export * from './filesystem'; -export * from './next'; +export * from './services'; +export * from './wiring'; export { mockErrorHandler } from './util'; diff --git a/packages/backend-test-utils/src/next/services/MockAuthService.test.ts b/packages/backend-test-utils/src/services/MockAuthService.test.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockAuthService.test.ts rename to packages/backend-test-utils/src/services/MockAuthService.test.ts diff --git a/packages/backend-test-utils/src/next/services/MockAuthService.ts b/packages/backend-test-utils/src/services/MockAuthService.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockAuthService.ts rename to packages/backend-test-utils/src/services/MockAuthService.ts diff --git a/packages/backend-test-utils/src/next/services/MockEventsService.test.ts b/packages/backend-test-utils/src/services/MockEventsService.test.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockEventsService.test.ts rename to packages/backend-test-utils/src/services/MockEventsService.test.ts diff --git a/packages/backend-test-utils/src/next/services/MockEventsService.ts b/packages/backend-test-utils/src/services/MockEventsService.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockEventsService.ts rename to packages/backend-test-utils/src/services/MockEventsService.ts diff --git a/packages/backend-test-utils/src/next/services/MockHttpAuthService.test.ts b/packages/backend-test-utils/src/services/MockHttpAuthService.test.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockHttpAuthService.test.ts rename to packages/backend-test-utils/src/services/MockHttpAuthService.test.ts diff --git a/packages/backend-test-utils/src/next/services/MockHttpAuthService.ts b/packages/backend-test-utils/src/services/MockHttpAuthService.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockHttpAuthService.ts rename to packages/backend-test-utils/src/services/MockHttpAuthService.ts diff --git a/packages/backend-test-utils/src/services/MockPermissionsService.test.ts b/packages/backend-test-utils/src/services/MockPermissionsService.test.ts new file mode 100644 index 0000000000..eb98fe9457 --- /dev/null +++ b/packages/backend-test-utils/src/services/MockPermissionsService.test.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2025 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 { AuthorizeResult } from '@backstage/plugin-permission-common'; +import { MockPermissionsService } from './MockPermissionsService'; + +describe('MockPermissionsService', () => { + it('should return the correct result', async () => { + const permission = { + permission: { + name: 'test', + type: 'basic', + attributes: {}, + }, + } as const; + + const defaultService = new MockPermissionsService(); + const allowService = new MockPermissionsService({ + result: AuthorizeResult.ALLOW, + }); + const denyService = new MockPermissionsService({ + result: AuthorizeResult.DENY, + }); + + await expect(defaultService.authorize([permission])).resolves.toEqual([ + { + ...permission, + result: AuthorizeResult.ALLOW, + }, + ]); + await expect(allowService.authorize([permission])).resolves.toEqual([ + { + ...permission, + result: AuthorizeResult.ALLOW, + }, + ]); + await expect(denyService.authorize([permission])).resolves.toEqual([ + { + ...permission, + result: AuthorizeResult.DENY, + }, + ]); + }); +}); diff --git a/packages/backend-test-utils/src/services/MockPermissionsService.ts b/packages/backend-test-utils/src/services/MockPermissionsService.ts new file mode 100644 index 0000000000..3637c34554 --- /dev/null +++ b/packages/backend-test-utils/src/services/MockPermissionsService.ts @@ -0,0 +1,52 @@ +/* + * Copyright 2025 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 { PermissionsService } from '@backstage/backend-plugin-api'; +import { + AuthorizePermissionRequest, + AuthorizePermissionResponse, + AuthorizeResult, + QueryPermissionRequest, + QueryPermissionResponse, +} from '@backstage/plugin-permission-common'; + +export class MockPermissionsService implements PermissionsService { + readonly #result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; + + constructor(options?: { + result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; + }) { + this.#result = options?.result ?? AuthorizeResult.ALLOW; + } + + async authorize( + requests: AuthorizePermissionRequest[], + ): Promise { + return requests.map(request => ({ + ...request, + result: this.#result, + })); + } + + async authorizeConditional( + requests: QueryPermissionRequest[], + ): Promise { + return requests.map(request => ({ + ...request, + result: this.#result, + })); + } +} diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts b/packages/backend-test-utils/src/services/MockRootLoggerService.test.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockRootLoggerService.test.ts rename to packages/backend-test-utils/src/services/MockRootLoggerService.test.ts diff --git a/packages/backend-test-utils/src/next/services/MockRootLoggerService.ts b/packages/backend-test-utils/src/services/MockRootLoggerService.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockRootLoggerService.ts rename to packages/backend-test-utils/src/services/MockRootLoggerService.ts diff --git a/packages/backend-test-utils/src/next/services/MockUserInfoService.test.ts b/packages/backend-test-utils/src/services/MockUserInfoService.test.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockUserInfoService.test.ts rename to packages/backend-test-utils/src/services/MockUserInfoService.test.ts diff --git a/packages/backend-test-utils/src/next/services/MockUserInfoService.ts b/packages/backend-test-utils/src/services/MockUserInfoService.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/MockUserInfoService.ts rename to packages/backend-test-utils/src/services/MockUserInfoService.ts diff --git a/packages/backend-test-utils/src/next/services/index.ts b/packages/backend-test-utils/src/services/index.ts similarity index 87% rename from packages/backend-test-utils/src/next/services/index.ts rename to packages/backend-test-utils/src/services/index.ts index 7c3949e207..73f179ca41 100644 --- a/packages/backend-test-utils/src/next/services/index.ts +++ b/packages/backend-test-utils/src/services/index.ts @@ -13,5 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { mockServices, type ServiceMock } from './mockServices'; +export { mockServices } from './mockServices'; export { mockCredentials } from './mockCredentials'; +export { type ServiceMock } from './simpleMock'; diff --git a/packages/backend-test-utils/src/next/services/mockCredentials.test.ts b/packages/backend-test-utils/src/services/mockCredentials.test.ts similarity index 89% rename from packages/backend-test-utils/src/next/services/mockCredentials.test.ts rename to packages/backend-test-utils/src/services/mockCredentials.test.ts index 343d6d6d20..9248e3bde0 100644 --- a/packages/backend-test-utils/src/next/services/mockCredentials.test.ts +++ b/packages/backend-test-utils/src/services/mockCredentials.test.ts @@ -170,4 +170,27 @@ describe('mockCredentials', () => { "Invalid user entity reference 'wrong', expected :/", ); }); + + it('should have a serializable form', () => { + expect(String(mockCredentials.service('my-service'))).toMatchInlineSnapshot( + `"mockCredentials{servicePrincipal{my-service}}"`, + ); + expect( + String(mockCredentials.user('user:default/mock')), + ).toMatchInlineSnapshot( + `"mockCredentials{userPrincipal{user:default/mock}}"`, + ); + expect( + String( + mockCredentials.user('user:default/mock', { + actor: { subject: 'my-actor' }, + }), + ), + ).toMatchInlineSnapshot( + `"mockCredentials{userPrincipal{user:default/mock,actor={my-actor}}}"`, + ); + expect(String(mockCredentials.none())).toMatchInlineSnapshot( + `"mockCredentials{nonePrincipal}"`, + ); + }); }); diff --git a/packages/backend-test-utils/src/next/services/mockCredentials.ts b/packages/backend-test-utils/src/services/mockCredentials.ts similarity index 88% rename from packages/backend-test-utils/src/next/services/mockCredentials.ts rename to packages/backend-test-utils/src/services/mockCredentials.ts index 231c108ac4..d749f7edb1 100644 --- a/packages/backend-test-utils/src/next/services/mockCredentials.ts +++ b/packages/backend-test-utils/src/services/mockCredentials.ts @@ -76,10 +76,19 @@ export namespace mockCredentials { * Creates a mocked credentials object for a unauthenticated principal. */ export function none(): BackstageCredentials { - return { + const result = { $$type: '@backstage/BackstageCredentials', principal: { type: 'none' }, - }; + } as const; + Object.defineProperties(result, { + toString: { + enumerable: false, + configurable: true, + writable: true, + value: () => `mockCredentials{nonePrincipal}`, + }, + }); + return result; } /** @@ -111,16 +120,32 @@ export namespace mockCredentials { options?: { actor?: { subject: string } }, ): BackstageCredentials { validateUserEntityRef(userEntityRef); - return { + const result = { $$type: '@backstage/BackstageCredentials', principal: { type: 'user', userEntityRef, ...(options?.actor && { - actor: { type: 'service', subject: options.actor.subject }, + actor: { type: 'service', subject: options.actor.subject } as const, }), }, - }; + } as const; + Object.defineProperties(result, { + toString: { + enumerable: false, + configurable: true, + value: () => + `mockCredentials{userPrincipal{${userEntityRef}${ + options?.actor ? `,actor={${options.actor.subject}}` : '' + }}}`, + }, + token: { + enumerable: false, + configurable: true, + value: user.token(), + }, + }); + return result; } /** @@ -223,14 +248,27 @@ export namespace mockCredentials { subject: string = DEFAULT_MOCK_SERVICE_SUBJECT, accessRestrictions?: BackstagePrincipalAccessRestrictions, ): BackstageCredentials { - return { + const result = { $$type: '@backstage/BackstageCredentials', principal: { type: 'service', subject, ...(accessRestrictions ? { accessRestrictions } : {}), }, - }; + } as const; + Object.defineProperties(result, { + toString: { + enumerable: false, + configurable: true, + value: () => + `mockCredentials{servicePrincipal{${subject}${ + accessRestrictions + ? `,accessRestrictions=${JSON.stringify(accessRestrictions)}` + : '' + }}}`, + }, + }); + return result; } /** diff --git a/packages/backend-test-utils/src/next/services/mockServices.test.ts b/packages/backend-test-utils/src/services/mockServices.test.ts similarity index 100% rename from packages/backend-test-utils/src/next/services/mockServices.test.ts rename to packages/backend-test-utils/src/services/mockServices.test.ts diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/services/mockServices.ts similarity index 92% rename from packages/backend-test-utils/src/next/services/mockServices.ts rename to packages/backend-test-utils/src/services/mockServices.ts index f68f1337b9..06bf8f9a29 100644 --- a/packages/backend-test-utils/src/next/services/mockServices.ts +++ b/packages/backend-test-utils/src/services/mockServices.ts @@ -36,6 +36,7 @@ import { DiscoveryService, HttpAuthService, LoggerService, + PermissionsService, RootConfigService, ServiceFactory, ServiceRef, @@ -45,6 +46,7 @@ import { } from '@backstage/backend-plugin-api'; import { ConfigReader } from '@backstage/config'; import { EventsService, eventsServiceRef } from '@backstage/plugin-events-node'; +import { AuthorizeResult } from '@backstage/plugin-permission-common'; import { JsonObject } from '@backstage/types'; import { Knex } from 'knex'; import { MockAuthService } from './MockAuthService'; @@ -53,6 +55,8 @@ import { MockRootLoggerService } from './MockRootLoggerService'; import { MockUserInfoService } from './MockUserInfoService'; import { mockCredentials } from './mockCredentials'; import { MockEventsService } from './MockEventsService'; +import { MockPermissionsService } from './MockPermissionsService'; +import { simpleMock } from './simpleMock'; /** @internal */ function createLoggerMock() { @@ -89,43 +93,6 @@ function simpleFactoryWithOptions< ((...options: TOptions) => ServiceFactory); } -/** @public */ -export type ServiceMock = { - factory: ServiceFactory; -} & { - [Key in keyof TService]: TService[Key] extends ( - ...args: infer Args - ) => infer Return - ? TService[Key] & jest.MockInstance - : TService[Key]; -}; - -/** @internal */ -function simpleMock( - ref: ServiceRef, - mockFactory: () => jest.Mocked, -): (partialImpl?: Partial) => ServiceMock { - return partialImpl => { - const mock = mockFactory(); - if (partialImpl) { - for (const [key, impl] of Object.entries(partialImpl)) { - if (typeof impl === 'function') { - (mock as any)[key].mockImplementation(impl); - } else { - (mock as any)[key] = impl; - } - } - } - return Object.assign(mock, { - factory: createServiceFactory({ - service: ref, - deps: {}, - factory: () => mock, - }), - }) as ServiceMock; - }; -} - /** * Mock implementations of the core services, to be used in tests. * @@ -473,8 +440,37 @@ export namespace mockServices { ); } + /** + * Creates a functional mock implementation of the + * {@link @backstage/backend-plugin-api#PermissionsService}. + */ + export function permissions(options?: { + result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; + }): PermissionsService { + return new MockPermissionsService(options); + } export namespace permissions { - export const factory = () => permissionsServiceFactory; + /** + * Creates a mock factory for the + * {@link @backstage/backend-plugin-api#coreServices.permissions}. Just + * returns the given `result` if you supply one. Otherwise, it returns the + * regular default permissions factory. + */ + export const factory = (options?: { + result: AuthorizeResult.ALLOW | AuthorizeResult.DENY; + }) => + options?.result + ? createServiceFactory({ + service: coreServices.permissions, + deps: {}, + factory: () => new MockPermissionsService(options), + }) + : permissionsServiceFactory; + /** + * Creates a mock of the + * {@link @backstage/backend-plugin-api#coreServices.permissions}, + * optionally with some given method implementations. + */ export const mock = simpleMock(coreServices.permissions, () => ({ authorize: jest.fn(), authorizeConditional: jest.fn(), diff --git a/packages/backend-test-utils/src/services/simpleMock.ts b/packages/backend-test-utils/src/services/simpleMock.ts new file mode 100644 index 0000000000..484969f235 --- /dev/null +++ b/packages/backend-test-utils/src/services/simpleMock.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2025 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 { + createServiceFactory, + ServiceFactory, + ServiceRef, +} from '@backstage/backend-plugin-api'; + +/** @public */ +export type ServiceMock = { + factory: ServiceFactory; +} & { + [Key in keyof TService]: TService[Key] extends ( + ...args: infer Args + ) => infer Return + ? TService[Key] & jest.MockInstance + : TService[Key]; +}; + +/** @internal */ +export function simpleMock( + ref: ServiceRef, + mockFactory: () => jest.Mocked, +): (partialImpl?: Partial) => ServiceMock { + return partialImpl => { + const mock = mockFactory(); + if (partialImpl) { + for (const [key, impl] of Object.entries(partialImpl)) { + if (typeof impl === 'function') { + (mock as any)[key].mockImplementation(impl); + } else { + (mock as any)[key] = impl; + } + } + } + return Object.assign(mock, { + factory: createServiceFactory({ + service: ref, + deps: {}, + factory: () => mock, + }), + }) as ServiceMock; + }; +} diff --git a/packages/backend-test-utils/src/util/errorHandler.ts b/packages/backend-test-utils/src/util/errorHandler.ts index f534823f50..79f4d8fd04 100644 --- a/packages/backend-test-utils/src/util/errorHandler.ts +++ b/packages/backend-test-utils/src/util/errorHandler.ts @@ -15,7 +15,7 @@ */ import { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter'; -import { mockServices } from '../next'; +import { mockServices } from '../services'; /** * A mock for error handler middleware that can be used in router tests. diff --git a/packages/backend-test-utils/src/next/wiring/ServiceFactoryTester.test.ts b/packages/backend-test-utils/src/wiring/ServiceFactoryTester.test.ts similarity index 100% rename from packages/backend-test-utils/src/next/wiring/ServiceFactoryTester.test.ts rename to packages/backend-test-utils/src/wiring/ServiceFactoryTester.test.ts diff --git a/packages/backend-test-utils/src/next/wiring/ServiceFactoryTester.ts b/packages/backend-test-utils/src/wiring/ServiceFactoryTester.ts similarity index 97% rename from packages/backend-test-utils/src/next/wiring/ServiceFactoryTester.ts rename to packages/backend-test-utils/src/wiring/ServiceFactoryTester.ts index 83a6a42307..2b49abc88f 100644 --- a/packages/backend-test-utils/src/next/wiring/ServiceFactoryTester.ts +++ b/packages/backend-test-utils/src/wiring/ServiceFactoryTester.ts @@ -20,7 +20,7 @@ import { defaultServiceFactories } from './TestBackend'; // This is a relative import in order to make sure that the implementation is duplicated // rather than leading to an import from @backstage/backend-app-api. // eslint-disable-next-line @backstage/no-relative-monorepo-imports -import { ServiceRegistry } from '../../../../backend-app-api/src/wiring/ServiceRegistry'; +import { ServiceRegistry } from '../../../backend-app-api/src/wiring/ServiceRegistry'; /** * Options for {@link ServiceFactoryTester}. diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.test.ts b/packages/backend-test-utils/src/wiring/TestBackend.test.ts similarity index 100% rename from packages/backend-test-utils/src/next/wiring/TestBackend.test.ts rename to packages/backend-test-utils/src/wiring/TestBackend.test.ts diff --git a/packages/backend-test-utils/src/next/wiring/TestBackend.ts b/packages/backend-test-utils/src/wiring/TestBackend.ts similarity index 97% rename from packages/backend-test-utils/src/next/wiring/TestBackend.ts rename to packages/backend-test-utils/src/wiring/TestBackend.ts index 20d02cf880..cdfa1fc695 100644 --- a/packages/backend-test-utils/src/next/wiring/TestBackend.ts +++ b/packages/backend-test-utils/src/wiring/TestBackend.ts @@ -31,7 +31,7 @@ import express from 'express'; import { InternalBackendFeature, InternalBackendRegistrations, -} from '../../../../backend-plugin-api/src/wiring/types'; +} from '../../../backend-plugin-api/src/wiring/types'; import { DefaultRootHttpRouter, ExtendedHttpServer, @@ -40,6 +40,10 @@ import { createHttpServer, } from '@backstage/backend-defaults/rootHttpRouter'; import { HostDiscovery } from '@backstage/backend-defaults/discovery'; +import { + actionsRegistryServiceMock, + actionsServiceMock, +} from '../alpha/services'; /** @public */ export interface TestBackendOptions { @@ -84,6 +88,10 @@ export const defaultServiceFactories = [ mockServices.userInfo.factory(), mockServices.urlReader.factory(), mockServices.events.factory(), + + // Alpha services + actionsRegistryServiceMock.factory(), + actionsServiceMock.factory(), ]; /** diff --git a/packages/backend-test-utils/src/next/wiring/index.ts b/packages/backend-test-utils/src/wiring/index.ts similarity index 100% rename from packages/backend-test-utils/src/next/wiring/index.ts rename to packages/backend-test-utils/src/wiring/index.ts diff --git a/packages/backend/CHANGELOG.md b/packages/backend/CHANGELOG.md index a197dd647f..f61280d204 100644 --- a/packages/backend/CHANGELOG.md +++ b/packages/backend/CHANGELOG.md @@ -1,5 +1,240 @@ # example-backend +## 0.0.40-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-permission-common@0.9.1-next.0 + - @backstage/plugin-permission-node@0.10.2-next.0 + - @backstage/catalog-model@1.7.5-next.0 + - @backstage/backend-defaults@0.11.1-next.1 + - @backstage/plugin-app-backend@0.5.4-next.0 + - @backstage/plugin-devtools-backend@0.5.7-next.1 + - @backstage/plugin-proxy-backend@0.6.4-next.0 + - @backstage/backend-plugin-api@1.4.1-next.0 + - @backstage/plugin-auth-backend@0.25.2-next.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.10-next.0 + - @backstage/plugin-auth-node@0.6.5-next.0 + - @backstage/plugin-catalog-backend@3.0.0-next.1 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.4-next.0 + - @backstage/plugin-events-backend@0.5.4-next.0 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.2-next.0 + - @backstage/plugin-kubernetes-backend@0.19.8-next.0 + - @backstage/plugin-notifications-backend@0.5.8-next.1 + - @backstage/plugin-permission-backend@0.7.2-next.0 + - @backstage/plugin-scaffolder-backend@2.0.1-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.8.1-next.1 + - @backstage/plugin-search-backend@2.0.4-next.1 + - @backstage/plugin-search-backend-module-catalog@0.3.6-next.0 + - @backstage/plugin-search-backend-module-explore@0.3.4-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.4-next.1 + - @backstage/plugin-search-backend-node@1.3.13-next.0 + - @backstage/plugin-signals-backend@0.3.6-next.0 + - @backstage/plugin-techdocs-backend@2.0.4-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.2-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.10-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.2.12-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.10-next.0 + - @backstage/plugin-mcp-actions-backend@0.1.1-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.5-next.0 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.12-next.1 + +## 0.0.40-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.0-next.0 + - @backstage/backend-defaults@0.11.1-next.0 + - @backstage/plugin-scaffolder-backend@2.0.1-next.0 + - @backstage/plugin-notifications-backend@0.5.8-next.0 + - @backstage/plugin-mcp-actions-backend@0.1.1-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.8.1-next.0 + - @backstage/plugin-search-backend@2.0.4-next.0 + - @backstage/plugin-app-backend@0.5.3 + - @backstage/plugin-auth-backend@0.25.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-devtools-backend@0.5.7-next.0 + - @backstage/plugin-events-backend@0.5.3 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1 + - @backstage/plugin-kubernetes-backend@0.19.7 + - @backstage/plugin-permission-backend@0.7.1 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-proxy-backend@0.6.3 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-signals-backend@0.3.5 + - @backstage/plugin-techdocs-backend@2.0.4-next.0 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9 + - @backstage/plugin-catalog-backend-module-openapi@0.2.12-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9 + - @backstage/plugin-search-backend-module-catalog@0.3.5 + - @backstage/plugin-search-backend-module-explore@0.3.3 + - @backstage/plugin-search-backend-module-techdocs@0.4.4-next.0 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.12-next.0 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1 + - @backstage/plugin-permission-common@0.9.0 + +## 0.0.39 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-notifications-backend@0.5.7 + - @backstage/plugin-scaffolder-backend-module-github@0.8.0 + - @backstage/backend-defaults@0.11.0 + - @backstage/plugin-scaffolder-backend@2.0.0 + - @backstage/plugin-catalog-backend@2.1.0 + - @backstage/plugin-devtools-backend@0.5.6 + - @backstage/plugin-mcp-actions-backend@0.1.0 + - @backstage/plugin-events-backend@0.5.3 + - @backstage/plugin-search-backend@2.0.3 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.11 + - @backstage/plugin-auth-node@0.6.4 + - @backstage/plugin-search-backend-module-techdocs@0.4.3 + - @backstage/backend-plugin-api@1.4.0 + - @backstage/plugin-kubernetes-backend@0.19.7 + - @backstage/plugin-search-backend-module-catalog@0.3.5 + - @backstage/plugin-techdocs-backend@2.0.3 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-app-backend@0.5.3 + - @backstage/plugin-auth-backend@0.25.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3 + - @backstage/plugin-catalog-backend-module-openapi@0.2.11 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1 + - @backstage/plugin-permission-backend@0.7.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1 + - @backstage/plugin-proxy-backend@0.6.3 + - @backstage/plugin-search-backend-module-explore@0.3.3 + - @backstage/plugin-search-backend-node@1.3.12 + - @backstage/plugin-signals-backend@0.3.5 + +## 0.0.39-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-github@0.8.0-next.2 + - @backstage/backend-defaults@0.11.0-next.2 + - @backstage/plugin-scaffolder-backend@2.0.0-next.2 + - @backstage/plugin-notifications-backend@0.5.7-next.2 + - @backstage/plugin-catalog-backend@2.0.1-next.2 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.2 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-app-backend@0.5.3-next.1 + - @backstage/plugin-auth-backend@0.25.1-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4-next.1 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.2.11-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1-next.1 + - @backstage/plugin-devtools-backend@0.5.6-next.2 + - @backstage/plugin-events-backend@0.5.3-next.1 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1-next.1 + - @backstage/plugin-kubernetes-backend@0.19.7-next.1 + - @backstage/plugin-permission-backend@0.7.1-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-proxy-backend@0.6.3-next.1 + - @backstage/plugin-search-backend@2.0.3-next.2 + - @backstage/plugin-search-backend-module-catalog@0.3.5-next.1 + - @backstage/plugin-search-backend-module-explore@0.3.3-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-signals-backend@0.3.5-next.1 + - @backstage/plugin-techdocs-backend@2.0.3-next.2 + +## 0.0.39-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.1 + - @backstage/plugin-notifications-backend@0.5.7-next.1 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.1 + - @backstage/plugin-scaffolder-backend@2.0.0-next.1 + - @backstage/plugin-auth-node@0.6.4-next.1 + - @backstage/plugin-catalog-backend@2.0.1-next.1 + - @backstage/plugin-kubernetes-backend@0.19.7-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.7.2-next.1 + - @backstage/plugin-search-backend-module-catalog@0.3.5-next.1 + - @backstage/plugin-techdocs-backend@2.0.3-next.1 + - @backstage/backend-defaults@0.10.1-next.1 + - @backstage/backend-plugin-api@1.4.0-next.1 + - @backstage/catalog-model@1.7.4 + - @backstage/plugin-app-backend@0.5.3-next.1 + - @backstage/plugin-auth-backend@0.25.1-next.1 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4-next.1 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9-next.1 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3-next.1 + - @backstage/plugin-catalog-backend-module-openapi@0.2.11-next.1 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.1 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1-next.1 + - @backstage/plugin-devtools-backend@0.5.6-next.1 + - @backstage/plugin-events-backend@0.5.3-next.1 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1-next.1 + - @backstage/plugin-permission-backend@0.7.1-next.1 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9-next.1 + - @backstage/plugin-permission-common@0.9.0 + - @backstage/plugin-permission-node@0.10.1-next.1 + - @backstage/plugin-proxy-backend@0.6.3-next.1 + - @backstage/plugin-search-backend@2.0.3-next.1 + - @backstage/plugin-search-backend-module-explore@0.3.3-next.1 + - @backstage/plugin-search-backend-node@1.3.12-next.1 + - @backstage/plugin-signals-backend@0.3.5-next.1 + +## 0.0.39-next.0 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@2.0.1-next.0 + - @backstage/backend-plugin-api@1.4.0-next.0 + - @backstage/backend-defaults@0.10.1-next.0 + - @backstage/plugin-events-backend@0.5.3-next.0 + - @backstage/plugin-search-backend@2.0.3-next.0 + - @backstage/plugin-scaffolder-backend@1.33.1-next.0 + - @backstage/plugin-scaffolder-backend-module-github@0.7.2-next.0 + - @backstage/plugin-scaffolder-backend-module-notifications@0.1.11-next.0 + - @backstage/plugin-techdocs-backend@2.0.3-next.0 + - @backstage/plugin-app-backend@0.5.3-next.0 + - @backstage/plugin-auth-backend@0.25.1-next.0 + - @backstage/plugin-auth-backend-module-github-provider@0.3.4-next.0 + - @backstage/plugin-auth-backend-module-guest-provider@0.2.9-next.0 + - @backstage/plugin-auth-node@0.6.4-next.0 + - @backstage/plugin-catalog-backend-module-openapi@0.2.11-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.9-next.0 + - @backstage/plugin-devtools-backend@0.5.6-next.0 + - @backstage/plugin-events-backend-module-google-pubsub@0.1.1-next.0 + - @backstage/plugin-kubernetes-backend@0.19.7-next.0 + - @backstage/plugin-notifications-backend@0.5.7-next.0 + - @backstage/plugin-permission-backend@0.7.1-next.0 + - @backstage/plugin-permission-backend-module-allow-all-policy@0.2.9-next.0 + - @backstage/plugin-permission-node@0.10.1-next.0 + - @backstage/plugin-proxy-backend@0.6.3-next.0 + - @backstage/plugin-search-backend-module-catalog@0.3.5-next.0 + - @backstage/plugin-search-backend-module-explore@0.3.3-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.3-next.0 + - @backstage/plugin-search-backend-node@1.3.12-next.0 + - @backstage/plugin-signals-backend@0.3.5-next.0 + - @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.3-next.0 + - @backstage/plugin-catalog-backend-module-unprocessed@0.6.1-next.0 + ## 0.0.38 ### Patch Changes diff --git a/packages/backend/package.json b/packages/backend/package.json index 49d43fe026..0d254b629a 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -1,6 +1,6 @@ { "name": "example-backend", - "version": "0.0.38", + "version": "0.0.40-next.1", "backstage": { "role": "backend" }, @@ -47,6 +47,7 @@ "@backstage/plugin-events-backend": "workspace:^", "@backstage/plugin-events-backend-module-google-pubsub": "workspace:^", "@backstage/plugin-kubernetes-backend": "workspace:^", + "@backstage/plugin-mcp-actions-backend": "workspace:^", "@backstage/plugin-notifications-backend": "workspace:^", "@backstage/plugin-permission-backend": "workspace:^", "@backstage/plugin-permission-backend-module-allow-all-policy": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 23d814f1ae..f46e947b0d 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -62,4 +62,5 @@ backend.add(import('@backstage/plugin-notifications-backend')); backend.add(import('./instanceMetadata')); backend.add(import('@backstage/plugin-events-backend-module-google-pubsub')); +backend.add(import('@backstage/plugin-mcp-actions-backend')); backend.start(); diff --git a/packages/canon/.eslintrc.js b/packages/canon/.eslintrc.js index f7c0e8cbd1..9638ff6e45 100644 --- a/packages/canon/.eslintrc.js +++ b/packages/canon/.eslintrc.js @@ -3,6 +3,7 @@ module.exports = { extends: ['plugin:storybook/recommended'], rules: { 'react/forbid-elements': 'off', + '@backstage/no-mixed-plugin-imports': 'off' }, }; diff --git a/packages/canon/.storybook/main.ts b/packages/canon/.storybook/main.ts index e58c0f182f..262862c657 100644 --- a/packages/canon/.storybook/main.ts +++ b/packages/canon/.storybook/main.ts @@ -9,16 +9,12 @@ function getAbsolutePath(value: string): string { return dirname(require.resolve(join(value, 'package.json'))); } const config: StorybookConfig = { - stories: [ - '../src/components/**/*.stories.@(js|jsx|mjs|ts|tsx)', - '../src/stories/**/*.stories.@(js|jsx|mjs|ts|tsx)', - ], + stories: ['../src/components/**/*.stories.@(js|jsx|mjs|ts|tsx)'], staticDirs: ['../static'], addons: [ getAbsolutePath('@storybook/addon-webpack5-compiler-swc'), getAbsolutePath('@storybook/addon-essentials'), getAbsolutePath('@storybook/addon-interactions'), - getAbsolutePath('@storybook/addon-themes'), ], framework: { name: getAbsolutePath('@storybook/react-webpack5'), diff --git a/packages/canon/.storybook/preview.tsx b/packages/canon/.storybook/preview.tsx index 405cdfa093..645b328cb2 100644 --- a/packages/canon/.storybook/preview.tsx +++ b/packages/canon/.storybook/preview.tsx @@ -1,8 +1,74 @@ -import type { Preview, ReactRenderer } from '@storybook/react'; -import { withThemeByDataAttribute } from '@storybook/addon-themes'; +import React, { useEffect } from 'react'; +import type { Decorator, Preview, ReactRenderer } from '@storybook/react'; +import { useGlobals } from '@storybook/preview-api'; + +// Default Backstage theme import '../src/css/styles.css'; +// Custom themes +import './themes/spotify.css'; + +export const withThemes: Decorator = StoryFn => { + const [globals] = useGlobals(); + const selectedTheme = globals.themeMode || 'light'; + const selectedThemeName = globals.themeName || 'default'; + + useEffect(() => { + const htmlElement = document.documentElement; + + // Remove any existing theme data attributes + htmlElement.removeAttribute('data-theme'); + htmlElement.removeAttribute('data-theme-name'); + + // Add the selected theme data attribute + htmlElement.setAttribute('data-theme', selectedTheme); + htmlElement.setAttribute('data-theme-name', selectedThemeName); + + // Cleanup on unmount + return () => { + htmlElement.removeAttribute('data-theme'); + htmlElement.removeAttribute('data-theme-name'); + }; + }, [selectedTheme, selectedThemeName]); + + return ; +}; + const preview: Preview = { + globalTypes: { + themeMode: { + name: 'Theme Mode', + description: 'Global theme mode for components', + defaultValue: 'light', + toolbar: { + icon: 'circlehollow', + items: [ + { value: 'light', icon: 'circlehollow', title: 'Light' }, + { value: 'dark', icon: 'circle', title: 'Dark' }, + ], + showName: true, + dynamicTitle: true, + }, + }, + themeName: { + name: 'Theme Name', + description: 'Global theme name for components', + defaultValue: 'default', + toolbar: { + icon: 'paintbrush', + items: [ + { value: 'default', title: 'Default (Backstage)' }, + { value: 'spotify', title: 'Spotify' }, + ], + showName: true, + dynamicTitle: true, + }, + }, + }, + initialGlobals: { + themeMode: 'light', + themeName: 'default', + }, parameters: { controls: { matchers: { @@ -67,13 +133,7 @@ const preview: Preview = { }, }, decorators: [ - withThemeByDataAttribute({ - themes: { - Light: 'light', - Dark: 'dark', - }, - defaultTheme: 'Light', - }), + withThemes, Story => { document.body.style.backgroundColor = 'var(--canon-bg)'; diff --git a/packages/canon/.storybook/themes/spotify.css b/packages/canon/.storybook/themes/spotify.css new file mode 100644 index 0000000000..74c7138a21 --- /dev/null +++ b/packages/canon/.storybook/themes/spotify.css @@ -0,0 +1,194 @@ +@font-face { + font-family: CircularSp; + font-weight: 700; + font-display: swap; + unicode-range: U+0000, U+000D, U+0020-007E, U+00A0-017E, U+018F, U+0192, + U+01A0-01A1, U+01AF-01B0, U+01B5-01B6, U+01C4-01C6, U+01F1-01F3, U+01FA-01FF, + U+0218-021B, U+0237, U+0259, U+02BB-02BC, U+02C6-02C7, U+02C9, U+02D8-02DD, + U+0300-0301, U+0303, U+0309, U+0323, U+0394, U+03A9, U+03BC, U+03C0, + U+1E80-1E85, U+1E8A-1E8B, U+1EA0-1EF9, U+1FD6, U+2007-2008, U+200B, + U+2010-2011, U+2013-2014, U+2018-201A, U+201C-201E, U+2020-2022, U+2026, + U+2030, U+2032-2033, U+2039-203A, U+2042, U+2044, U+2051, U+2070, + U+2074-2079, U+2080-2089, U+20AB-20AC, U+2113, U+2117, U+2122, U+2126, + U+2160-2169, U+216C-216F, U+2190-2193, U+2196-2199, U+21A9, U+21B0-21B5, + U+21C6, U+2202, U+2206, U+220F, U+2211-2212, U+2215, U+2219-221A, U+221E, + U+222B, U+2248, U+2260, U+2264-2265, U+22C5, U+24C5, U+25A0-25A1, U+25AF, + U+25B2-25B3, U+25CA-25CB, U+25CF, U+262E, U+2713, U+2715, U+2780-2788, + U+E000, U+E002, U+F6C3, U+FB00-FB04, U+FEFF, U+FF0C, U+FF0E, U+FF1A-FF1B, + U+FFFF; + src: url('https://encore.scdn.co/fonts/CircularSp-Bold-602e7aefc706aa36c6ec1324b9bbc461.woff2') + format('woff2'), + url('https://encore.scdn.co/fonts/CircularSp-Bold-856afe2da4ba4e61239b129e2c16d633.woff') + format('woff'); +} + +[data-theme='dark'][data-theme-name='spotify'] { + --canon-font-text: CircularSp, CircularSp-Arab, CircularSp-Hebr, + CircularSp-Cyrl, CircularSp-Grek, CircularSp-Deva; + --canon-font-title: CircularSpTitle, CircularSp-Arab, CircularSp-Hebr, + CircularSp-Cyrl, CircularSp-Grek, CircularSp-Deva; + --canon-font-regular: CircularSp, CircularSp-Arab, CircularSp-Hebr, + CircularSp-Cyrl, CircularSp-Grek, CircularSp-Deva; + + /* Gray scale */ + --canon-gray-1: #191919; + --canon-gray-2: #242424; + --canon-gray-3: #373737; + --canon-gray-4: #464646; + --canon-gray-5: #575757; + --canon-gray-6: #7b7b7b; + --canon-gray-7: #9e9e9e; + --canon-gray-8: #b4b4b4; + + /* Background Colors */ + --canon-bg: #000000; + --canon-bg-surface-1: #191919; + --canon-bg-surface-2: #242424; + --canon-bg-solid: #1ed760; + --canon-bg-solid-hover: #3be477; + --canon-bg-solid-pressed: #1abc54; + --canon-bg-solid-disabled: #0f6c30; + --canon-bg-tint: #242424; + --canon-bg-tint-hover: #202020; + --canon-bg-tint-pressed: #292929; + --canon-bg-tint-disabled: rgba(255, 255, 255, 0.8); + --canon-bg-danger: #3b1219; + --canon-bg-warning: #302008; + --canon-bg-success: #132d21; + --canon-bg-underline: #d16ecb; + + /* Foreground Colors */ + --canon-fg-primary: #ffffff; + --canon-fg-secondary: #9e9e9e; + --canon-fg-link: #ffffff; + --canon-fg-link-hover: #ffffff; + --canon-fg-disabled: #575757; + --canon-fg-solid: #000000; + --canon-fg-solid-disabled: #083618; + --canon-fg-tint: #ffffff; + --canon-fg-tint-disabled: #575757; + --canon-fg-danger: #e22b2b; + --canon-fg-warning: #e36d05; + --canon-fg-success: #1db954; + + /* Border Colors */ + --canon-border: var(--canon-gray-3); + --canon-border-hover: rgba(255, 255, 255, 0.4); + --canon-border-pressed: rgba(255, 255, 255, 0.5); + --canon-border-disabled: rgba(255, 255, 255, 0.2); + --canon-border-danger: #f87a7a; + --canon-border-warning: #e36d05; + --canon-border-success: #53db83; + + /* Ring Colors */ + --canon-ring: rgba(255, 255, 255, 0.2); +} + +#root { + padding-top: var(--header-height); +} + +.canon-Button, +.canon-IconButton { + border-radius: var(--canon-radius-3); + transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out, + box-shadow 0.2s ease-in-out; +} + +.canon-Button--variant-primary, +.canon-IconButton--variant-primary { + &:hover { + box-shadow: inset 0 0 0 1px var(--canon-bg-solid); + background-color: transparent; + color: var(--canon-fg-primary); + } + + &:active { + background-color: rgba(30, 215, 96, 0.1); + } + + &:disabled { + background-color: var(--canon-bg-solid-disabled); + color: var(--canon-fg-solid-disabled); + box-shadow: none; + } +} + +.canon-Button[data-size='medium'], +.canon-Button[data-size='small'] { + padding-inline: var(--canon-space-3); +} + +.canon-MenuTrigger { + all: unset; + display: inline-flex; +} + +.canon-MenuPopup { + box-sizing: border-box; + max-width: 21.25rem; +} + +.canon-MenuSubmenuTrigger, +.canon-MenuItem { + height: auto; + min-height: 2rem; +} + +.canon-Text { + font-family: var(--canon-font-text); +} + +.canon-Heading { + font-family: var(--canon-font-title); +} + +.canon-TableRow { + border: none; + border-radius: var(--canon-radius-4); +} + +.canon-TableRow:hover td:first-child { + border-top-left-radius: var(--canon-radius-2); + border-bottom-left-radius: var(--canon-radius-2); +} + +.canon-TableRow:hover td:last-child { + border-top-right-radius: var(--canon-radius-2); + border-bottom-right-radius: var(--canon-radius-2); +} + +.canon-TableBody:before, +.canon-TableBody:after { + line-height: var(--canon-space-1); + content: '\200C'; + display: block; +} + +.canon-TableHeader .canon-TableRow { + border-bottom: 1px solid var(--canon-border); +} + +.canon-TableHead { + font-size: var(--canon-font-size-2); + color: var(--canon-fg-secondary); + font-weight: var(--canon-font-weight-regular); +} + +.canon-ScrollAreaRoot { + width: 100%; + /* TODO: Bring this as a fix in OS */ + height: unset; +} + +.canon-TabsIndicator { + background-color: var(--canon-bg-underline); +} + +.canon-TabsTab[data-selected] { + background: radial-gradient( + ellipse at bottom, + rgba(209, 110, 203, 0.25) 0%, + transparent 95% + ); +} diff --git a/packages/canon/CHANGELOG.md b/packages/canon/CHANGELOG.md index b53f1dc3a0..9daf374ba4 100644 --- a/packages/canon/CHANGELOG.md +++ b/packages/canon/CHANGELOG.md @@ -1,5 +1,73 @@ # @backstage/canon +## 0.6.0-next.0 + +### Minor Changes + +- 4c6d891: **BREAKING CHANGES** + + We’re updating our Button component to provide better support for button links. + + - We’re introducing a new `ButtonLink` component, which replaces the previous render prop pattern. + - To maintain naming consistency across components, `IconButton` is being renamed to `ButtonIcon`. + - Additionally, the render prop will be removed from all button-related components. + + These changes aim to simplify usage and improve clarity in our component API. + +### Patch Changes + +- 140f652: We are consolidating all css files into a single styles.css in Canon. +- 8154fb9: Add new SearchField component in Canon +- 6910892: Add new `RadioGroup` + `Radio` component to Canon +- a8a8514: We are transforming how we structure our class names and data attributes definitions for all components. They are now all set in the same place. +- 667b951: Added placeholder prop to TextField component. +- e71333a: adding export for ButtonLink so it's importable + +## 0.5.0 + +### Minor Changes + +- 621fac9: We are updating the default size of the Button component in Canon to be small instead of medium. +- a842554: We set the default size for IconButton in Canon to be small instead of medium. +- 35fd51d: Move TextField component to use react Aria under the hood. Introducing a new FieldLabel component to help build custom fields. +- 78204a2: **Breaking** We are adding a new as prop on the Heading and Text component to make it easier to change the component tag. We are removing the render prop in favour of the as prop. +- c49e335: TextField in Canon now has multiple label sizes as well as the capacity to hide label and description but still make them available for screen readers. +- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using instead of just . + +### Patch Changes + +- 44df879: Add min-width: 0; by default on every Flex components in Canon to help support truncated texts inside flex elements. +- ee6ffe6: Fix styling for the title4 prop on the Heading component in Canon. +- f2f814a: Added a render prop to the Button component in Canon to use it as a link. +- 98f02a6: Add new Switch component in Canon. +- c94f8e0: The filter input in menu comboboxes should now always use the full width of the menu it's in. +- 269316d: Remove leftover console.log from Container component. + +## 0.5.0-next.2 + +### Patch Changes + +- 44df879: Add min-width: 0; by default on every Flex components in Canon to help support truncated texts inside flex elements. +- ee6ffe6: Fix styling for the title4 prop on the Heading component in Canon. +- f2f814a: Added a render prop to the Button component in Canon to use it as a link. + +## 0.5.0-next.1 + +### Minor Changes + +- 621fac9: We are updating the default size of the Button component in Canon to be small instead of medium. +- a842554: We set the default size for IconButton in Canon to be small instead of medium. + +## 0.5.0-next.0 + +### Minor Changes + +- 24b45ef: Fixes spacing props on layout components and aligned on naming for the Grid component. You should now call the Grid root component using instead of just . + +### Patch Changes + +- 269316d: Remove leftover console.log from Container component. + ## 0.4.0 ### Minor Changes diff --git a/packages/canon/css/avatar.css b/packages/canon/css/avatar.css deleted file mode 100644 index c1f4cca59e..0000000000 --- a/packages/canon/css/avatar.css +++ /dev/null @@ -1,49 +0,0 @@ -.canon-AvatarRoot { - vertical-align: middle; - user-select: none; - color: var(--canon-fg-primary); - background-color: var(--canon-bg-surface-2); - border-radius: 100%; - justify-content: center; - align-items: center; - width: 2rem; - height: 2rem; - font-size: 1rem; - font-weight: 500; - line-height: 1; - display: inline-flex; - overflow: hidden; -} - -.canon-AvatarRoot[data-size="small"] { - width: 1.5rem; - height: 1.5rem; -} - -.canon-AvatarRoot[data-size="medium"] { - width: 2rem; - height: 2rem; -} - -.canon-AvatarRoot[data-size="large"] { - width: 3rem; - height: 3rem; -} - -.canon-AvatarImage { - object-fit: cover; - width: 100%; - height: 100%; -} - -.canon-AvatarFallback { - width: 100%; - height: 100%; - font-size: var(--canon-font-size-3); - font-weight: var(--canon-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--canon-border); - border-radius: var(--canon-radius-full); - justify-content: center; - align-items: center; - display: flex; -} diff --git a/packages/canon/css/box.css b/packages/canon/css/box.css deleted file mode 100644 index 7a01d5aa3a..0000000000 --- a/packages/canon/css/box.css +++ /dev/null @@ -1,5 +0,0 @@ -.canon-Box { - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); -} diff --git a/packages/canon/css/button.css b/packages/canon/css/button.css deleted file mode 100644 index 7aaad3ec48..0000000000 --- a/packages/canon/css/button.css +++ /dev/null @@ -1,89 +0,0 @@ -.canon-Button { - user-select: none; - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-bold); - cursor: pointer; - border-radius: var(--canon-radius-2); - justify-content: center; - align-items: center; - gap: var(--canon-space-1_5); - border: none; - padding: 0; - display: inline-flex; - - &:disabled { - cursor: not-allowed; - } -} - -.canon-Button[data-variant="primary"] { - background-color: var(--canon-bg-solid); - color: var(--canon-fg-solid); - transition: background-color .15s, box-shadow .15s; - - &:hover { - background-color: var(--canon-bg-solid-hover); - } - - &:active { - background-color: var(--canon-bg-solid-pressed); - } - - &:focus-visible { - outline: 2px solid var(--canon-ring); - outline-offset: 2px; - } - - &:disabled { - background-color: var(--canon-bg-solid-disabled); - color: var(--canon-fg-solid-disabled); - } -} - -.canon-Button[data-variant="secondary"] { - background-color: var(--canon-bg-surface-1); - box-shadow: inset 0 0 0 1px var(--canon-border); - color: var(--canon-fg-primary); - transition: box-shadow .15s; - - &:hover { - box-shadow: inset 0 0 0 1px var(--canon-border-hover); - } - - &:active { - box-shadow: inset 0 0 0 1px var(--canon-border-pressed); - } - - &:focus-visible { - box-shadow: inset 0 0 0 2px var(--canon-ring); - outline: none; - transition: none; - } - - &:disabled { - box-shadow: inset 0 0 0 1px var(--canon-border-disabled); - color: var(--canon-fg-disabled); - } -} - -.canon-Button[data-size="medium"] { - font-size: var(--canon-font-size-4); - padding: 0 var(--canon-space-3); - height: 40px; -} - -.canon-Button[data-size="small"] { - font-size: var(--canon-font-size-3); - padding: 0 var(--canon-space-2); - height: 32px; -} - -.canon-ButtonIcon[data-size="small"], .canon-ButtonIcon[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.canon-ButtonIcon[data-size="medium"], .canon-ButtonIcon[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} diff --git a/packages/canon/css/checkbox.css b/packages/canon/css/checkbox.css deleted file mode 100644 index f8a2cc32d5..0000000000 --- a/packages/canon/css/checkbox.css +++ /dev/null @@ -1,52 +0,0 @@ -.canon-CheckboxRoot { - width: 1rem; - height: 1rem; - box-shadow: inset 0 0 0 1px var(--canon-border); - cursor: pointer; - background-color: var(--canon-bg-surface-1); - border: none; - border-radius: 2px; - flex-shrink: 0; - justify-content: center; - align-items: center; - padding: 0; - transition: background-color .2s ease-in-out; - display: flex; -} - -.canon-CheckboxRoot:focus-visible { - outline: 2px solid var(--canon-ring); - outline-offset: 2px; - transition: none; -} - -.canon-CheckboxRoot[data-checked] { - background-color: var(--canon-bg-solid); - box-shadow: none; - color: var(--canon-fg-solid); -} - -.canon-CheckboxLabel { - align-items: center; - gap: var(--canon-space-2); - font-size: var(--canon-font-size-3); - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - user-select: none; - flex-direction: row; - display: flex; - - &:hover { - & .canon-CheckboxRoot:not([data-checked]) { - box-shadow: inset 0 0 0 1px var(--canon-border-hover); - } - } -} - -.canon-CheckboxIndicator { - color: var(--canon-fg-solid); - justify-content: center; - align-items: center; - display: flex; -} diff --git a/packages/canon/css/collapsible.css b/packages/canon/css/collapsible.css deleted file mode 100644 index e5508f1ecb..0000000000 --- a/packages/canon/css/collapsible.css +++ /dev/null @@ -1,10 +0,0 @@ -.canon-CollapsiblePanel { - height: var(--collapsible-panel-height); - transition: all .15s ease-out; - display: flex; - overflow: hidden; - - &[data-starting-style], &[data-ending-style] { - height: 0; - } -} diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css deleted file mode 100644 index bce8e71a6c..0000000000 --- a/packages/canon/css/components.css +++ /dev/null @@ -1,1302 +0,0 @@ -.canon-AvatarRoot { - vertical-align: middle; - user-select: none; - color: var(--canon-fg-primary); - background-color: var(--canon-bg-surface-2); - border-radius: 100%; - justify-content: center; - align-items: center; - width: 2rem; - height: 2rem; - font-size: 1rem; - font-weight: 500; - line-height: 1; - display: inline-flex; - overflow: hidden; -} - -.canon-AvatarRoot[data-size="small"] { - width: 1.5rem; - height: 1.5rem; -} - -.canon-AvatarRoot[data-size="medium"] { - width: 2rem; - height: 2rem; -} - -.canon-AvatarRoot[data-size="large"] { - width: 3rem; - height: 3rem; -} - -.canon-AvatarImage { - object-fit: cover; - width: 100%; - height: 100%; -} - -.canon-AvatarFallback { - width: 100%; - height: 100%; - font-size: var(--canon-font-size-3); - font-weight: var(--canon-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--canon-border); - border-radius: var(--canon-radius-full); - justify-content: center; - align-items: center; - display: flex; -} - -.canon-Box { - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); -} - -.canon-Button { - user-select: none; - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-bold); - cursor: pointer; - border-radius: var(--canon-radius-2); - justify-content: center; - align-items: center; - gap: var(--canon-space-1_5); - border: none; - padding: 0; - display: inline-flex; - - &:disabled { - cursor: not-allowed; - } -} - -.canon-Button[data-variant="primary"] { - background-color: var(--canon-bg-solid); - color: var(--canon-fg-solid); - transition: background-color .15s, box-shadow .15s; - - &:hover { - background-color: var(--canon-bg-solid-hover); - } - - &:active { - background-color: var(--canon-bg-solid-pressed); - } - - &:focus-visible { - outline: 2px solid var(--canon-ring); - outline-offset: 2px; - } - - &:disabled { - background-color: var(--canon-bg-solid-disabled); - color: var(--canon-fg-solid-disabled); - } -} - -.canon-Button[data-variant="secondary"] { - background-color: var(--canon-bg-surface-1); - box-shadow: inset 0 0 0 1px var(--canon-border); - color: var(--canon-fg-primary); - transition: box-shadow .15s; - - &:hover { - box-shadow: inset 0 0 0 1px var(--canon-border-hover); - } - - &:active { - box-shadow: inset 0 0 0 1px var(--canon-border-pressed); - } - - &:focus-visible { - box-shadow: inset 0 0 0 2px var(--canon-ring); - outline: none; - transition: none; - } - - &:disabled { - box-shadow: inset 0 0 0 1px var(--canon-border-disabled); - color: var(--canon-fg-disabled); - } -} - -.canon-Button[data-size="medium"] { - font-size: var(--canon-font-size-4); - padding: 0 var(--canon-space-3); - height: 40px; -} - -.canon-Button[data-size="small"] { - font-size: var(--canon-font-size-3); - padding: 0 var(--canon-space-2); - height: 32px; -} - -.canon-ButtonIcon[data-size="small"], .canon-ButtonIcon[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.canon-ButtonIcon[data-size="medium"], .canon-ButtonIcon[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} - -.canon-CollapsiblePanel { - height: var(--collapsible-panel-height); - transition: all .15s ease-out; - display: flex; - overflow: hidden; - - &[data-starting-style], &[data-ending-style] { - height: 0; - } -} - -.canon-DataTableRoot { - gap: var(--canon-space-3); - flex-direction: column; - display: flex; -} - -.canon-DataTablePagination { - padding-top: var(--canon-space-5); - justify-content: space-between; - align-items: center; - display: flex; -} - -.canon-DataTablePagination--left { - justify-content: space-between; - align-items: center; - display: flex; -} - -.canon-DataTablePagination--right { - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - display: flex; -} - -.canon-DataTablePagination--select { - min-width: 10.5rem; -} - -.canon-Flex { - display: flex; -} - -.canon-Grid { - display: grid; -} - -.canon-Container { - max-width: 120rem; - padding-inline: var(--canon-space-4); - margin-inline: auto; - transition: padding .2s ease-in-out; -} - -@media (width >= 640px) { - .canon-Container { - padding-inline: var(--canon-space-8); - } -} - -@media (width >= 1024px) { - .canon-Container { - padding-inline: var(--canon-space-12); - } -} - -.canon-Icon { - width: 1rem; - height: 1rem; -} - -.canon-CheckboxRoot { - width: 1rem; - height: 1rem; - box-shadow: inset 0 0 0 1px var(--canon-border); - cursor: pointer; - background-color: var(--canon-bg-surface-1); - border: none; - border-radius: 2px; - flex-shrink: 0; - justify-content: center; - align-items: center; - padding: 0; - transition: background-color .2s ease-in-out; - display: flex; -} - -.canon-CheckboxRoot:focus-visible { - outline: 2px solid var(--canon-ring); - outline-offset: 2px; - transition: none; -} - -.canon-CheckboxRoot[data-checked] { - background-color: var(--canon-bg-solid); - box-shadow: none; - color: var(--canon-fg-solid); -} - -.canon-CheckboxLabel { - align-items: center; - gap: var(--canon-space-2); - font-size: var(--canon-font-size-3); - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - user-select: none; - flex-direction: row; - display: flex; - - &:hover { - & .canon-CheckboxRoot:not([data-checked]) { - box-shadow: inset 0 0 0 1px var(--canon-border-hover); - } - } -} - -.canon-CheckboxIndicator { - color: var(--canon-fg-solid); - justify-content: center; - align-items: center; - display: flex; -} - -.canon-TableRoot { - caption-side: bottom; - border-collapse: collapse; - width: 100%; -} - -.canon-TableHead { - text-align: left; - padding: var(--canon-space-3); - font-size: var(--canon-font-size-3); - color: var(--canon-fg-primary); -} - -.canon-TableBody { - color: var(--canon-fg-primary); -} - -.canon-TableRow { - border-bottom: 1px solid var(--canon-border); - transition: color .2s ease-in-out; -} - -.canon-TableBody .canon-TableRow:hover { - background-color: var(--canon-gray-2); -} - -.canon-TableCell { - padding: var(--canon-space-3); - font-size: var(--canon-font-size-3); -} - -.canon-TableCellText, .canon-TableCellLink { - gap: var(--canon-space-0_5); - flex-direction: column; - display: flex; -} - -.canon-TableCellProfile { - gap: var(--canon-space-2); - flex-direction: row; - align-items: center; - display: flex; -} - -.canon-TableCellProfileAvatar { - vertical-align: middle; - user-select: none; - color: var(--canon-fg-primary); - background-color: var(--canon-bg-surface-2); - border-radius: 100%; - justify-content: center; - align-items: center; - width: 1.25rem; - height: 1.25rem; - font-size: 1rem; - font-weight: 500; - line-height: 1; - display: inline-flex; - overflow: hidden; -} - -.canon-TableCellProfileAvatarImage { - object-fit: cover; - width: 100%; - height: 100%; -} - -.canon-TableCellProfileAvatarFallback { - width: 100%; - height: 100%; - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--canon-border); - border-radius: var(--canon-radius-full); - justify-content: center; - align-items: center; - display: flex; -} - -.canon-TabsRoot { - border: 1px solid var(--color-gray-200); - border-radius: .375rem; -} - -.canon-TabsList { - z-index: 0; - display: flex; - position: relative; -} - -.canon-TabsTab { - appearance: none; - color: var(--canon-fg-secondary); - user-select: none; - padding-inline: var(--canon-space-3); - height: 2rem; - font-family: inherit; - font-size: .875rem; - font-weight: 500; - line-height: 1.25rem; - font-size: var(--canon-font-size-2); - cursor: pointer; - background: none; - border: 0; - outline: 0; - justify-content: center; - align-items: center; - margin: 0; - padding-block: 0; - transition: color .2s ease-in-out; - display: flex; - - &[data-selected] { - color: var(--canon-fg-primary); - } - - @media (hover: hover) { - &:hover { - color: var(--canon-fg-primary); - } - } - - &:focus-visible { - position: relative; - - &:before { - content: ""; - outline: 1px solid var(--canon-ring); - outline-offset: -1px; - border-radius: .25rem; - position: absolute; - inset: .25rem 0; - } - } -} - -.canon-TabsIndicator { - z-index: -1; - translate: var(--active-tab-left) -50%; - width: var(--active-tab-width); - background-color: var(--canon-bg-solid); - height: 1px; - transition-property: translate, width; - transition-duration: .2s; - transition-timing-function: ease-in-out; - position: absolute; - bottom: 0; - left: 0; -} - -.canon-TabsPanel { - &[hidden] { - display: none; - } -} - -.canon-Text { - font-family: var(--canon-font-regular); - margin: 0; - padding: 0; -} - -.canon-Text[data-variant="body"] { - font-size: var(--canon-font-size-3); - line-height: 140%; -} - -.canon-Text[data-variant="subtitle"] { - font-size: var(--canon-font-size-4); - line-height: 140%; -} - -.canon-Text[data-variant="caption"] { - font-size: var(--canon-font-size-2); - line-height: 140%; -} - -.canon-Text[data-variant="label"] { - font-size: var(--canon-font-size-1); - line-height: 140%; -} - -.canon-Text[data-weight="regular"] { - font-weight: var(--canon-font-weight-regular); -} - -.canon-Text[data-weight="bold"] { - font-weight: var(--canon-font-weight-bold); -} - -.canon-Text[data-color="primary"] { - color: var(--canon-fg-primary); -} - -.canon-Text[data-color="secondary"] { - color: var(--canon-fg-secondary); -} - -.canon-Text[data-color="danger"] { - color: var(--canon-fg-danger); -} - -.canon-Text[data-color="warning"] { - color: var(--canon-fg-warning); -} - -.canon-Text[data-color="success"] { - color: var(--canon-fg-success); -} - -.canon-Text[data-truncate] { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.canon-Heading { - font-family: var(--canon-font-regular); - color: var(--canon-fg-primary); - margin: 0; - padding: 0; - line-height: 100%; -} - -.canon-Heading[data-variant="display"] { - font-size: var(--canon-font-size-10); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title1"] { - font-size: var(--canon-font-size-9); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title2"] { - font-size: var(--canon-font-size-8); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title3"] { - font-size: var(--canon-font-size-7); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title4"] { - font-size: var(--canon-font-size-title4); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title5"] { - font-size: var(--canon-font-size-5); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-color="primary"] { - color: var(--canon-fg-primary); -} - -.canon-Heading[data-color="secondary"] { - color: var(--canon-fg-secondary); -} - -.canon-Heading[data-truncate] { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.canon-IconButton { - user-select: none; - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-bold); - cursor: pointer; - border-radius: var(--canon-radius-2); - justify-content: center; - align-items: center; - gap: var(--canon-space-1_5); - border: none; - padding: 0; - display: inline-flex; - - &:disabled { - cursor: not-allowed; - } -} - -.canon-IconButton[data-variant="primary"] { - background-color: var(--canon-bg-solid); - color: var(--canon-fg-solid); - transition: background-color .15s, box-shadow .15s; - - &:hover { - background-color: var(--canon-bg-solid-hover); - } - - &:active { - background-color: var(--canon-bg-solid-pressed); - } - - &:focus-visible { - outline: 2px solid var(--canon-ring); - outline-offset: 2px; - } - - &:disabled { - background-color: var(--canon-bg-solid-disabled); - color: var(--canon-fg-solid-disabled); - } -} - -.canon-IconButton[data-variant="secondary"] { - background-color: var(--canon-bg-surface-1); - box-shadow: inset 0 0 0 1px var(--canon-border); - color: var(--canon-fg-primary); - transition: box-shadow .15s; - - &:hover { - box-shadow: inset 0 0 0 1px var(--canon-border-hover); - } - - &:active { - box-shadow: inset 0 0 0 1px var(--canon-border-pressed); - } - - &:focus-visible { - box-shadow: inset 0 0 0 2px var(--canon-ring); - outline: none; - transition: none; - } - - &:disabled { - box-shadow: inset 0 0 0 1px var(--canon-border-disabled); - color: var(--canon-fg-disabled); - } -} - -.canon-IconButton[data-size="medium"] { - font-size: var(--canon-font-size-4); - width: 40px; - height: 40px; -} - -.canon-IconButton[data-size="small"] { - font-size: var(--canon-font-size-3); - width: 32px; - height: 32px; -} - -.canon-IconButtonIcon[data-size="small"], .canon-IconButtonIcon[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.canon-IconButtonIcon[data-size="medium"], .canon-IconButtonIcon[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} - -.canon-TextField { - font-family: var(--canon-font-regular); - flex-direction: column; - width: 100%; - display: flex; -} - -.canon-TextFieldLabel { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - margin-bottom: var(--canon-space-1_5); - cursor: pointer; - margin-right: auto; -} - -.canon-TextFieldLabel[data-disabled] { - cursor: default; -} - -.canon-TextFieldDescription { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-secondary); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-TextFieldError { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-danger); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-TextFieldInputWrapper { - padding: 0 var(--canon-space-3); - border-radius: var(--canon-radius-3); - border: 1px solid var(--canon-border); - background-color: var(--canon-bg-surface-1); - align-items: center; - display: flex; -} - -.canon-TextFieldIcon { - margin-right: var(--canon-space-1); - color: var(--canon-fg-primary); - flex-shrink: 0; -} - -.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} - -.canon-TextFieldInput { - font-size: var(--canon-font-size-3); - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - width: 100%; - height: 100%; - cursor: inherit; - background: none; - border: none; - padding: 0; - transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; -} - -.canon-TextFieldInput:not([data-filled]):has( + .canon-TextFieldClearButton) { - padding-right: 1.25rem; -} - -.canon-TextFieldInput[type="search"]::-webkit-search-cancel-button, .canon-TextFieldInput[type="search"]::-webkit-search-decoration { - appearance: none; -} - -.canon-TextFieldClearButton { - margin-left: var(--canon-space-1); - vertical-align: middle; - color: var(--canon-fg-primary); - background: none; - border: none; - padding: 0; - display: none; -} - -.canon-TextFieldInput[data-filled] + .canon-TextFieldClearButton { - display: inline-block; -} - -.canon-TextFieldClearButtonIcon { - display: block; -} - -.canon-TextFieldInput::placeholder { - color: var(--canon-fg-secondary); -} - -.canon-TextFieldInput[data-focused] { - outline-color: var(--canon-border-pressed); - outline-width: 0; -} - -.canon-TextFieldInputWrapper:has( > .canon-TextFieldInput:hover) { - border-color: var(--canon-border-hover); -} - -.canon-TextField[data-focused] .canon-TextFieldInputWrapper { - border-color: var(--canon-border-pressed); -} - -.canon-TextField[data-invalid] .canon-TextFieldInputWrapper { - border-color: var(--canon-fg-danger); -} - -.canon-TextField[data-disabled] .canon-TextFieldInputWrapper { - opacity: .5; - cursor: not-allowed; - border: 1px solid var(--canon-border-disabled); -} - -.canon-TextField[data-disabled] .canon-TextFieldClearButton { - cursor: inherit; -} - -.canon-TextFieldInputWrapper[data-size="small"] { - height: 2rem; -} - -.canon-TextFieldInputWrapper[data-size="medium"] { - height: 2.5rem; -} - -.canon-TextFieldRequired { - color: var(--canon-fg-secondary); - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - margin-left: var(--canon-space-1); -} - -.canon-MenuPositioner { - outline: 0; -} - -.canon-MenuPopup { - background-color: var(--canon-bg-surface-1); - border: 1px solid var(--canon-border); - color: var(--canon-fg-primary); - transform-origin: var(--transform-origin); - max-width: min(var(--available-width), 340px); - max-height: min(var(--available-height), 500px); - padding-bottom: var(--canon-space-1); - border-radius: .375rem; - outline: none; - flex-direction: column; - transition: transform .15s, opacity .15s; - display: flex; - position: relative; - overflow: auto; - - &[data-starting-style], &[data-ending-style] { - opacity: 0; - transform: scale(.9); - } -} - -.canon-MenuItem { - user-select: none; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; - display: flex; - - &:first-child { - margin-top: var(--canon-space-1); - } - - &[data-highlighted] { - background-color: var(--canon-gray-3); - } -} - -.canon-MenuSubmenuTrigger { - user-select: none; - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; - display: flex; - - & .canon-Icon { - color: var(--canon-fg-secondary); - } - - &:first-child { - margin-top: var(--canon-space-1); - } - - &[data-popup-open], &[data-highlighted] { - background-color: var(--canon-gray-3); - - & .canon-Icon { - color: var(--canon-fg-primary); - } - } -} - -.canon-MenuSeparator { - background-color: var(--color-gray-200); - height: 1px; - margin: .375rem 1rem; -} - -.canon-SubmenuComboboxSearch { - padding-inline: var(--canon-space-3); - border: none; - border-bottom: 1px solid var(--canon-border); - background-color: var(--canon-bg-surface-1); - height: 32px; - color: var(--canon-fg-primary); - line-height: 140%; - font-size: var(--canon-font-size-3); - z-index: 1; - outline: none; - position: sticky; - top: 0; - - &::placeholder { - color: var(--canon-fg-secondary); - } - - &:disabled { - opacity: .6; - cursor: not-allowed; - } -} - -.canon-SubmenuComboboxItems { - padding-top: var(--canon-space-2); - outline: none; - flex-direction: column; - display: flex; - overflow-y: auto; -} - -.canon-SubmenuComboboxNoResults { - padding-inline: var(--canon-space-3); - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-4); - color: var(--canon-fg-secondary); - font-size: var(--canon-font-size-3); -} - -.canon-SubmenuComboboxItem { - user-select: none; - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; - display: flex; - - &[data-highlighted] { - background-color: var(--canon-gray-3); - } - - &[data-disabled] { - opacity: .5; - cursor: not-allowed; - } -} - -.canon-SubmenuComboboxItemCheckbox { - width: 16px; - height: 16px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - border: 1px solid var(--canon-border); - background: var(--canon-bg-surface-1); - flex-shrink: 0; - justify-content: center; - align-items: center; - display: flex; -} - -.canon-SubmenuComboboxItemLabel { - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - overflow: hidden; -} - -.canon-Link { - font-family: var(--canon-font-regular); - color: var(--canon-fg-link); - cursor: pointer; - margin: 0; - padding: 0; - text-decoration-line: none; - - &:hover { - color: var(--canon-fg-link-hover); - text-underline-offset: calc(.025em + 2px); - text-decoration-line: underline; - text-decoration-style: solid; - text-decoration-thickness: min(2px, max(1px, .05em)); - text-decoration-color: color-mix(in srgb, var(--canon-fg-link-hover) 30%, transparent); - } -} - -.canon-Link[data-variant="body"] { - font-size: var(--canon-font-size-3); - line-height: 140%; -} - -.canon-Link[data-variant="subtitle"] { - font-size: var(--canon-font-size-4); - line-height: 140%; -} - -.canon-Link[data-variant="caption"] { - font-size: var(--canon-font-size-2); - line-height: 140%; -} - -.canon-Link[data-variant="label"] { - font-size: var(--canon-font-size-1); - line-height: 140%; -} - -.canon-Link[data-weight="regular"] { - font-weight: var(--canon-font-weight-regular); -} - -.canon-Link[data-weight="bold"] { - font-weight: var(--canon-font-weight-bold); -} - -.canon-TooltipPopup { - box-sizing: border-box; - transform-origin: var(--transform-origin); - background-color: canvas; - background-color: var(--canon-bg-surface-1); - color: var(--canon-fg-primary); - outline: 1px solid var(--canon-border); - box-shadow: 0 10px 15px -3px var(--canon-border), 0 4px 6px -4px var(--canon-border); - border-radius: .375rem; - flex-direction: column; - padding: .25rem .5rem; - font-size: .875rem; - line-height: 1.25rem; - transition: transform .15s, opacity .15s; - display: flex; - - &[data-starting-style], &[data-ending-style] { - opacity: 0; - transform: scale(.9); - } - - &[data-instant] { - transition-duration: 0s; - } -} - -.canon-TooltipArrow { - display: flex; - - &[data-side="top"] { - bottom: -8px; - rotate: 180deg; - } - - &[data-side="bottom"] { - top: -8px; - rotate: none; - } - - &[data-side="left"] { - right: -13px; - rotate: 90deg; - } - - &[data-side="right"] { - left: -13px; - rotate: -90deg; - } -} - -.canon-TooltipArrow-fill { - fill: var(--canon-bg-surface-1); -} - -.canon-TooltipArrow-outer-stroke { - @media (prefers-color-scheme: light) { - & { - fill: var(--canon-border); - } - } -} - -.canon-ScrollAreaRoot { - box-sizing: border-box; - width: 24rem; - max-width: calc(100vw - 8rem); - height: 8.5rem; -} - -.canon-ScrollAreaViewport { - overscroll-behavior: contain; - height: 100%; -} - -.canon-ScrollAreaContent { - padding-block: .75rem; - flex-direction: column; - gap: 1rem; - padding-left: 1rem; - padding-right: 1.5rem; - display: flex; -} - -.canon-ScrollAreaScrollbar { - background-color: var(--canon-scrollbar); - opacity: 0; - border-radius: .375rem; - justify-content: center; - width: .25rem; - margin: .5rem; - transition: opacity .15s .3s; - display: flex; - - &[data-hovering], &[data-scrolling] { - opacity: 1; - transition-duration: 75ms; - transition-delay: 0s; - } - - &:before { - content: ""; - width: 1.25rem; - height: 100%; - position: absolute; - } -} - -.canon-ScrollAreaThumb { - border-radius: inherit; - background-color: var(--canon-scrollbar-thumb); - width: 100%; -} - -.canon-Select { - font-family: var(--canon-font-regular); - flex-direction: column; - width: 100%; - display: flex; -} - -.canon-SelectLabel { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - margin-bottom: var(--canon-space-1_5); - cursor: pointer; -} - -.canon-SelectLabel[data-disabled] { - cursor: default; -} - -.canon-SelectDescription { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-secondary); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-SelectError { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-danger); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-SelectTrigger { - box-sizing: border-box; - border-radius: var(--canon-radius-3); - border: 1px solid var(--canon-border); - padding: 0 var(--canon-space-4); - background-color: var(--canon-bg-surface-1); - font-size: var(--canon-font-size-3); - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - cursor: pointer; - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - width: 100%; - transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; - display: flex; -} - -.canon-SelectTrigger::placeholder { - color: var(--canon-fg-secondary); -} - -.canon-SelectTrigger:hover { - border-color: var(--canon-border-hover); -} - -.canon-SelectTrigger:focus-visible { - border-color: var(--canon-border-pressed); - outline: 0; -} - -.canon-SelectTrigger[data-invalid] { - border-color: var(--canon-fg-danger); -} - -.canon-SelectTrigger[data-invalid]:hover, .canon-SelectTrigger[data-invalid]:focus-visible { - border-width: 2px; -} - -.canon-SelectTrigger[data-disabled] { - cursor: not-allowed; - border-color: var(--canon-border-disabled); - color: var(--canon-fg-disabled); -} - -.canon-SelectTrigger[data-size="small"] { - height: 2rem; -} - -.canon-SelectTrigger[data-size="medium"] { - height: 3rem; -} - -.canon-SelectIcon { - margin-left: var(--canon-space-5); - transition: transform .2s; -} - -.canon-SelectTrigger[data-popup-open] .canon-SelectIcon { - transform: rotate(180deg); -} - -.canon-SelectPopup { - box-sizing: border-box; - max-height: var(--available-height); - background-color: var(--canon-bg-surface-1); - border: 1px solid var(--canon-border); - border-radius: var(--canon-radius-3); - padding-block: var(--canon-space-1); - z-index: 1; - transform-origin: var(--transform-origin); - outline: 0; - transition: transform .15s, opacity .15s; - overflow-y: auto; - box-shadow: 0 4px 12px #0003; -} - -.canon-SelectPopup[data-starting-style], .canon-SelectPopup[data-ending-style] { - opacity: 0; - transform: scale(.9); -} - -.canon-SelectItem { - width: var(--anchor-width); - padding-block: var(--canon-space-2); - padding-inline: var(--canon-space-4); - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-3); - cursor: pointer; - user-select: none; - font-size: var(--canon-font-size-3); - align-items: center; - gap: var(--canon-space-2); - outline: none; - grid-template-columns: 1rem 1fr; - grid-template-areas: "icon text"; - display: grid; - position: relative; -} - -.canon-SelectItem[data-highlighted] { - z-index: 0; - color: var(--canon-fg-primary); - position: relative; -} - -.canon-SelectItem[data-highlighted]:before { - content: ""; - z-index: -1; - background-color: var(--canon-bg-tint-hover); - border-radius: .25rem; - position: absolute; - inset-block: 0; - inset-inline: .25rem; -} - -.canon-SelectItem[data-disabled] { - cursor: not-allowed; - color: var(--canon-fg-disabled); -} - -.canon-SelectItemIndicator { - grid-area: icon; - justify-content: center; - align-items: center; - display: flex; -} - -.canon-SelectItemText { - flex: 1; - grid-area: text; -} - -.canon-SelectRequired { - color: var(--canon-fg-secondary); - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - margin-left: var(--canon-space-1); -} - -.canon-SelectIcon { - justify-content: center; - align-items: center; - display: flex; -} - -.canon-SelectValue { - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; - overflow: hidden; -} diff --git a/packages/canon/css/container.css b/packages/canon/css/container.css deleted file mode 100644 index 47744cce1e..0000000000 --- a/packages/canon/css/container.css +++ /dev/null @@ -1,18 +0,0 @@ -.canon-Container { - max-width: 120rem; - padding-inline: var(--canon-space-4); - margin-inline: auto; - transition: padding .2s ease-in-out; -} - -@media (width >= 640px) { - .canon-Container { - padding-inline: var(--canon-space-8); - } -} - -@media (width >= 1024px) { - .canon-Container { - padding-inline: var(--canon-space-12); - } -} diff --git a/packages/canon/css/core.css b/packages/canon/css/core.css deleted file mode 100644 index ffdde83d72..0000000000 --- a/packages/canon/css/core.css +++ /dev/null @@ -1,9223 +0,0 @@ -/*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ -@layer base { - *, :before, :after { - box-sizing: border-box; - } - - html { - -webkit-text-size-adjust: 100%; - tab-size: 4; - font-family: system-ui, Segoe UI, Roboto, Helvetica, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji; - line-height: 1.15; - } - - body { - margin: 0; - } - - b, strong { - font-weight: bolder; - } - - code, kbd, samp, pre { - font-family: ui-monospace, SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace; - font-size: 1em; - } - - small { - font-size: 80%; - } - - sub, sup { - vertical-align: baseline; - font-size: 75%; - line-height: 0; - position: relative; - } - - sub { - bottom: -.25em; - } - - sup { - top: -.5em; - } - - table { - border-color: currentColor; - } - - button, input, optgroup, select, textarea { - margin: 0; - font-family: inherit; - font-size: 100%; - line-height: 1.15; - } - - button, [type="button"], [type="reset"], [type="submit"] { - -webkit-appearance: button; - } - - legend { - padding: 0; - } - - progress { - vertical-align: baseline; - } - - ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { - height: auto; - } - - [type="search"] { - -webkit-appearance: textfield; - outline-offset: -2px; - } - - ::-webkit-search-decoration { - -webkit-appearance: none; - } - - ::-webkit-file-upload-button { - -webkit-appearance: button; - font: inherit; - } - - summary { - display: list-item; - } -} - -.cu-p { - padding: var(--p); -} - -.cu-p-0\.5 { - padding: var(--canon-space-0_5); -} - -.cu-p-1 { - padding: var(--canon-space-1); -} - -.cu-p-1\.5 { - padding: var(--canon-space-1_5); -} - -.cu-p-2 { - padding: var(--canon-space-2); -} - -.cu-p-3 { - padding: var(--canon-space-3); -} - -.cu-p-4 { - padding: var(--canon-space-4); -} - -.cu-p-5 { - padding: var(--canon-space-5); -} - -.cu-p-6 { - padding: var(--canon-space-6); -} - -.cu-p-7 { - padding: var(--canon-space-7); -} - -.cu-p-8 { - padding: var(--canon-space-8); -} - -.cu-p-9 { - padding: var(--canon-space-9); -} - -.cu-p-10 { - padding: var(--canon-space-10); -} - -.cu-p-11 { - padding: var(--canon-space-11); -} - -.cu-p-12 { - padding: var(--canon-space-12); -} - -.cu-p-13 { - padding: var(--canon-space-13); -} - -.cu-p-14 { - padding: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-p { - padding: var(--p-xs); - } - - .xs\:cu-p-0\.5 { - padding: var(--canon-space-0_5); - } - - .xs\:cu-p-1 { - padding: var(--canon-space-1); - } - - .xs\:cu-p-1\.5 { - padding: var(--canon-space-1_5); - } - - .xs\:cu-p-2 { - padding: var(--canon-space-2); - } - - .xs\:cu-p-3 { - padding: var(--canon-space-3); - } - - .xs\:cu-p-4 { - padding: var(--canon-space-4); - } - - .xs\:cu-p-5 { - padding: var(--canon-space-5); - } - - .xs\:cu-p-6 { - padding: var(--canon-space-6); - } - - .xs\:cu-p-7 { - padding: var(--canon-space-7); - } - - .xs\:cu-p-8 { - padding: var(--canon-space-8); - } - - .xs\:cu-p-9 { - padding: var(--canon-space-9); - } - - .xs\:cu-p-10 { - padding: var(--canon-space-10); - } - - .xs\:cu-p-11 { - padding: var(--canon-space-11); - } - - .xs\:cu-p-12 { - padding: var(--canon-space-12); - } - - .xs\:cu-p-13 { - padding: var(--canon-space-13); - } - - .xs\:cu-p-14 { - padding: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-p { - padding: var(--p-sm); - } - - .sm\:cu-p-0\.5 { - padding: var(--canon-space-0_5); - } - - .sm\:cu-p-1 { - padding: var(--canon-space-1); - } - - .sm\:cu-p-1\.5 { - padding: var(--canon-space-1_5); - } - - .sm\:cu-p-2 { - padding: var(--canon-space-2); - } - - .sm\:cu-p-3 { - padding: var(--canon-space-3); - } - - .sm\:cu-p-4 { - padding: var(--canon-space-4); - } - - .sm\:cu-p-5 { - padding: var(--canon-space-5); - } - - .sm\:cu-p-6 { - padding: var(--canon-space-6); - } - - .sm\:cu-p-7 { - padding: var(--canon-space-7); - } - - .sm\:cu-p-8 { - padding: var(--canon-space-8); - } - - .sm\:cu-p-9 { - padding: var(--canon-space-9); - } - - .sm\:cu-p-10 { - padding: var(--canon-space-10); - } - - .sm\:cu-p-11 { - padding: var(--canon-space-11); - } - - .sm\:cu-p-12 { - padding: var(--canon-space-12); - } - - .sm\:cu-p-13 { - padding: var(--canon-space-13); - } - - .sm\:cu-p-14 { - padding: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-p { - padding: var(--p-md); - } - - .md\:cu-p-0\.5 { - padding: var(--canon-space-0_5); - } - - .md\:cu-p-1 { - padding: var(--canon-space-1); - } - - .md\:cu-p-1\.5 { - padding: var(--canon-space-1_5); - } - - .md\:cu-p-2 { - padding: var(--canon-space-2); - } - - .md\:cu-p-3 { - padding: var(--canon-space-3); - } - - .md\:cu-p-4 { - padding: var(--canon-space-4); - } - - .md\:cu-p-5 { - padding: var(--canon-space-5); - } - - .md\:cu-p-6 { - padding: var(--canon-space-6); - } - - .md\:cu-p-7 { - padding: var(--canon-space-7); - } - - .md\:cu-p-8 { - padding: var(--canon-space-8); - } - - .md\:cu-p-9 { - padding: var(--canon-space-9); - } - - .md\:cu-p-10 { - padding: var(--canon-space-10); - } - - .md\:cu-p-11 { - padding: var(--canon-space-11); - } - - .md\:cu-p-12 { - padding: var(--canon-space-12); - } - - .md\:cu-p-13 { - padding: var(--canon-space-13); - } - - .md\:cu-p-14 { - padding: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-p { - padding: var(--p-lg); - } - - .lg\:cu-p-0\.5 { - padding: var(--canon-space-0_5); - } - - .lg\:cu-p-1 { - padding: var(--canon-space-1); - } - - .lg\:cu-p-1\.5 { - padding: var(--canon-space-1_5); - } - - .lg\:cu-p-2 { - padding: var(--canon-space-2); - } - - .lg\:cu-p-3 { - padding: var(--canon-space-3); - } - - .lg\:cu-p-4 { - padding: var(--canon-space-4); - } - - .lg\:cu-p-5 { - padding: var(--canon-space-5); - } - - .lg\:cu-p-6 { - padding: var(--canon-space-6); - } - - .lg\:cu-p-7 { - padding: var(--canon-space-7); - } - - .lg\:cu-p-8 { - padding: var(--canon-space-8); - } - - .lg\:cu-p-9 { - padding: var(--canon-space-9); - } - - .lg\:cu-p-10 { - padding: var(--canon-space-10); - } - - .lg\:cu-p-11 { - padding: var(--canon-space-11); - } - - .lg\:cu-p-12 { - padding: var(--canon-space-12); - } - - .lg\:cu-p-13 { - padding: var(--canon-space-13); - } - - .lg\:cu-p-14 { - padding: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-p { - padding: var(--p-xl); - } - - .xl\:cu-p-0\.5 { - padding: var(--canon-space-0_5); - } - - .xl\:cu-p-1 { - padding: var(--canon-space-1); - } - - .xl\:cu-p-1\.5 { - padding: var(--canon-space-1_5); - } - - .xl\:cu-p-2 { - padding: var(--canon-space-2); - } - - .xl\:cu-p-3 { - padding: var(--canon-space-3); - } - - .xl\:cu-p-4 { - padding: var(--canon-space-4); - } - - .xl\:cu-p-5 { - padding: var(--canon-space-5); - } - - .xl\:cu-p-6 { - padding: var(--canon-space-6); - } - - .xl\:cu-p-7 { - padding: var(--canon-space-7); - } - - .xl\:cu-p-8 { - padding: var(--canon-space-8); - } - - .xl\:cu-p-9 { - padding: var(--canon-space-9); - } - - .xl\:cu-p-10 { - padding: var(--canon-space-10); - } - - .xl\:cu-p-11 { - padding: var(--canon-space-11); - } - - .xl\:cu-p-12 { - padding: var(--canon-space-12); - } - - .xl\:cu-p-13 { - padding: var(--canon-space-13); - } - - .xl\:cu-p-14 { - padding: var(--canon-space-14); - } -} - -.cu-pl { - padding-left: var(--pl); -} - -.cu-pl-0\.5 { - padding-left: var(--canon-space-0_5); -} - -.cu-pl-1 { - padding-left: var(--canon-space-1); -} - -.cu-pl-1\.5 { - padding-left: var(--canon-space-1_5); -} - -.cu-pl-2 { - padding-left: var(--canon-space-2); -} - -.cu-pl-3 { - padding-left: var(--canon-space-3); -} - -.cu-pl-4 { - padding-left: var(--canon-space-4); -} - -.cu-pl-5 { - padding-left: var(--canon-space-5); -} - -.cu-pl-6 { - padding-left: var(--canon-space-6); -} - -.cu-pl-7 { - padding-left: var(--canon-space-7); -} - -.cu-pl-8 { - padding-left: var(--canon-space-8); -} - -.cu-pl-9 { - padding-left: var(--canon-space-9); -} - -.cu-pl-10 { - padding-left: var(--canon-space-10); -} - -.cu-pl-11 { - padding-left: var(--canon-space-11); -} - -.cu-pl-12 { - padding-left: var(--canon-space-12); -} - -.cu-pl-13 { - padding-left: var(--canon-space-13); -} - -.cu-pl-14 { - padding-left: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-pl { - padding-left: var(--pl-xs); - } - - .xs\:cu-pl-0\.5 { - padding-left: var(--canon-space-0_5); - } - - .xs\:cu-pl-1 { - padding-left: var(--canon-space-1); - } - - .xs\:cu-pl-1\.5 { - padding-left: var(--canon-space-1_5); - } - - .xs\:cu-pl-2 { - padding-left: var(--canon-space-2); - } - - .xs\:cu-pl-3 { - padding-left: var(--canon-space-3); - } - - .xs\:cu-pl-4 { - padding-left: var(--canon-space-4); - } - - .xs\:cu-pl-5 { - padding-left: var(--canon-space-5); - } - - .xs\:cu-pl-6 { - padding-left: var(--canon-space-6); - } - - .xs\:cu-pl-7 { - padding-left: var(--canon-space-7); - } - - .xs\:cu-pl-8 { - padding-left: var(--canon-space-8); - } - - .xs\:cu-pl-9 { - padding-left: var(--canon-space-9); - } - - .xs\:cu-pl-10 { - padding-left: var(--canon-space-10); - } - - .xs\:cu-pl-11 { - padding-left: var(--canon-space-11); - } - - .xs\:cu-pl-12 { - padding-left: var(--canon-space-12); - } - - .xs\:cu-pl-13 { - padding-left: var(--canon-space-13); - } - - .xs\:cu-pl-14 { - padding-left: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-pl { - padding-left: var(--pl-sm); - } - - .sm\:cu-pl-0\.5 { - padding-left: var(--canon-space-0_5); - } - - .sm\:cu-pl-1 { - padding-left: var(--canon-space-1); - } - - .sm\:cu-pl-1\.5 { - padding-left: var(--canon-space-1_5); - } - - .sm\:cu-pl-2 { - padding-left: var(--canon-space-2); - } - - .sm\:cu-pl-3 { - padding-left: var(--canon-space-3); - } - - .sm\:cu-pl-4 { - padding-left: var(--canon-space-4); - } - - .sm\:cu-pl-5 { - padding-left: var(--canon-space-5); - } - - .sm\:cu-pl-6 { - padding-left: var(--canon-space-6); - } - - .sm\:cu-pl-7 { - padding-left: var(--canon-space-7); - } - - .sm\:cu-pl-8 { - padding-left: var(--canon-space-8); - } - - .sm\:cu-pl-9 { - padding-left: var(--canon-space-9); - } - - .sm\:cu-pl-10 { - padding-left: var(--canon-space-10); - } - - .sm\:cu-pl-11 { - padding-left: var(--canon-space-11); - } - - .sm\:cu-pl-12 { - padding-left: var(--canon-space-12); - } - - .sm\:cu-pl-13 { - padding-left: var(--canon-space-13); - } - - .sm\:cu-pl-14 { - padding-left: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-pl { - padding-left: var(--pl-md); - } - - .md\:cu-pl-0\.5 { - padding-left: var(--canon-space-0_5); - } - - .md\:cu-pl-1 { - padding-left: var(--canon-space-1); - } - - .md\:cu-pl-1\.5 { - padding-left: var(--canon-space-1_5); - } - - .md\:cu-pl-2 { - padding-left: var(--canon-space-2); - } - - .md\:cu-pl-3 { - padding-left: var(--canon-space-3); - } - - .md\:cu-pl-4 { - padding-left: var(--canon-space-4); - } - - .md\:cu-pl-5 { - padding-left: var(--canon-space-5); - } - - .md\:cu-pl-6 { - padding-left: var(--canon-space-6); - } - - .md\:cu-pl-7 { - padding-left: var(--canon-space-7); - } - - .md\:cu-pl-8 { - padding-left: var(--canon-space-8); - } - - .md\:cu-pl-9 { - padding-left: var(--canon-space-9); - } - - .md\:cu-pl-10 { - padding-left: var(--canon-space-10); - } - - .md\:cu-pl-11 { - padding-left: var(--canon-space-11); - } - - .md\:cu-pl-12 { - padding-left: var(--canon-space-12); - } - - .md\:cu-pl-13 { - padding-left: var(--canon-space-13); - } - - .md\:cu-pl-14 { - padding-left: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-pl { - padding-left: var(--pl-lg); - } - - .lg\:cu-pl-0\.5 { - padding-left: var(--canon-space-0_5); - } - - .lg\:cu-pl-1 { - padding-left: var(--canon-space-1); - } - - .lg\:cu-pl-1\.5 { - padding-left: var(--canon-space-1_5); - } - - .lg\:cu-pl-2 { - padding-left: var(--canon-space-2); - } - - .lg\:cu-pl-3 { - padding-left: var(--canon-space-3); - } - - .lg\:cu-pl-4 { - padding-left: var(--canon-space-4); - } - - .lg\:cu-pl-5 { - padding-left: var(--canon-space-5); - } - - .lg\:cu-pl-6 { - padding-left: var(--canon-space-6); - } - - .lg\:cu-pl-7 { - padding-left: var(--canon-space-7); - } - - .lg\:cu-pl-8 { - padding-left: var(--canon-space-8); - } - - .lg\:cu-pl-9 { - padding-left: var(--canon-space-9); - } - - .lg\:cu-pl-10 { - padding-left: var(--canon-space-10); - } - - .lg\:cu-pl-11 { - padding-left: var(--canon-space-11); - } - - .lg\:cu-pl-12 { - padding-left: var(--canon-space-12); - } - - .lg\:cu-pl-13 { - padding-left: var(--canon-space-13); - } - - .lg\:cu-pl-14 { - padding-left: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-pl { - padding-left: var(--pl-xl); - } - - .xl\:cu-pl-0\.5 { - padding-left: var(--canon-space-0_5); - } - - .xl\:cu-pl-1 { - padding-left: var(--canon-space-1); - } - - .xl\:cu-pl-1\.5 { - padding-left: var(--canon-space-1_5); - } - - .xl\:cu-pl-2 { - padding-left: var(--canon-space-2); - } - - .xl\:cu-pl-3 { - padding-left: var(--canon-space-3); - } - - .xl\:cu-pl-4 { - padding-left: var(--canon-space-4); - } - - .xl\:cu-pl-5 { - padding-left: var(--canon-space-5); - } - - .xl\:cu-pl-6 { - padding-left: var(--canon-space-6); - } - - .xl\:cu-pl-7 { - padding-left: var(--canon-space-7); - } - - .xl\:cu-pl-8 { - padding-left: var(--canon-space-8); - } - - .xl\:cu-pl-9 { - padding-left: var(--canon-space-9); - } - - .xl\:cu-pl-10 { - padding-left: var(--canon-space-10); - } - - .xl\:cu-pl-11 { - padding-left: var(--canon-space-11); - } - - .xl\:cu-pl-12 { - padding-left: var(--canon-space-12); - } - - .xl\:cu-pl-13 { - padding-left: var(--canon-space-13); - } - - .xl\:cu-pl-14 { - padding-left: var(--canon-space-14); - } -} - -.cu-pr { - padding-right: var(--pr); -} - -.cu-pr-0\.5 { - padding-right: var(--canon-space-0_5); -} - -.cu-pr-1 { - padding-right: var(--canon-space-1); -} - -.cu-pr-1\.5 { - padding-right: var(--canon-space-1_5); -} - -.cu-pr-2 { - padding-right: var(--canon-space-2); -} - -.cu-pr-3 { - padding-right: var(--canon-space-3); -} - -.cu-pr-4 { - padding-right: var(--canon-space-4); -} - -.cu-pr-5 { - padding-right: var(--canon-space-5); -} - -.cu-pr-6 { - padding-right: var(--canon-space-6); -} - -.cu-pr-7 { - padding-right: var(--canon-space-7); -} - -.cu-pr-8 { - padding-right: var(--canon-space-8); -} - -.cu-pr-9 { - padding-right: var(--canon-space-9); -} - -.cu-pr-10 { - padding-right: var(--canon-space-10); -} - -.cu-pr-11 { - padding-right: var(--canon-space-11); -} - -.cu-pr-12 { - padding-right: var(--canon-space-12); -} - -.cu-pr-13 { - padding-right: var(--canon-space-13); -} - -.cu-pr-14 { - padding-right: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-pr { - padding-right: var(--pr-xs); - } - - .xs\:cu-pr-0\.5 { - padding-right: var(--canon-space-0_5); - } - - .xs\:cu-pr-1 { - padding-right: var(--canon-space-1); - } - - .xs\:cu-pr-1\.5 { - padding-right: var(--canon-space-1_5); - } - - .xs\:cu-pr-2 { - padding-right: var(--canon-space-2); - } - - .xs\:cu-pr-3 { - padding-right: var(--canon-space-3); - } - - .xs\:cu-pr-4 { - padding-right: var(--canon-space-4); - } - - .xs\:cu-pr-5 { - padding-right: var(--canon-space-5); - } - - .xs\:cu-pr-6 { - padding-right: var(--canon-space-6); - } - - .xs\:cu-pr-7 { - padding-right: var(--canon-space-7); - } - - .xs\:cu-pr-8 { - padding-right: var(--canon-space-8); - } - - .xs\:cu-pr-9 { - padding-right: var(--canon-space-9); - } - - .xs\:cu-pr-10 { - padding-right: var(--canon-space-10); - } - - .xs\:cu-pr-11 { - padding-right: var(--canon-space-11); - } - - .xs\:cu-pr-12 { - padding-right: var(--canon-space-12); - } - - .xs\:cu-pr-13 { - padding-right: var(--canon-space-13); - } - - .xs\:cu-pr-14 { - padding-right: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-pr { - padding-right: var(--pr-sm); - } - - .sm\:cu-pr-0\.5 { - padding-right: var(--canon-space-0_5); - } - - .sm\:cu-pr-1 { - padding-right: var(--canon-space-1); - } - - .sm\:cu-pr-1\.5 { - padding-right: var(--canon-space-1_5); - } - - .sm\:cu-pr-2 { - padding-right: var(--canon-space-2); - } - - .sm\:cu-pr-3 { - padding-right: var(--canon-space-3); - } - - .sm\:cu-pr-4 { - padding-right: var(--canon-space-4); - } - - .sm\:cu-pr-5 { - padding-right: var(--canon-space-5); - } - - .sm\:cu-pr-6 { - padding-right: var(--canon-space-6); - } - - .sm\:cu-pr-7 { - padding-right: var(--canon-space-7); - } - - .sm\:cu-pr-8 { - padding-right: var(--canon-space-8); - } - - .sm\:cu-pr-9 { - padding-right: var(--canon-space-9); - } - - .sm\:cu-pr-10 { - padding-right: var(--canon-space-10); - } - - .sm\:cu-pr-11 { - padding-right: var(--canon-space-11); - } - - .sm\:cu-pr-12 { - padding-right: var(--canon-space-12); - } - - .sm\:cu-pr-13 { - padding-right: var(--canon-space-13); - } - - .sm\:cu-pr-14 { - padding-right: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-pr { - padding-right: var(--pr-md); - } - - .md\:cu-pr-0\.5 { - padding-right: var(--canon-space-0_5); - } - - .md\:cu-pr-1 { - padding-right: var(--canon-space-1); - } - - .md\:cu-pr-1\.5 { - padding-right: var(--canon-space-1_5); - } - - .md\:cu-pr-2 { - padding-right: var(--canon-space-2); - } - - .md\:cu-pr-3 { - padding-right: var(--canon-space-3); - } - - .md\:cu-pr-4 { - padding-right: var(--canon-space-4); - } - - .md\:cu-pr-5 { - padding-right: var(--canon-space-5); - } - - .md\:cu-pr-6 { - padding-right: var(--canon-space-6); - } - - .md\:cu-pr-7 { - padding-right: var(--canon-space-7); - } - - .md\:cu-pr-8 { - padding-right: var(--canon-space-8); - } - - .md\:cu-pr-9 { - padding-right: var(--canon-space-9); - } - - .md\:cu-pr-10 { - padding-right: var(--canon-space-10); - } - - .md\:cu-pr-11 { - padding-right: var(--canon-space-11); - } - - .md\:cu-pr-12 { - padding-right: var(--canon-space-12); - } - - .md\:cu-pr-13 { - padding-right: var(--canon-space-13); - } - - .md\:cu-pr-14 { - padding-right: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-pr { - padding-right: var(--pr-lg); - } - - .lg\:cu-pr-0\.5 { - padding-right: var(--canon-space-0_5); - } - - .lg\:cu-pr-1 { - padding-right: var(--canon-space-1); - } - - .lg\:cu-pr-1\.5 { - padding-right: var(--canon-space-1_5); - } - - .lg\:cu-pr-2 { - padding-right: var(--canon-space-2); - } - - .lg\:cu-pr-3 { - padding-right: var(--canon-space-3); - } - - .lg\:cu-pr-4 { - padding-right: var(--canon-space-4); - } - - .lg\:cu-pr-5 { - padding-right: var(--canon-space-5); - } - - .lg\:cu-pr-6 { - padding-right: var(--canon-space-6); - } - - .lg\:cu-pr-7 { - padding-right: var(--canon-space-7); - } - - .lg\:cu-pr-8 { - padding-right: var(--canon-space-8); - } - - .lg\:cu-pr-9 { - padding-right: var(--canon-space-9); - } - - .lg\:cu-pr-10 { - padding-right: var(--canon-space-10); - } - - .lg\:cu-pr-11 { - padding-right: var(--canon-space-11); - } - - .lg\:cu-pr-12 { - padding-right: var(--canon-space-12); - } - - .lg\:cu-pr-13 { - padding-right: var(--canon-space-13); - } - - .lg\:cu-pr-14 { - padding-right: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-pr { - padding-right: var(--pr-xl); - } - - .xl\:cu-pr-0\.5 { - padding-right: var(--canon-space-0_5); - } - - .xl\:cu-pr-1 { - padding-right: var(--canon-space-1); - } - - .xl\:cu-pr-1\.5 { - padding-right: var(--canon-space-1_5); - } - - .xl\:cu-pr-2 { - padding-right: var(--canon-space-2); - } - - .xl\:cu-pr-3 { - padding-right: var(--canon-space-3); - } - - .xl\:cu-pr-4 { - padding-right: var(--canon-space-4); - } - - .xl\:cu-pr-5 { - padding-right: var(--canon-space-5); - } - - .xl\:cu-pr-6 { - padding-right: var(--canon-space-6); - } - - .xl\:cu-pr-7 { - padding-right: var(--canon-space-7); - } - - .xl\:cu-pr-8 { - padding-right: var(--canon-space-8); - } - - .xl\:cu-pr-9 { - padding-right: var(--canon-space-9); - } - - .xl\:cu-pr-10 { - padding-right: var(--canon-space-10); - } - - .xl\:cu-pr-11 { - padding-right: var(--canon-space-11); - } - - .xl\:cu-pr-12 { - padding-right: var(--canon-space-12); - } - - .xl\:cu-pr-13 { - padding-right: var(--canon-space-13); - } - - .xl\:cu-pr-14 { - padding-right: var(--canon-space-14); - } -} - -.cu-pt { - padding-top: var(--pt); -} - -.cu-pt-0\.5 { - padding-top: var(--canon-space-0_5); -} - -.cu-pt-1 { - padding-top: var(--canon-space-1); -} - -.cu-pt-1\.5 { - padding-top: var(--canon-space-1_5); -} - -.cu-pt-2 { - padding-top: var(--canon-space-2); -} - -.cu-pt-3 { - padding-top: var(--canon-space-3); -} - -.cu-pt-4 { - padding-top: var(--canon-space-4); -} - -.cu-pt-5 { - padding-top: var(--canon-space-5); -} - -.cu-pt-6 { - padding-top: var(--canon-space-6); -} - -.cu-pt-7 { - padding-top: var(--canon-space-7); -} - -.cu-pt-8 { - padding-top: var(--canon-space-8); -} - -.cu-pt-9 { - padding-top: var(--canon-space-9); -} - -.cu-pt-10 { - padding-top: var(--canon-space-10); -} - -.cu-pt-11 { - padding-top: var(--canon-space-11); -} - -.cu-pt-12 { - padding-top: var(--canon-space-12); -} - -.cu-pt-13 { - padding-top: var(--canon-space-13); -} - -.cu-pt-14 { - padding-top: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-pt { - padding-top: var(--pt-xs); - } - - .xs\:cu-pt-0\.5 { - padding-top: var(--canon-space-0_5); - } - - .xs\:cu-pt-1 { - padding-top: var(--canon-space-1); - } - - .xs\:cu-pt-1\.5 { - padding-top: var(--canon-space-1_5); - } - - .xs\:cu-pt-2 { - padding-top: var(--canon-space-2); - } - - .xs\:cu-pt-3 { - padding-top: var(--canon-space-3); - } - - .xs\:cu-pt-4 { - padding-top: var(--canon-space-4); - } - - .xs\:cu-pt-5 { - padding-top: var(--canon-space-5); - } - - .xs\:cu-pt-6 { - padding-top: var(--canon-space-6); - } - - .xs\:cu-pt-7 { - padding-top: var(--canon-space-7); - } - - .xs\:cu-pt-8 { - padding-top: var(--canon-space-8); - } - - .xs\:cu-pt-9 { - padding-top: var(--canon-space-9); - } - - .xs\:cu-pt-10 { - padding-top: var(--canon-space-10); - } - - .xs\:cu-pt-11 { - padding-top: var(--canon-space-11); - } - - .xs\:cu-pt-12 { - padding-top: var(--canon-space-12); - } - - .xs\:cu-pt-13 { - padding-top: var(--canon-space-13); - } - - .xs\:cu-pt-14 { - padding-top: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-pt { - padding-top: var(--pt-sm); - } - - .sm\:cu-pt-0\.5 { - padding-top: var(--canon-space-0_5); - } - - .sm\:cu-pt-1 { - padding-top: var(--canon-space-1); - } - - .sm\:cu-pt-1\.5 { - padding-top: var(--canon-space-1_5); - } - - .sm\:cu-pt-2 { - padding-top: var(--canon-space-2); - } - - .sm\:cu-pt-3 { - padding-top: var(--canon-space-3); - } - - .sm\:cu-pt-4 { - padding-top: var(--canon-space-4); - } - - .sm\:cu-pt-5 { - padding-top: var(--canon-space-5); - } - - .sm\:cu-pt-6 { - padding-top: var(--canon-space-6); - } - - .sm\:cu-pt-7 { - padding-top: var(--canon-space-7); - } - - .sm\:cu-pt-8 { - padding-top: var(--canon-space-8); - } - - .sm\:cu-pt-9 { - padding-top: var(--canon-space-9); - } - - .sm\:cu-pt-10 { - padding-top: var(--canon-space-10); - } - - .sm\:cu-pt-11 { - padding-top: var(--canon-space-11); - } - - .sm\:cu-pt-12 { - padding-top: var(--canon-space-12); - } - - .sm\:cu-pt-13 { - padding-top: var(--canon-space-13); - } - - .sm\:cu-pt-14 { - padding-top: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-pt { - padding-top: var(--pt-md); - } - - .md\:cu-pt-0\.5 { - padding-top: var(--canon-space-0_5); - } - - .md\:cu-pt-1 { - padding-top: var(--canon-space-1); - } - - .md\:cu-pt-1\.5 { - padding-top: var(--canon-space-1_5); - } - - .md\:cu-pt-2 { - padding-top: var(--canon-space-2); - } - - .md\:cu-pt-3 { - padding-top: var(--canon-space-3); - } - - .md\:cu-pt-4 { - padding-top: var(--canon-space-4); - } - - .md\:cu-pt-5 { - padding-top: var(--canon-space-5); - } - - .md\:cu-pt-6 { - padding-top: var(--canon-space-6); - } - - .md\:cu-pt-7 { - padding-top: var(--canon-space-7); - } - - .md\:cu-pt-8 { - padding-top: var(--canon-space-8); - } - - .md\:cu-pt-9 { - padding-top: var(--canon-space-9); - } - - .md\:cu-pt-10 { - padding-top: var(--canon-space-10); - } - - .md\:cu-pt-11 { - padding-top: var(--canon-space-11); - } - - .md\:cu-pt-12 { - padding-top: var(--canon-space-12); - } - - .md\:cu-pt-13 { - padding-top: var(--canon-space-13); - } - - .md\:cu-pt-14 { - padding-top: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-pt { - padding-top: var(--pt-lg); - } - - .lg\:cu-pt-0\.5 { - padding-top: var(--canon-space-0_5); - } - - .lg\:cu-pt-1 { - padding-top: var(--canon-space-1); - } - - .lg\:cu-pt-1\.5 { - padding-top: var(--canon-space-1_5); - } - - .lg\:cu-pt-2 { - padding-top: var(--canon-space-2); - } - - .lg\:cu-pt-3 { - padding-top: var(--canon-space-3); - } - - .lg\:cu-pt-4 { - padding-top: var(--canon-space-4); - } - - .lg\:cu-pt-5 { - padding-top: var(--canon-space-5); - } - - .lg\:cu-pt-6 { - padding-top: var(--canon-space-6); - } - - .lg\:cu-pt-7 { - padding-top: var(--canon-space-7); - } - - .lg\:cu-pt-8 { - padding-top: var(--canon-space-8); - } - - .lg\:cu-pt-9 { - padding-top: var(--canon-space-9); - } - - .lg\:cu-pt-10 { - padding-top: var(--canon-space-10); - } - - .lg\:cu-pt-11 { - padding-top: var(--canon-space-11); - } - - .lg\:cu-pt-12 { - padding-top: var(--canon-space-12); - } - - .lg\:cu-pt-13 { - padding-top: var(--canon-space-13); - } - - .lg\:cu-pt-14 { - padding-top: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-pt { - padding-top: var(--pt-xl); - } - - .xl\:cu-pt-0\.5 { - padding-top: var(--canon-space-0_5); - } - - .xl\:cu-pt-1 { - padding-top: var(--canon-space-1); - } - - .xl\:cu-pt-1\.5 { - padding-top: var(--canon-space-1_5); - } - - .xl\:cu-pt-2 { - padding-top: var(--canon-space-2); - } - - .xl\:cu-pt-3 { - padding-top: var(--canon-space-3); - } - - .xl\:cu-pt-4 { - padding-top: var(--canon-space-4); - } - - .xl\:cu-pt-5 { - padding-top: var(--canon-space-5); - } - - .xl\:cu-pt-6 { - padding-top: var(--canon-space-6); - } - - .xl\:cu-pt-7 { - padding-top: var(--canon-space-7); - } - - .xl\:cu-pt-8 { - padding-top: var(--canon-space-8); - } - - .xl\:cu-pt-9 { - padding-top: var(--canon-space-9); - } - - .xl\:cu-pt-10 { - padding-top: var(--canon-space-10); - } - - .xl\:cu-pt-11 { - padding-top: var(--canon-space-11); - } - - .xl\:cu-pt-12 { - padding-top: var(--canon-space-12); - } - - .xl\:cu-pt-13 { - padding-top: var(--canon-space-13); - } - - .xl\:cu-pt-14 { - padding-top: var(--canon-space-14); - } -} - -.cu-pb { - padding-bottom: var(--pb); -} - -.cu-pb-0\.5 { - padding-bottom: var(--canon-space-0_5); -} - -.cu-pb-1 { - padding-bottom: var(--canon-space-1); -} - -.cu-pb-1\.5 { - padding-bottom: var(--canon-space-1_5); -} - -.cu-pb-2 { - padding-bottom: var(--canon-space-2); -} - -.cu-pb-3 { - padding-bottom: var(--canon-space-3); -} - -.cu-pb-4 { - padding-bottom: var(--canon-space-4); -} - -.cu-pb-5 { - padding-bottom: var(--canon-space-5); -} - -.cu-pb-6 { - padding-bottom: var(--canon-space-6); -} - -.cu-pb-7 { - padding-bottom: var(--canon-space-7); -} - -.cu-pb-8 { - padding-bottom: var(--canon-space-8); -} - -.cu-pb-9 { - padding-bottom: var(--canon-space-9); -} - -.cu-pb-10 { - padding-bottom: var(--canon-space-10); -} - -.cu-pb-11 { - padding-bottom: var(--canon-space-11); -} - -.cu-pb-12 { - padding-bottom: var(--canon-space-12); -} - -.cu-pb-13 { - padding-bottom: var(--canon-space-13); -} - -.cu-pb-14 { - padding-bottom: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-pb { - padding-bottom: var(--pb-xs); - } - - .xs\:cu-pb-0\.5 { - padding-bottom: var(--canon-space-0_5); - } - - .xs\:cu-pb-1 { - padding-bottom: var(--canon-space-1); - } - - .xs\:cu-pb-1\.5 { - padding-bottom: var(--canon-space-1_5); - } - - .xs\:cu-pb-2 { - padding-bottom: var(--canon-space-2); - } - - .xs\:cu-pb-3 { - padding-bottom: var(--canon-space-3); - } - - .xs\:cu-pb-4 { - padding-bottom: var(--canon-space-4); - } - - .xs\:cu-pb-5 { - padding-bottom: var(--canon-space-5); - } - - .xs\:cu-pb-6 { - padding-bottom: var(--canon-space-6); - } - - .xs\:cu-pb-7 { - padding-bottom: var(--canon-space-7); - } - - .xs\:cu-pb-8 { - padding-bottom: var(--canon-space-8); - } - - .xs\:cu-pb-9 { - padding-bottom: var(--canon-space-9); - } - - .xs\:cu-pb-10 { - padding-bottom: var(--canon-space-10); - } - - .xs\:cu-pb-11 { - padding-bottom: var(--canon-space-11); - } - - .xs\:cu-pb-12 { - padding-bottom: var(--canon-space-12); - } - - .xs\:cu-pb-13 { - padding-bottom: var(--canon-space-13); - } - - .xs\:cu-pb-14 { - padding-bottom: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-pb { - padding-bottom: var(--pb-sm); - } - - .sm\:cu-pb-0\.5 { - padding-bottom: var(--canon-space-0_5); - } - - .sm\:cu-pb-1 { - padding-bottom: var(--canon-space-1); - } - - .sm\:cu-pb-1\.5 { - padding-bottom: var(--canon-space-1_5); - } - - .sm\:cu-pb-2 { - padding-bottom: var(--canon-space-2); - } - - .sm\:cu-pb-3 { - padding-bottom: var(--canon-space-3); - } - - .sm\:cu-pb-4 { - padding-bottom: var(--canon-space-4); - } - - .sm\:cu-pb-5 { - padding-bottom: var(--canon-space-5); - } - - .sm\:cu-pb-6 { - padding-bottom: var(--canon-space-6); - } - - .sm\:cu-pb-7 { - padding-bottom: var(--canon-space-7); - } - - .sm\:cu-pb-8 { - padding-bottom: var(--canon-space-8); - } - - .sm\:cu-pb-9 { - padding-bottom: var(--canon-space-9); - } - - .sm\:cu-pb-10 { - padding-bottom: var(--canon-space-10); - } - - .sm\:cu-pb-11 { - padding-bottom: var(--canon-space-11); - } - - .sm\:cu-pb-12 { - padding-bottom: var(--canon-space-12); - } - - .sm\:cu-pb-13 { - padding-bottom: var(--canon-space-13); - } - - .sm\:cu-pb-14 { - padding-bottom: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-pb { - padding-bottom: var(--pb-md); - } - - .md\:cu-pb-0\.5 { - padding-bottom: var(--canon-space-0_5); - } - - .md\:cu-pb-1 { - padding-bottom: var(--canon-space-1); - } - - .md\:cu-pb-1\.5 { - padding-bottom: var(--canon-space-1_5); - } - - .md\:cu-pb-2 { - padding-bottom: var(--canon-space-2); - } - - .md\:cu-pb-3 { - padding-bottom: var(--canon-space-3); - } - - .md\:cu-pb-4 { - padding-bottom: var(--canon-space-4); - } - - .md\:cu-pb-5 { - padding-bottom: var(--canon-space-5); - } - - .md\:cu-pb-6 { - padding-bottom: var(--canon-space-6); - } - - .md\:cu-pb-7 { - padding-bottom: var(--canon-space-7); - } - - .md\:cu-pb-8 { - padding-bottom: var(--canon-space-8); - } - - .md\:cu-pb-9 { - padding-bottom: var(--canon-space-9); - } - - .md\:cu-pb-10 { - padding-bottom: var(--canon-space-10); - } - - .md\:cu-pb-11 { - padding-bottom: var(--canon-space-11); - } - - .md\:cu-pb-12 { - padding-bottom: var(--canon-space-12); - } - - .md\:cu-pb-13 { - padding-bottom: var(--canon-space-13); - } - - .md\:cu-pb-14 { - padding-bottom: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-pb { - padding-bottom: var(--pb-lg); - } - - .lg\:cu-pb-0\.5 { - padding-bottom: var(--canon-space-0_5); - } - - .lg\:cu-pb-1 { - padding-bottom: var(--canon-space-1); - } - - .lg\:cu-pb-1\.5 { - padding-bottom: var(--canon-space-1_5); - } - - .lg\:cu-pb-2 { - padding-bottom: var(--canon-space-2); - } - - .lg\:cu-pb-3 { - padding-bottom: var(--canon-space-3); - } - - .lg\:cu-pb-4 { - padding-bottom: var(--canon-space-4); - } - - .lg\:cu-pb-5 { - padding-bottom: var(--canon-space-5); - } - - .lg\:cu-pb-6 { - padding-bottom: var(--canon-space-6); - } - - .lg\:cu-pb-7 { - padding-bottom: var(--canon-space-7); - } - - .lg\:cu-pb-8 { - padding-bottom: var(--canon-space-8); - } - - .lg\:cu-pb-9 { - padding-bottom: var(--canon-space-9); - } - - .lg\:cu-pb-10 { - padding-bottom: var(--canon-space-10); - } - - .lg\:cu-pb-11 { - padding-bottom: var(--canon-space-11); - } - - .lg\:cu-pb-12 { - padding-bottom: var(--canon-space-12); - } - - .lg\:cu-pb-13 { - padding-bottom: var(--canon-space-13); - } - - .lg\:cu-pb-14 { - padding-bottom: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-pb { - padding-bottom: var(--pb-xl); - } - - .xl\:cu-pb-0\.5 { - padding-bottom: var(--canon-space-0_5); - } - - .xl\:cu-pb-1 { - padding-bottom: var(--canon-space-1); - } - - .xl\:cu-pb-1\.5 { - padding-bottom: var(--canon-space-1_5); - } - - .xl\:cu-pb-2 { - padding-bottom: var(--canon-space-2); - } - - .xl\:cu-pb-3 { - padding-bottom: var(--canon-space-3); - } - - .xl\:cu-pb-4 { - padding-bottom: var(--canon-space-4); - } - - .xl\:cu-pb-5 { - padding-bottom: var(--canon-space-5); - } - - .xl\:cu-pb-6 { - padding-bottom: var(--canon-space-6); - } - - .xl\:cu-pb-7 { - padding-bottom: var(--canon-space-7); - } - - .xl\:cu-pb-8 { - padding-bottom: var(--canon-space-8); - } - - .xl\:cu-pb-9 { - padding-bottom: var(--canon-space-9); - } - - .xl\:cu-pb-10 { - padding-bottom: var(--canon-space-10); - } - - .xl\:cu-pb-11 { - padding-bottom: var(--canon-space-11); - } - - .xl\:cu-pb-12 { - padding-bottom: var(--canon-space-12); - } - - .xl\:cu-pb-13 { - padding-bottom: var(--canon-space-13); - } - - .xl\:cu-pb-14 { - padding-bottom: var(--canon-space-14); - } -} - -.cu-py { - padding-top: var(--py); - padding-bottom: var(--py); -} - -.cu-py-0\.5 { - padding-top: var(--canon-space-0_5); - padding-bottom: var(--canon-space-0_5); -} - -.cu-py-1 { - padding-top: var(--canon-space-1); - padding-bottom: var(--canon-space-1); -} - -.cu-py-1\.5 { - padding-top: var(--canon-space-1_5); - padding-bottom: var(--canon-space-1_5); -} - -.cu-py-2 { - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-2); -} - -.cu-py-3 { - padding-top: var(--canon-space-3); - padding-bottom: var(--canon-space-3); -} - -.cu-py-4 { - padding-top: var(--canon-space-4); - padding-bottom: var(--canon-space-4); -} - -.cu-py-5 { - padding-top: var(--canon-space-5); - padding-bottom: var(--canon-space-5); -} - -.cu-py-6 { - padding-top: var(--canon-space-6); - padding-bottom: var(--canon-space-6); -} - -.cu-py-7 { - padding-top: var(--canon-space-7); - padding-bottom: var(--canon-space-7); -} - -.cu-py-8 { - padding-top: var(--canon-space-8); - padding-bottom: var(--canon-space-8); -} - -.cu-py-9 { - padding-top: var(--canon-space-9); - padding-bottom: var(--canon-space-9); -} - -.cu-py-10 { - padding-top: var(--canon-space-10); - padding-bottom: var(--canon-space-10); -} - -.cu-py-11 { - padding-top: var(--canon-space-11); - padding-bottom: var(--canon-space-11); -} - -.cu-py-12 { - padding-top: var(--canon-space-12); - padding-bottom: var(--canon-space-12); -} - -.cu-py-13 { - padding-top: var(--canon-space-13); - padding-bottom: var(--canon-space-13); -} - -.cu-py-14 { - padding-top: var(--canon-space-14); - padding-bottom: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-py { - padding-top: var(--py-xs); - padding-bottom: var(--py-xs); - } - - .xs\:cu-py-0\.5 { - padding-top: var(--canon-space-0_5); - padding-bottom: var(--canon-space-0_5); - } - - .xs\:cu-py-1 { - padding-top: var(--canon-space-1); - padding-bottom: var(--canon-space-1); - } - - .xs\:cu-py-1\.5 { - padding-top: var(--canon-space-1_5); - padding-bottom: var(--canon-space-1_5); - } - - .xs\:cu-py-2 { - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-2); - } - - .xs\:cu-py-3 { - padding-top: var(--canon-space-3); - padding-bottom: var(--canon-space-3); - } - - .xs\:cu-py-4 { - padding-top: var(--canon-space-4); - padding-bottom: var(--canon-space-4); - } - - .xs\:cu-py-5 { - padding-top: var(--canon-space-5); - padding-bottom: var(--canon-space-5); - } - - .xs\:cu-py-6 { - padding-top: var(--canon-space-6); - padding-bottom: var(--canon-space-6); - } - - .xs\:cu-py-7 { - padding-top: var(--canon-space-7); - padding-bottom: var(--canon-space-7); - } - - .xs\:cu-py-8 { - padding-top: var(--canon-space-8); - padding-bottom: var(--canon-space-8); - } - - .xs\:cu-py-9 { - padding-top: var(--canon-space-9); - padding-bottom: var(--canon-space-9); - } - - .xs\:cu-py-10 { - padding-top: var(--canon-space-10); - padding-bottom: var(--canon-space-10); - } - - .xs\:cu-py-11 { - padding-top: var(--canon-space-11); - padding-bottom: var(--canon-space-11); - } - - .xs\:cu-py-12 { - padding-top: var(--canon-space-12); - padding-bottom: var(--canon-space-12); - } - - .xs\:cu-py-13 { - padding-top: var(--canon-space-13); - padding-bottom: var(--canon-space-13); - } - - .xs\:cu-py-14 { - padding-top: var(--canon-space-14); - padding-bottom: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-py { - padding-top: var(--py-sm); - padding-bottom: var(--py-sm); - } - - .sm\:cu-py-0\.5 { - padding-top: var(--canon-space-0_5); - padding-bottom: var(--canon-space-0_5); - } - - .sm\:cu-py-1 { - padding-top: var(--canon-space-1); - padding-bottom: var(--canon-space-1); - } - - .sm\:cu-py-1\.5 { - padding-top: var(--canon-space-1_5); - padding-bottom: var(--canon-space-1_5); - } - - .sm\:cu-py-2 { - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-2); - } - - .sm\:cu-py-3 { - padding-top: var(--canon-space-3); - padding-bottom: var(--canon-space-3); - } - - .sm\:cu-py-4 { - padding-top: var(--canon-space-4); - padding-bottom: var(--canon-space-4); - } - - .sm\:cu-py-5 { - padding-top: var(--canon-space-5); - padding-bottom: var(--canon-space-5); - } - - .sm\:cu-py-6 { - padding-top: var(--canon-space-6); - padding-bottom: var(--canon-space-6); - } - - .sm\:cu-py-7 { - padding-top: var(--canon-space-7); - padding-bottom: var(--canon-space-7); - } - - .sm\:cu-py-8 { - padding-top: var(--canon-space-8); - padding-bottom: var(--canon-space-8); - } - - .sm\:cu-py-9 { - padding-top: var(--canon-space-9); - padding-bottom: var(--canon-space-9); - } - - .sm\:cu-py-10 { - padding-top: var(--canon-space-10); - padding-bottom: var(--canon-space-10); - } - - .sm\:cu-py-11 { - padding-top: var(--canon-space-11); - padding-bottom: var(--canon-space-11); - } - - .sm\:cu-py-12 { - padding-top: var(--canon-space-12); - padding-bottom: var(--canon-space-12); - } - - .sm\:cu-py-13 { - padding-top: var(--canon-space-13); - padding-bottom: var(--canon-space-13); - } - - .sm\:cu-py-14 { - padding-top: var(--canon-space-14); - padding-bottom: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-py { - padding-top: var(--py-md); - padding-bottom: var(--py-md); - } - - .md\:cu-py-0\.5 { - padding-top: var(--canon-space-0_5); - padding-bottom: var(--canon-space-0_5); - } - - .md\:cu-py-1 { - padding-top: var(--canon-space-1); - padding-bottom: var(--canon-space-1); - } - - .md\:cu-py-1\.5 { - padding-top: var(--canon-space-1_5); - padding-bottom: var(--canon-space-1_5); - } - - .md\:cu-py-2 { - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-2); - } - - .md\:cu-py-3 { - padding-top: var(--canon-space-3); - padding-bottom: var(--canon-space-3); - } - - .md\:cu-py-4 { - padding-top: var(--canon-space-4); - padding-bottom: var(--canon-space-4); - } - - .md\:cu-py-5 { - padding-top: var(--canon-space-5); - padding-bottom: var(--canon-space-5); - } - - .md\:cu-py-6 { - padding-top: var(--canon-space-6); - padding-bottom: var(--canon-space-6); - } - - .md\:cu-py-7 { - padding-top: var(--canon-space-7); - padding-bottom: var(--canon-space-7); - } - - .md\:cu-py-8 { - padding-top: var(--canon-space-8); - padding-bottom: var(--canon-space-8); - } - - .md\:cu-py-9 { - padding-top: var(--canon-space-9); - padding-bottom: var(--canon-space-9); - } - - .md\:cu-py-10 { - padding-top: var(--canon-space-10); - padding-bottom: var(--canon-space-10); - } - - .md\:cu-py-11 { - padding-top: var(--canon-space-11); - padding-bottom: var(--canon-space-11); - } - - .md\:cu-py-12 { - padding-top: var(--canon-space-12); - padding-bottom: var(--canon-space-12); - } - - .md\:cu-py-13 { - padding-top: var(--canon-space-13); - padding-bottom: var(--canon-space-13); - } - - .md\:cu-py-14 { - padding-top: var(--canon-space-14); - padding-bottom: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-py { - padding-top: var(--py-lg); - padding-bottom: var(--py-lg); - } - - .lg\:cu-py-0\.5 { - padding-top: var(--canon-space-0_5); - padding-bottom: var(--canon-space-0_5); - } - - .lg\:cu-py-1 { - padding-top: var(--canon-space-1); - padding-bottom: var(--canon-space-1); - } - - .lg\:cu-py-1\.5 { - padding-top: var(--canon-space-1_5); - padding-bottom: var(--canon-space-1_5); - } - - .lg\:cu-py-2 { - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-2); - } - - .lg\:cu-py-3 { - padding-top: var(--canon-space-3); - padding-bottom: var(--canon-space-3); - } - - .lg\:cu-py-4 { - padding-top: var(--canon-space-4); - padding-bottom: var(--canon-space-4); - } - - .lg\:cu-py-5 { - padding-top: var(--canon-space-5); - padding-bottom: var(--canon-space-5); - } - - .lg\:cu-py-6 { - padding-top: var(--canon-space-6); - padding-bottom: var(--canon-space-6); - } - - .lg\:cu-py-7 { - padding-top: var(--canon-space-7); - padding-bottom: var(--canon-space-7); - } - - .lg\:cu-py-8 { - padding-top: var(--canon-space-8); - padding-bottom: var(--canon-space-8); - } - - .lg\:cu-py-9 { - padding-top: var(--canon-space-9); - padding-bottom: var(--canon-space-9); - } - - .lg\:cu-py-10 { - padding-top: var(--canon-space-10); - padding-bottom: var(--canon-space-10); - } - - .lg\:cu-py-11 { - padding-top: var(--canon-space-11); - padding-bottom: var(--canon-space-11); - } - - .lg\:cu-py-12 { - padding-top: var(--canon-space-12); - padding-bottom: var(--canon-space-12); - } - - .lg\:cu-py-13 { - padding-top: var(--canon-space-13); - padding-bottom: var(--canon-space-13); - } - - .lg\:cu-py-14 { - padding-top: var(--canon-space-14); - padding-bottom: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-py { - padding-top: var(--py-xl); - padding-bottom: var(--py-xl); - } - - .xl\:cu-py-0\.5 { - padding-top: var(--canon-space-0_5); - padding-bottom: var(--canon-space-0_5); - } - - .xl\:cu-py-1 { - padding-top: var(--canon-space-1); - padding-bottom: var(--canon-space-1); - } - - .xl\:cu-py-1\.5 { - padding-top: var(--canon-space-1_5); - padding-bottom: var(--canon-space-1_5); - } - - .xl\:cu-py-2 { - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-2); - } - - .xl\:cu-py-3 { - padding-top: var(--canon-space-3); - padding-bottom: var(--canon-space-3); - } - - .xl\:cu-py-4 { - padding-top: var(--canon-space-4); - padding-bottom: var(--canon-space-4); - } - - .xl\:cu-py-5 { - padding-top: var(--canon-space-5); - padding-bottom: var(--canon-space-5); - } - - .xl\:cu-py-6 { - padding-top: var(--canon-space-6); - padding-bottom: var(--canon-space-6); - } - - .xl\:cu-py-7 { - padding-top: var(--canon-space-7); - padding-bottom: var(--canon-space-7); - } - - .xl\:cu-py-8 { - padding-top: var(--canon-space-8); - padding-bottom: var(--canon-space-8); - } - - .xl\:cu-py-9 { - padding-top: var(--canon-space-9); - padding-bottom: var(--canon-space-9); - } - - .xl\:cu-py-10 { - padding-top: var(--canon-space-10); - padding-bottom: var(--canon-space-10); - } - - .xl\:cu-py-11 { - padding-top: var(--canon-space-11); - padding-bottom: var(--canon-space-11); - } - - .xl\:cu-py-12 { - padding-top: var(--canon-space-12); - padding-bottom: var(--canon-space-12); - } - - .xl\:cu-py-13 { - padding-top: var(--canon-space-13); - padding-bottom: var(--canon-space-13); - } - - .xl\:cu-py-14 { - padding-top: var(--canon-space-14); - padding-bottom: var(--canon-space-14); - } -} - -.cu-px { - padding-left: var(--px); - padding-right: var(--px); -} - -.cu-px-0\.5 { - padding-left: var(--canon-space-0_5); - padding-right: var(--canon-space-0_5); -} - -.cu-px-1 { - padding-left: var(--canon-space-1); - padding-right: var(--canon-space-1); -} - -.cu-px-1\.5 { - padding-left: var(--canon-space-1_5); - padding-right: var(--canon-space-1_5); -} - -.cu-px-2 { - padding-left: var(--canon-space-2); - padding-right: var(--canon-space-2); -} - -.cu-px-3 { - padding-left: var(--canon-space-3); - padding-right: var(--canon-space-3); -} - -.cu-px-4 { - padding-left: var(--canon-space-4); - padding-right: var(--canon-space-4); -} - -.cu-px-5 { - padding-left: var(--canon-space-5); - padding-right: var(--canon-space-5); -} - -.cu-px-6 { - padding-left: var(--canon-space-6); - padding-right: var(--canon-space-6); -} - -.cu-px-7 { - padding-left: var(--canon-space-7); - padding-right: var(--canon-space-7); -} - -.cu-px-8 { - padding-left: var(--canon-space-8); - padding-right: var(--canon-space-8); -} - -.cu-px-9 { - padding-left: var(--canon-space-9); - padding-right: var(--canon-space-9); -} - -.cu-px-10 { - padding-left: var(--canon-space-10); - padding-right: var(--canon-space-10); -} - -.cu-px-11 { - padding-left: var(--canon-space-11); - padding-right: var(--canon-space-11); -} - -.cu-px-12 { - padding-left: var(--canon-space-12); - padding-right: var(--canon-space-12); -} - -.cu-px-13 { - padding-left: var(--canon-space-13); - padding-right: var(--canon-space-13); -} - -.cu-px-14 { - padding-left: var(--canon-space-14); - padding-right: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-px { - padding-left: var(--px-xs); - padding-right: var(--px-xs); - } - - .xs\:cu-px-0\.5 { - padding-left: var(--canon-space-0_5); - padding-right: var(--canon-space-0_5); - } - - .xs\:cu-px-1 { - padding-left: var(--canon-space-1); - padding-right: var(--canon-space-1); - } - - .xs\:cu-px-1\.5 { - padding-left: var(--canon-space-1_5); - padding-right: var(--canon-space-1_5); - } - - .xs\:cu-px-2 { - padding-left: var(--canon-space-2); - padding-right: var(--canon-space-2); - } - - .xs\:cu-px-3 { - padding-left: var(--canon-space-3); - padding-right: var(--canon-space-3); - } - - .xs\:cu-px-4 { - padding-left: var(--canon-space-4); - padding-right: var(--canon-space-4); - } - - .xs\:cu-px-5 { - padding-left: var(--canon-space-5); - padding-right: var(--canon-space-5); - } - - .xs\:cu-px-6 { - padding-left: var(--canon-space-6); - padding-right: var(--canon-space-6); - } - - .xs\:cu-px-7 { - padding-left: var(--canon-space-7); - padding-right: var(--canon-space-7); - } - - .xs\:cu-px-8 { - padding-left: var(--canon-space-8); - padding-right: var(--canon-space-8); - } - - .xs\:cu-px-9 { - padding-left: var(--canon-space-9); - padding-right: var(--canon-space-9); - } - - .xs\:cu-px-10 { - padding-left: var(--canon-space-10); - padding-right: var(--canon-space-10); - } - - .xs\:cu-px-11 { - padding-left: var(--canon-space-11); - padding-right: var(--canon-space-11); - } - - .xs\:cu-px-12 { - padding-left: var(--canon-space-12); - padding-right: var(--canon-space-12); - } - - .xs\:cu-px-13 { - padding-left: var(--canon-space-13); - padding-right: var(--canon-space-13); - } - - .xs\:cu-px-14 { - padding-left: var(--canon-space-14); - padding-right: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-px { - padding-left: var(--px-sm); - padding-right: var(--px-sm); - } - - .sm\:cu-px-0\.5 { - padding-left: var(--canon-space-0_5); - padding-right: var(--canon-space-0_5); - } - - .sm\:cu-px-1 { - padding-left: var(--canon-space-1); - padding-right: var(--canon-space-1); - } - - .sm\:cu-px-1\.5 { - padding-left: var(--canon-space-1_5); - padding-right: var(--canon-space-1_5); - } - - .sm\:cu-px-2 { - padding-left: var(--canon-space-2); - padding-right: var(--canon-space-2); - } - - .sm\:cu-px-3 { - padding-left: var(--canon-space-3); - padding-right: var(--canon-space-3); - } - - .sm\:cu-px-4 { - padding-left: var(--canon-space-4); - padding-right: var(--canon-space-4); - } - - .sm\:cu-px-5 { - padding-left: var(--canon-space-5); - padding-right: var(--canon-space-5); - } - - .sm\:cu-px-6 { - padding-left: var(--canon-space-6); - padding-right: var(--canon-space-6); - } - - .sm\:cu-px-7 { - padding-left: var(--canon-space-7); - padding-right: var(--canon-space-7); - } - - .sm\:cu-px-8 { - padding-left: var(--canon-space-8); - padding-right: var(--canon-space-8); - } - - .sm\:cu-px-9 { - padding-left: var(--canon-space-9); - padding-right: var(--canon-space-9); - } - - .sm\:cu-px-10 { - padding-left: var(--canon-space-10); - padding-right: var(--canon-space-10); - } - - .sm\:cu-px-11 { - padding-left: var(--canon-space-11); - padding-right: var(--canon-space-11); - } - - .sm\:cu-px-12 { - padding-left: var(--canon-space-12); - padding-right: var(--canon-space-12); - } - - .sm\:cu-px-13 { - padding-left: var(--canon-space-13); - padding-right: var(--canon-space-13); - } - - .sm\:cu-px-14 { - padding-left: var(--canon-space-14); - padding-right: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-px { - padding-left: var(--px-md); - padding-right: var(--px-md); - } - - .md\:cu-px-0\.5 { - padding-left: var(--canon-space-0_5); - padding-right: var(--canon-space-0_5); - } - - .md\:cu-px-1 { - padding-left: var(--canon-space-1); - padding-right: var(--canon-space-1); - } - - .md\:cu-px-1\.5 { - padding-left: var(--canon-space-1_5); - padding-right: var(--canon-space-1_5); - } - - .md\:cu-px-2 { - padding-left: var(--canon-space-2); - padding-right: var(--canon-space-2); - } - - .md\:cu-px-3 { - padding-left: var(--canon-space-3); - padding-right: var(--canon-space-3); - } - - .md\:cu-px-4 { - padding-left: var(--canon-space-4); - padding-right: var(--canon-space-4); - } - - .md\:cu-px-5 { - padding-left: var(--canon-space-5); - padding-right: var(--canon-space-5); - } - - .md\:cu-px-6 { - padding-left: var(--canon-space-6); - padding-right: var(--canon-space-6); - } - - .md\:cu-px-7 { - padding-left: var(--canon-space-7); - padding-right: var(--canon-space-7); - } - - .md\:cu-px-8 { - padding-left: var(--canon-space-8); - padding-right: var(--canon-space-8); - } - - .md\:cu-px-9 { - padding-left: var(--canon-space-9); - padding-right: var(--canon-space-9); - } - - .md\:cu-px-10 { - padding-left: var(--canon-space-10); - padding-right: var(--canon-space-10); - } - - .md\:cu-px-11 { - padding-left: var(--canon-space-11); - padding-right: var(--canon-space-11); - } - - .md\:cu-px-12 { - padding-left: var(--canon-space-12); - padding-right: var(--canon-space-12); - } - - .md\:cu-px-13 { - padding-left: var(--canon-space-13); - padding-right: var(--canon-space-13); - } - - .md\:cu-px-14 { - padding-left: var(--canon-space-14); - padding-right: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-px { - padding-left: var(--px-lg); - padding-right: var(--px-lg); - } - - .lg\:cu-px-0\.5 { - padding-left: var(--canon-space-0_5); - padding-right: var(--canon-space-0_5); - } - - .lg\:cu-px-1 { - padding-left: var(--canon-space-1); - padding-right: var(--canon-space-1); - } - - .lg\:cu-px-1\.5 { - padding-left: var(--canon-space-1_5); - padding-right: var(--canon-space-1_5); - } - - .lg\:cu-px-2 { - padding-left: var(--canon-space-2); - padding-right: var(--canon-space-2); - } - - .lg\:cu-px-3 { - padding-left: var(--canon-space-3); - padding-right: var(--canon-space-3); - } - - .lg\:cu-px-4 { - padding-left: var(--canon-space-4); - padding-right: var(--canon-space-4); - } - - .lg\:cu-px-5 { - padding-left: var(--canon-space-5); - padding-right: var(--canon-space-5); - } - - .lg\:cu-px-6 { - padding-left: var(--canon-space-6); - padding-right: var(--canon-space-6); - } - - .lg\:cu-px-7 { - padding-left: var(--canon-space-7); - padding-right: var(--canon-space-7); - } - - .lg\:cu-px-8 { - padding-left: var(--canon-space-8); - padding-right: var(--canon-space-8); - } - - .lg\:cu-px-9 { - padding-left: var(--canon-space-9); - padding-right: var(--canon-space-9); - } - - .lg\:cu-px-10 { - padding-left: var(--canon-space-10); - padding-right: var(--canon-space-10); - } - - .lg\:cu-px-11 { - padding-left: var(--canon-space-11); - padding-right: var(--canon-space-11); - } - - .lg\:cu-px-12 { - padding-left: var(--canon-space-12); - padding-right: var(--canon-space-12); - } - - .lg\:cu-px-13 { - padding-left: var(--canon-space-13); - padding-right: var(--canon-space-13); - } - - .lg\:cu-px-14 { - padding-left: var(--canon-space-14); - padding-right: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-px { - padding-left: var(--px-xl); - padding-right: var(--px-xl); - } - - .xl\:cu-px-0\.5 { - padding-left: var(--canon-space-0_5); - padding-right: var(--canon-space-0_5); - } - - .xl\:cu-px-1 { - padding-left: var(--canon-space-1); - padding-right: var(--canon-space-1); - } - - .xl\:cu-px-1\.5 { - padding-left: var(--canon-space-1_5); - padding-right: var(--canon-space-1_5); - } - - .xl\:cu-px-2 { - padding-left: var(--canon-space-2); - padding-right: var(--canon-space-2); - } - - .xl\:cu-px-3 { - padding-left: var(--canon-space-3); - padding-right: var(--canon-space-3); - } - - .xl\:cu-px-4 { - padding-left: var(--canon-space-4); - padding-right: var(--canon-space-4); - } - - .xl\:cu-px-5 { - padding-left: var(--canon-space-5); - padding-right: var(--canon-space-5); - } - - .xl\:cu-px-6 { - padding-left: var(--canon-space-6); - padding-right: var(--canon-space-6); - } - - .xl\:cu-px-7 { - padding-left: var(--canon-space-7); - padding-right: var(--canon-space-7); - } - - .xl\:cu-px-8 { - padding-left: var(--canon-space-8); - padding-right: var(--canon-space-8); - } - - .xl\:cu-px-9 { - padding-left: var(--canon-space-9); - padding-right: var(--canon-space-9); - } - - .xl\:cu-px-10 { - padding-left: var(--canon-space-10); - padding-right: var(--canon-space-10); - } - - .xl\:cu-px-11 { - padding-left: var(--canon-space-11); - padding-right: var(--canon-space-11); - } - - .xl\:cu-px-12 { - padding-left: var(--canon-space-12); - padding-right: var(--canon-space-12); - } - - .xl\:cu-px-13 { - padding-left: var(--canon-space-13); - padding-right: var(--canon-space-13); - } - - .xl\:cu-px-14 { - padding-left: var(--canon-space-14); - padding-right: var(--canon-space-14); - } -} - -.cu-m { - margin: var(--m); -} - -.cu-m-0\.5 { - margin: var(--canon-space-0_5); -} - -.cu-m-1 { - margin: var(--canon-space-1); -} - -.cu-m-1\.5 { - margin: var(--canon-space-1_5); -} - -.cu-m-2 { - margin: var(--canon-space-2); -} - -.cu-m-3 { - margin: var(--canon-space-3); -} - -.cu-m-4 { - margin: var(--canon-space-4); -} - -.cu-m-5 { - margin: var(--canon-space-5); -} - -.cu-m-6 { - margin: var(--canon-space-6); -} - -.cu-m-7 { - margin: var(--canon-space-7); -} - -.cu-m-8 { - margin: var(--canon-space-8); -} - -.cu-m-9 { - margin: var(--canon-space-9); -} - -.cu-m-10 { - margin: var(--canon-space-10); -} - -.cu-m-11 { - margin: var(--canon-space-11); -} - -.cu-m-12 { - margin: var(--canon-space-12); -} - -.cu-m-13 { - margin: var(--canon-space-13); -} - -.cu-m-14 { - margin: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-m { - margin: var(--p-xs); - } - - .xs\:cu-m-0\.5 { - margin: var(--canon-space-0_5); - } - - .xs\:cu-m-1 { - margin: var(--canon-space-1); - } - - .xs\:cu-m-1\.5 { - margin: var(--canon-space-1_5); - } - - .xs\:cu-m-2 { - margin: var(--canon-space-2); - } - - .xs\:cu-m-3 { - margin: var(--canon-space-3); - } - - .xs\:cu-m-4 { - margin: var(--canon-space-4); - } - - .xs\:cu-m-5 { - margin: var(--canon-space-5); - } - - .xs\:cu-m-6 { - margin: var(--canon-space-6); - } - - .xs\:cu-m-7 { - margin: var(--canon-space-7); - } - - .xs\:cu-m-8 { - margin: var(--canon-space-8); - } - - .xs\:cu-m-9 { - margin: var(--canon-space-9); - } - - .xs\:cu-m-10 { - margin: var(--canon-space-10); - } - - .xs\:cu-m-11 { - margin: var(--canon-space-11); - } - - .xs\:cu-m-12 { - margin: var(--canon-space-12); - } - - .xs\:cu-m-13 { - margin: var(--canon-space-13); - } - - .xs\:cu-m-14 { - margin: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-m { - margin: var(--p-sm); - } - - .sm\:cu-m-0\.5 { - margin: var(--canon-space-0_5); - } - - .sm\:cu-m-1 { - margin: var(--canon-space-1); - } - - .sm\:cu-m-1\.5 { - margin: var(--canon-space-1_5); - } - - .sm\:cu-m-2 { - margin: var(--canon-space-2); - } - - .sm\:cu-m-3 { - margin: var(--canon-space-3); - } - - .sm\:cu-m-4 { - margin: var(--canon-space-4); - } - - .sm\:cu-m-5 { - margin: var(--canon-space-5); - } - - .sm\:cu-m-6 { - margin: var(--canon-space-6); - } - - .sm\:cu-m-7 { - margin: var(--canon-space-7); - } - - .sm\:cu-m-8 { - margin: var(--canon-space-8); - } - - .sm\:cu-m-9 { - margin: var(--canon-space-9); - } - - .sm\:cu-m-10 { - margin: var(--canon-space-10); - } - - .sm\:cu-m-11 { - margin: var(--canon-space-11); - } - - .sm\:cu-m-12 { - margin: var(--canon-space-12); - } - - .sm\:cu-m-13 { - margin: var(--canon-space-13); - } - - .sm\:cu-m-14 { - margin: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-m { - margin: var(--p-md); - } - - .md\:cu-m-0\.5 { - margin: var(--canon-space-0_5); - } - - .md\:cu-m-1 { - margin: var(--canon-space-1); - } - - .md\:cu-m-1\.5 { - margin: var(--canon-space-1_5); - } - - .md\:cu-m-2 { - margin: var(--canon-space-2); - } - - .md\:cu-m-3 { - margin: var(--canon-space-3); - } - - .md\:cu-m-4 { - margin: var(--canon-space-4); - } - - .md\:cu-m-5 { - margin: var(--canon-space-5); - } - - .md\:cu-m-6 { - margin: var(--canon-space-6); - } - - .md\:cu-m-7 { - margin: var(--canon-space-7); - } - - .md\:cu-m-8 { - margin: var(--canon-space-8); - } - - .md\:cu-m-9 { - margin: var(--canon-space-9); - } - - .md\:cu-m-10 { - margin: var(--canon-space-10); - } - - .md\:cu-m-11 { - margin: var(--canon-space-11); - } - - .md\:cu-m-12 { - margin: var(--canon-space-12); - } - - .md\:cu-m-13 { - margin: var(--canon-space-13); - } - - .md\:cu-m-14 { - margin: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-m { - margin: var(--p-lg); - } - - .lg\:cu-m-0\.5 { - margin: var(--canon-space-0_5); - } - - .lg\:cu-m-1 { - margin: var(--canon-space-1); - } - - .lg\:cu-m-1\.5 { - margin: var(--canon-space-1_5); - } - - .lg\:cu-m-2 { - margin: var(--canon-space-2); - } - - .lg\:cu-m-3 { - margin: var(--canon-space-3); - } - - .lg\:cu-m-4 { - margin: var(--canon-space-4); - } - - .lg\:cu-m-5 { - margin: var(--canon-space-5); - } - - .lg\:cu-m-6 { - margin: var(--canon-space-6); - } - - .lg\:cu-m-7 { - margin: var(--canon-space-7); - } - - .lg\:cu-m-8 { - margin: var(--canon-space-8); - } - - .lg\:cu-m-9 { - margin: var(--canon-space-9); - } - - .lg\:cu-m-10 { - margin: var(--canon-space-10); - } - - .lg\:cu-m-11 { - margin: var(--canon-space-11); - } - - .lg\:cu-m-12 { - margin: var(--canon-space-12); - } - - .lg\:cu-m-13 { - margin: var(--canon-space-13); - } - - .lg\:cu-m-14 { - margin: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-m { - margin: var(--p-xl); - } - - .xl\:cu-m-0\.5 { - margin: var(--canon-space-0_5); - } - - .xl\:cu-m-1 { - margin: var(--canon-space-1); - } - - .xl\:cu-m-1\.5 { - margin: var(--canon-space-1_5); - } - - .xl\:cu-m-2 { - margin: var(--canon-space-2); - } - - .xl\:cu-m-3 { - margin: var(--canon-space-3); - } - - .xl\:cu-m-4 { - margin: var(--canon-space-4); - } - - .xl\:cu-m-5 { - margin: var(--canon-space-5); - } - - .xl\:cu-m-6 { - margin: var(--canon-space-6); - } - - .xl\:cu-m-7 { - margin: var(--canon-space-7); - } - - .xl\:cu-m-8 { - margin: var(--canon-space-8); - } - - .xl\:cu-m-9 { - margin: var(--canon-space-9); - } - - .xl\:cu-m-10 { - margin: var(--canon-space-10); - } - - .xl\:cu-m-11 { - margin: var(--canon-space-11); - } - - .xl\:cu-m-12 { - margin: var(--canon-space-12); - } - - .xl\:cu-m-13 { - margin: var(--canon-space-13); - } - - .xl\:cu-m-14 { - margin: var(--canon-space-14); - } -} - -.cu-ml { - margin-left: var(--ml); -} - -.cu-ml-0\.5 { - margin-left: var(--canon-space-0_5); -} - -.cu-ml-1 { - margin-left: var(--canon-space-1); -} - -.cu-ml-1\.5 { - margin-left: var(--canon-space-1_5); -} - -.cu-ml-2 { - margin-left: var(--canon-space-2); -} - -.cu-ml-3 { - margin-left: var(--canon-space-3); -} - -.cu-ml-4 { - margin-left: var(--canon-space-4); -} - -.cu-ml-5 { - margin-left: var(--canon-space-5); -} - -.cu-ml-6 { - margin-left: var(--canon-space-6); -} - -.cu-ml-7 { - margin-left: var(--canon-space-7); -} - -.cu-ml-8 { - margin-left: var(--canon-space-8); -} - -.cu-ml-9 { - margin-left: var(--canon-space-9); -} - -.cu-ml-10 { - margin-left: var(--canon-space-10); -} - -.cu-ml-11 { - margin-left: var(--canon-space-11); -} - -.cu-ml-12 { - margin-left: var(--canon-space-12); -} - -.cu-ml-13 { - margin-left: var(--canon-space-13); -} - -.cu-ml-14 { - margin-left: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-ml { - margin-left: var(--pl-xs); - } - - .xs\:cu-ml-0\.5 { - margin-left: var(--canon-space-0_5); - } - - .xs\:cu-ml-1 { - margin-left: var(--canon-space-1); - } - - .xs\:cu-ml-1\.5 { - margin-left: var(--canon-space-1_5); - } - - .xs\:cu-ml-2 { - margin-left: var(--canon-space-2); - } - - .xs\:cu-ml-3 { - margin-left: var(--canon-space-3); - } - - .xs\:cu-ml-4 { - margin-left: var(--canon-space-4); - } - - .xs\:cu-ml-5 { - margin-left: var(--canon-space-5); - } - - .xs\:cu-ml-6 { - margin-left: var(--canon-space-6); - } - - .xs\:cu-ml-7 { - margin-left: var(--canon-space-7); - } - - .xs\:cu-ml-8 { - margin-left: var(--canon-space-8); - } - - .xs\:cu-ml-9 { - margin-left: var(--canon-space-9); - } - - .xs\:cu-ml-10 { - margin-left: var(--canon-space-10); - } - - .xs\:cu-ml-11 { - margin-left: var(--canon-space-11); - } - - .xs\:cu-ml-12 { - margin-left: var(--canon-space-12); - } - - .xs\:cu-ml-13 { - margin-left: var(--canon-space-13); - } - - .xs\:cu-ml-14 { - margin-left: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-ml { - margin-left: var(--pl-sm); - } - - .sm\:cu-ml-0\.5 { - margin-left: var(--canon-space-0_5); - } - - .sm\:cu-ml-1 { - margin-left: var(--canon-space-1); - } - - .sm\:cu-ml-1\.5 { - margin-left: var(--canon-space-1_5); - } - - .sm\:cu-ml-2 { - margin-left: var(--canon-space-2); - } - - .sm\:cu-ml-3 { - margin-left: var(--canon-space-3); - } - - .sm\:cu-ml-4 { - margin-left: var(--canon-space-4); - } - - .sm\:cu-ml-5 { - margin-left: var(--canon-space-5); - } - - .sm\:cu-ml-6 { - margin-left: var(--canon-space-6); - } - - .sm\:cu-ml-7 { - margin-left: var(--canon-space-7); - } - - .sm\:cu-ml-8 { - margin-left: var(--canon-space-8); - } - - .sm\:cu-ml-9 { - margin-left: var(--canon-space-9); - } - - .sm\:cu-ml-10 { - margin-left: var(--canon-space-10); - } - - .sm\:cu-ml-11 { - margin-left: var(--canon-space-11); - } - - .sm\:cu-ml-12 { - margin-left: var(--canon-space-12); - } - - .sm\:cu-ml-13 { - margin-left: var(--canon-space-13); - } - - .sm\:cu-ml-14 { - margin-left: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-ml { - margin-left: var(--pl-md); - } - - .md\:cu-ml-0\.5 { - margin-left: var(--canon-space-0_5); - } - - .md\:cu-ml-1 { - margin-left: var(--canon-space-1); - } - - .md\:cu-ml-1\.5 { - margin-left: var(--canon-space-1_5); - } - - .md\:cu-ml-2 { - margin-left: var(--canon-space-2); - } - - .md\:cu-ml-3 { - margin-left: var(--canon-space-3); - } - - .md\:cu-ml-4 { - margin-left: var(--canon-space-4); - } - - .md\:cu-ml-5 { - margin-left: var(--canon-space-5); - } - - .md\:cu-ml-6 { - margin-left: var(--canon-space-6); - } - - .md\:cu-ml-7 { - margin-left: var(--canon-space-7); - } - - .md\:cu-ml-8 { - margin-left: var(--canon-space-8); - } - - .md\:cu-ml-9 { - margin-left: var(--canon-space-9); - } - - .md\:cu-ml-10 { - margin-left: var(--canon-space-10); - } - - .md\:cu-ml-11 { - margin-left: var(--canon-space-11); - } - - .md\:cu-ml-12 { - margin-left: var(--canon-space-12); - } - - .md\:cu-ml-13 { - margin-left: var(--canon-space-13); - } - - .md\:cu-ml-14 { - margin-left: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-ml { - margin-left: var(--pl-lg); - } - - .lg\:cu-ml-0\.5 { - margin-left: var(--canon-space-0_5); - } - - .lg\:cu-ml-1 { - margin-left: var(--canon-space-1); - } - - .lg\:cu-ml-1\.5 { - margin-left: var(--canon-space-1_5); - } - - .lg\:cu-ml-2 { - margin-left: var(--canon-space-2); - } - - .lg\:cu-ml-3 { - margin-left: var(--canon-space-3); - } - - .lg\:cu-ml-4 { - margin-left: var(--canon-space-4); - } - - .lg\:cu-ml-5 { - margin-left: var(--canon-space-5); - } - - .lg\:cu-ml-6 { - margin-left: var(--canon-space-6); - } - - .lg\:cu-ml-7 { - margin-left: var(--canon-space-7); - } - - .lg\:cu-ml-8 { - margin-left: var(--canon-space-8); - } - - .lg\:cu-ml-9 { - margin-left: var(--canon-space-9); - } - - .lg\:cu-ml-10 { - margin-left: var(--canon-space-10); - } - - .lg\:cu-ml-11 { - margin-left: var(--canon-space-11); - } - - .lg\:cu-ml-12 { - margin-left: var(--canon-space-12); - } - - .lg\:cu-ml-13 { - margin-left: var(--canon-space-13); - } - - .lg\:cu-ml-14 { - margin-left: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-ml { - margin-left: var(--pl-xl); - } - - .xl\:cu-ml-0\.5 { - margin-left: var(--canon-space-0_5); - } - - .xl\:cu-ml-1 { - margin-left: var(--canon-space-1); - } - - .xl\:cu-ml-1\.5 { - margin-left: var(--canon-space-1_5); - } - - .xl\:cu-ml-2 { - margin-left: var(--canon-space-2); - } - - .xl\:cu-ml-3 { - margin-left: var(--canon-space-3); - } - - .xl\:cu-ml-4 { - margin-left: var(--canon-space-4); - } - - .xl\:cu-ml-5 { - margin-left: var(--canon-space-5); - } - - .xl\:cu-ml-6 { - margin-left: var(--canon-space-6); - } - - .xl\:cu-ml-7 { - margin-left: var(--canon-space-7); - } - - .xl\:cu-ml-8 { - margin-left: var(--canon-space-8); - } - - .xl\:cu-ml-9 { - margin-left: var(--canon-space-9); - } - - .xl\:cu-ml-10 { - margin-left: var(--canon-space-10); - } - - .xl\:cu-ml-11 { - margin-left: var(--canon-space-11); - } - - .xl\:cu-ml-12 { - margin-left: var(--canon-space-12); - } - - .xl\:cu-ml-13 { - margin-left: var(--canon-space-13); - } - - .xl\:cu-ml-14 { - margin-left: var(--canon-space-14); - } -} - -.cu-mr { - margin-right: var(--mr); -} - -.cu-mr-0\.5 { - margin-right: var(--canon-space-0_5); -} - -.cu-mr-1 { - margin-right: var(--canon-space-1); -} - -.cu-mr-1\.5 { - margin-right: var(--canon-space-1_5); -} - -.cu-mr-2 { - margin-right: var(--canon-space-2); -} - -.cu-mr-3 { - margin-right: var(--canon-space-3); -} - -.cu-mr-4 { - margin-right: var(--canon-space-4); -} - -.cu-mr-5 { - margin-right: var(--canon-space-5); -} - -.cu-mr-6 { - margin-right: var(--canon-space-6); -} - -.cu-mr-7 { - margin-right: var(--canon-space-7); -} - -.cu-mr-8 { - margin-right: var(--canon-space-8); -} - -.cu-mr-9 { - margin-right: var(--canon-space-9); -} - -.cu-mr-10 { - margin-right: var(--canon-space-10); -} - -.cu-mr-11 { - margin-right: var(--canon-space-11); -} - -.cu-mr-12 { - margin-right: var(--canon-space-12); -} - -.cu-mr-13 { - margin-right: var(--canon-space-13); -} - -.cu-mr-14 { - margin-right: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-mr { - margin-right: var(--pr-xs); - } - - .xs\:cu-mr-0\.5 { - margin-right: var(--canon-space-0_5); - } - - .xs\:cu-mr-1 { - margin-right: var(--canon-space-1); - } - - .xs\:cu-mr-1\.5 { - margin-right: var(--canon-space-1_5); - } - - .xs\:cu-mr-2 { - margin-right: var(--canon-space-2); - } - - .xs\:cu-mr-3 { - margin-right: var(--canon-space-3); - } - - .xs\:cu-mr-4 { - margin-right: var(--canon-space-4); - } - - .xs\:cu-mr-5 { - margin-right: var(--canon-space-5); - } - - .xs\:cu-mr-6 { - margin-right: var(--canon-space-6); - } - - .xs\:cu-mr-7 { - margin-right: var(--canon-space-7); - } - - .xs\:cu-mr-8 { - margin-right: var(--canon-space-8); - } - - .xs\:cu-mr-9 { - margin-right: var(--canon-space-9); - } - - .xs\:cu-mr-10 { - margin-right: var(--canon-space-10); - } - - .xs\:cu-mr-11 { - margin-right: var(--canon-space-11); - } - - .xs\:cu-mr-12 { - margin-right: var(--canon-space-12); - } - - .xs\:cu-mr-13 { - margin-right: var(--canon-space-13); - } - - .xs\:cu-mr-14 { - margin-right: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-mr { - margin-right: var(--pr-sm); - } - - .sm\:cu-mr-0\.5 { - margin-right: var(--canon-space-0_5); - } - - .sm\:cu-mr-1 { - margin-right: var(--canon-space-1); - } - - .sm\:cu-mr-1\.5 { - margin-right: var(--canon-space-1_5); - } - - .sm\:cu-mr-2 { - margin-right: var(--canon-space-2); - } - - .sm\:cu-mr-3 { - margin-right: var(--canon-space-3); - } - - .sm\:cu-mr-4 { - margin-right: var(--canon-space-4); - } - - .sm\:cu-mr-5 { - margin-right: var(--canon-space-5); - } - - .sm\:cu-mr-6 { - margin-right: var(--canon-space-6); - } - - .sm\:cu-mr-7 { - margin-right: var(--canon-space-7); - } - - .sm\:cu-mr-8 { - margin-right: var(--canon-space-8); - } - - .sm\:cu-mr-9 { - margin-right: var(--canon-space-9); - } - - .sm\:cu-mr-10 { - margin-right: var(--canon-space-10); - } - - .sm\:cu-mr-11 { - margin-right: var(--canon-space-11); - } - - .sm\:cu-mr-12 { - margin-right: var(--canon-space-12); - } - - .sm\:cu-mr-13 { - margin-right: var(--canon-space-13); - } - - .sm\:cu-mr-14 { - margin-right: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-mr { - margin-right: var(--pr-md); - } - - .md\:cu-mr-0\.5 { - margin-right: var(--canon-space-0_5); - } - - .md\:cu-mr-1 { - margin-right: var(--canon-space-1); - } - - .md\:cu-mr-1\.5 { - margin-right: var(--canon-space-1_5); - } - - .md\:cu-mr-2 { - margin-right: var(--canon-space-2); - } - - .md\:cu-mr-3 { - margin-right: var(--canon-space-3); - } - - .md\:cu-mr-4 { - margin-right: var(--canon-space-4); - } - - .md\:cu-mr-5 { - margin-right: var(--canon-space-5); - } - - .md\:cu-mr-6 { - margin-right: var(--canon-space-6); - } - - .md\:cu-mr-7 { - margin-right: var(--canon-space-7); - } - - .md\:cu-mr-8 { - margin-right: var(--canon-space-8); - } - - .md\:cu-mr-9 { - margin-right: var(--canon-space-9); - } - - .md\:cu-mr-10 { - margin-right: var(--canon-space-10); - } - - .md\:cu-mr-11 { - margin-right: var(--canon-space-11); - } - - .md\:cu-mr-12 { - margin-right: var(--canon-space-12); - } - - .md\:cu-mr-13 { - margin-right: var(--canon-space-13); - } - - .md\:cu-mr-14 { - margin-right: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-mr { - margin-right: var(--pr-lg); - } - - .lg\:cu-mr-0\.5 { - margin-right: var(--canon-space-0_5); - } - - .lg\:cu-mr-1 { - margin-right: var(--canon-space-1); - } - - .lg\:cu-mr-1\.5 { - margin-right: var(--canon-space-1_5); - } - - .lg\:cu-mr-2 { - margin-right: var(--canon-space-2); - } - - .lg\:cu-mr-3 { - margin-right: var(--canon-space-3); - } - - .lg\:cu-mr-4 { - margin-right: var(--canon-space-4); - } - - .lg\:cu-mr-5 { - margin-right: var(--canon-space-5); - } - - .lg\:cu-mr-6 { - margin-right: var(--canon-space-6); - } - - .lg\:cu-mr-7 { - margin-right: var(--canon-space-7); - } - - .lg\:cu-mr-8 { - margin-right: var(--canon-space-8); - } - - .lg\:cu-mr-9 { - margin-right: var(--canon-space-9); - } - - .lg\:cu-mr-10 { - margin-right: var(--canon-space-10); - } - - .lg\:cu-mr-11 { - margin-right: var(--canon-space-11); - } - - .lg\:cu-mr-12 { - margin-right: var(--canon-space-12); - } - - .lg\:cu-mr-13 { - margin-right: var(--canon-space-13); - } - - .lg\:cu-mr-14 { - margin-right: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-mr { - margin-right: var(--pr-xl); - } - - .xl\:cu-mr-0\.5 { - margin-right: var(--canon-space-0_5); - } - - .xl\:cu-mr-1 { - margin-right: var(--canon-space-1); - } - - .xl\:cu-mr-1\.5 { - margin-right: var(--canon-space-1_5); - } - - .xl\:cu-mr-2 { - margin-right: var(--canon-space-2); - } - - .xl\:cu-mr-3 { - margin-right: var(--canon-space-3); - } - - .xl\:cu-mr-4 { - margin-right: var(--canon-space-4); - } - - .xl\:cu-mr-5 { - margin-right: var(--canon-space-5); - } - - .xl\:cu-mr-6 { - margin-right: var(--canon-space-6); - } - - .xl\:cu-mr-7 { - margin-right: var(--canon-space-7); - } - - .xl\:cu-mr-8 { - margin-right: var(--canon-space-8); - } - - .xl\:cu-mr-9 { - margin-right: var(--canon-space-9); - } - - .xl\:cu-mr-10 { - margin-right: var(--canon-space-10); - } - - .xl\:cu-mr-11 { - margin-right: var(--canon-space-11); - } - - .xl\:cu-mr-12 { - margin-right: var(--canon-space-12); - } - - .xl\:cu-mr-13 { - margin-right: var(--canon-space-13); - } - - .xl\:cu-mr-14 { - margin-right: var(--canon-space-14); - } -} - -.cu-mt { - margin-top: var(--mt); -} - -.cu-mt-0\.5 { - margin-top: var(--canon-space-0_5); -} - -.cu-mt-1 { - margin-top: var(--canon-space-1); -} - -.cu-mt-1\.5 { - margin-top: var(--canon-space-1_5); -} - -.cu-mt-2 { - margin-top: var(--canon-space-2); -} - -.cu-mt-3 { - margin-top: var(--canon-space-3); -} - -.cu-mt-4 { - margin-top: var(--canon-space-4); -} - -.cu-mt-5 { - margin-top: var(--canon-space-5); -} - -.cu-mt-6 { - margin-top: var(--canon-space-6); -} - -.cu-mt-7 { - margin-top: var(--canon-space-7); -} - -.cu-mt-8 { - margin-top: var(--canon-space-8); -} - -.cu-mt-9 { - margin-top: var(--canon-space-9); -} - -.cu-mt-10 { - margin-top: var(--canon-space-10); -} - -.cu-mt-11 { - margin-top: var(--canon-space-11); -} - -.cu-mt-12 { - margin-top: var(--canon-space-12); -} - -.cu-mt-13 { - margin-top: var(--canon-space-13); -} - -.cu-mt-14 { - margin-top: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-mt { - margin-top: var(--pt-xs); - } - - .xs\:cu-mt-0\.5 { - margin-top: var(--canon-space-0_5); - } - - .xs\:cu-mt-1 { - margin-top: var(--canon-space-1); - } - - .xs\:cu-mt-1\.5 { - margin-top: var(--canon-space-1_5); - } - - .xs\:cu-mt-2 { - margin-top: var(--canon-space-2); - } - - .xs\:cu-mt-3 { - margin-top: var(--canon-space-3); - } - - .xs\:cu-mt-4 { - margin-top: var(--canon-space-4); - } - - .xs\:cu-mt-5 { - margin-top: var(--canon-space-5); - } - - .xs\:cu-mt-6 { - margin-top: var(--canon-space-6); - } - - .xs\:cu-mt-7 { - margin-top: var(--canon-space-7); - } - - .xs\:cu-mt-8 { - margin-top: var(--canon-space-8); - } - - .xs\:cu-mt-9 { - margin-top: var(--canon-space-9); - } - - .xs\:cu-mt-10 { - margin-top: var(--canon-space-10); - } - - .xs\:cu-mt-11 { - margin-top: var(--canon-space-11); - } - - .xs\:cu-mt-12 { - margin-top: var(--canon-space-12); - } - - .xs\:cu-mt-13 { - margin-top: var(--canon-space-13); - } - - .xs\:cu-mt-14 { - margin-top: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-mt { - margin-top: var(--pt-sm); - } - - .sm\:cu-mt-0\.5 { - margin-top: var(--canon-space-0_5); - } - - .sm\:cu-mt-1 { - margin-top: var(--canon-space-1); - } - - .sm\:cu-mt-1\.5 { - margin-top: var(--canon-space-1_5); - } - - .sm\:cu-mt-2 { - margin-top: var(--canon-space-2); - } - - .sm\:cu-mt-3 { - margin-top: var(--canon-space-3); - } - - .sm\:cu-mt-4 { - margin-top: var(--canon-space-4); - } - - .sm\:cu-mt-5 { - margin-top: var(--canon-space-5); - } - - .sm\:cu-mt-6 { - margin-top: var(--canon-space-6); - } - - .sm\:cu-mt-7 { - margin-top: var(--canon-space-7); - } - - .sm\:cu-mt-8 { - margin-top: var(--canon-space-8); - } - - .sm\:cu-mt-9 { - margin-top: var(--canon-space-9); - } - - .sm\:cu-mt-10 { - margin-top: var(--canon-space-10); - } - - .sm\:cu-mt-11 { - margin-top: var(--canon-space-11); - } - - .sm\:cu-mt-12 { - margin-top: var(--canon-space-12); - } - - .sm\:cu-mt-13 { - margin-top: var(--canon-space-13); - } - - .sm\:cu-mt-14 { - margin-top: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-mt { - margin-top: var(--pt-md); - } - - .md\:cu-mt-0\.5 { - margin-top: var(--canon-space-0_5); - } - - .md\:cu-mt-1 { - margin-top: var(--canon-space-1); - } - - .md\:cu-mt-1\.5 { - margin-top: var(--canon-space-1_5); - } - - .md\:cu-mt-2 { - margin-top: var(--canon-space-2); - } - - .md\:cu-mt-3 { - margin-top: var(--canon-space-3); - } - - .md\:cu-mt-4 { - margin-top: var(--canon-space-4); - } - - .md\:cu-mt-5 { - margin-top: var(--canon-space-5); - } - - .md\:cu-mt-6 { - margin-top: var(--canon-space-6); - } - - .md\:cu-mt-7 { - margin-top: var(--canon-space-7); - } - - .md\:cu-mt-8 { - margin-top: var(--canon-space-8); - } - - .md\:cu-mt-9 { - margin-top: var(--canon-space-9); - } - - .md\:cu-mt-10 { - margin-top: var(--canon-space-10); - } - - .md\:cu-mt-11 { - margin-top: var(--canon-space-11); - } - - .md\:cu-mt-12 { - margin-top: var(--canon-space-12); - } - - .md\:cu-mt-13 { - margin-top: var(--canon-space-13); - } - - .md\:cu-mt-14 { - margin-top: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-mt { - margin-top: var(--pt-lg); - } - - .lg\:cu-mt-0\.5 { - margin-top: var(--canon-space-0_5); - } - - .lg\:cu-mt-1 { - margin-top: var(--canon-space-1); - } - - .lg\:cu-mt-1\.5 { - margin-top: var(--canon-space-1_5); - } - - .lg\:cu-mt-2 { - margin-top: var(--canon-space-2); - } - - .lg\:cu-mt-3 { - margin-top: var(--canon-space-3); - } - - .lg\:cu-mt-4 { - margin-top: var(--canon-space-4); - } - - .lg\:cu-mt-5 { - margin-top: var(--canon-space-5); - } - - .lg\:cu-mt-6 { - margin-top: var(--canon-space-6); - } - - .lg\:cu-mt-7 { - margin-top: var(--canon-space-7); - } - - .lg\:cu-mt-8 { - margin-top: var(--canon-space-8); - } - - .lg\:cu-mt-9 { - margin-top: var(--canon-space-9); - } - - .lg\:cu-mt-10 { - margin-top: var(--canon-space-10); - } - - .lg\:cu-mt-11 { - margin-top: var(--canon-space-11); - } - - .lg\:cu-mt-12 { - margin-top: var(--canon-space-12); - } - - .lg\:cu-mt-13 { - margin-top: var(--canon-space-13); - } - - .lg\:cu-mt-14 { - margin-top: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-mt { - margin-top: var(--pt-xl); - } - - .xl\:cu-mt-0\.5 { - margin-top: var(--canon-space-0_5); - } - - .xl\:cu-mt-1 { - margin-top: var(--canon-space-1); - } - - .xl\:cu-mt-1\.5 { - margin-top: var(--canon-space-1_5); - } - - .xl\:cu-mt-2 { - margin-top: var(--canon-space-2); - } - - .xl\:cu-mt-3 { - margin-top: var(--canon-space-3); - } - - .xl\:cu-mt-4 { - margin-top: var(--canon-space-4); - } - - .xl\:cu-mt-5 { - margin-top: var(--canon-space-5); - } - - .xl\:cu-mt-6 { - margin-top: var(--canon-space-6); - } - - .xl\:cu-mt-7 { - margin-top: var(--canon-space-7); - } - - .xl\:cu-mt-8 { - margin-top: var(--canon-space-8); - } - - .xl\:cu-mt-9 { - margin-top: var(--canon-space-9); - } - - .xl\:cu-mt-10 { - margin-top: var(--canon-space-10); - } - - .xl\:cu-mt-11 { - margin-top: var(--canon-space-11); - } - - .xl\:cu-mt-12 { - margin-top: var(--canon-space-12); - } - - .xl\:cu-mt-13 { - margin-top: var(--canon-space-13); - } - - .xl\:cu-mt-14 { - margin-top: var(--canon-space-14); - } -} - -.cu-mb { - margin-bottom: var(--mb); -} - -.cu-mb-0\.5 { - margin-bottom: var(--canon-space-0_5); -} - -.cu-mb-1 { - margin-bottom: var(--canon-space-1); -} - -.cu-mb-1\.5 { - margin-bottom: var(--canon-space-1_5); -} - -.cu-mb-2 { - margin-bottom: var(--canon-space-2); -} - -.cu-mb-3 { - margin-bottom: var(--canon-space-3); -} - -.cu-mb-4 { - margin-bottom: var(--canon-space-4); -} - -.cu-mb-5 { - margin-bottom: var(--canon-space-5); -} - -.cu-mb-6 { - margin-bottom: var(--canon-space-6); -} - -.cu-mb-7 { - margin-bottom: var(--canon-space-7); -} - -.cu-mb-8 { - margin-bottom: var(--canon-space-8); -} - -.cu-mb-9 { - margin-bottom: var(--canon-space-9); -} - -.cu-mb-10 { - margin-bottom: var(--canon-space-10); -} - -.cu-mb-11 { - margin-bottom: var(--canon-space-11); -} - -.cu-mb-12 { - margin-bottom: var(--canon-space-12); -} - -.cu-mb-13 { - margin-bottom: var(--canon-space-13); -} - -.cu-mb-14 { - margin-bottom: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-mb { - margin-bottom: var(--pb-xs); - } - - .xs\:cu-mb-0\.5 { - margin-bottom: var(--canon-space-0_5); - } - - .xs\:cu-mb-1 { - margin-bottom: var(--canon-space-1); - } - - .xs\:cu-mb-1\.5 { - margin-bottom: var(--canon-space-1_5); - } - - .xs\:cu-mb-2 { - margin-bottom: var(--canon-space-2); - } - - .xs\:cu-mb-3 { - margin-bottom: var(--canon-space-3); - } - - .xs\:cu-mb-4 { - margin-bottom: var(--canon-space-4); - } - - .xs\:cu-mb-5 { - margin-bottom: var(--canon-space-5); - } - - .xs\:cu-mb-6 { - margin-bottom: var(--canon-space-6); - } - - .xs\:cu-mb-7 { - margin-bottom: var(--canon-space-7); - } - - .xs\:cu-mb-8 { - margin-bottom: var(--canon-space-8); - } - - .xs\:cu-mb-9 { - margin-bottom: var(--canon-space-9); - } - - .xs\:cu-mb-10 { - margin-bottom: var(--canon-space-10); - } - - .xs\:cu-mb-11 { - margin-bottom: var(--canon-space-11); - } - - .xs\:cu-mb-12 { - margin-bottom: var(--canon-space-12); - } - - .xs\:cu-mb-13 { - margin-bottom: var(--canon-space-13); - } - - .xs\:cu-mb-14 { - margin-bottom: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-mb { - margin-bottom: var(--pb-sm); - } - - .sm\:cu-mb-0\.5 { - margin-bottom: var(--canon-space-0_5); - } - - .sm\:cu-mb-1 { - margin-bottom: var(--canon-space-1); - } - - .sm\:cu-mb-1\.5 { - margin-bottom: var(--canon-space-1_5); - } - - .sm\:cu-mb-2 { - margin-bottom: var(--canon-space-2); - } - - .sm\:cu-mb-3 { - margin-bottom: var(--canon-space-3); - } - - .sm\:cu-mb-4 { - margin-bottom: var(--canon-space-4); - } - - .sm\:cu-mb-5 { - margin-bottom: var(--canon-space-5); - } - - .sm\:cu-mb-6 { - margin-bottom: var(--canon-space-6); - } - - .sm\:cu-mb-7 { - margin-bottom: var(--canon-space-7); - } - - .sm\:cu-mb-8 { - margin-bottom: var(--canon-space-8); - } - - .sm\:cu-mb-9 { - margin-bottom: var(--canon-space-9); - } - - .sm\:cu-mb-10 { - margin-bottom: var(--canon-space-10); - } - - .sm\:cu-mb-11 { - margin-bottom: var(--canon-space-11); - } - - .sm\:cu-mb-12 { - margin-bottom: var(--canon-space-12); - } - - .sm\:cu-mb-13 { - margin-bottom: var(--canon-space-13); - } - - .sm\:cu-mb-14 { - margin-bottom: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-mb { - margin-bottom: var(--pb-md); - } - - .md\:cu-mb-0\.5 { - margin-bottom: var(--canon-space-0_5); - } - - .md\:cu-mb-1 { - margin-bottom: var(--canon-space-1); - } - - .md\:cu-mb-1\.5 { - margin-bottom: var(--canon-space-1_5); - } - - .md\:cu-mb-2 { - margin-bottom: var(--canon-space-2); - } - - .md\:cu-mb-3 { - margin-bottom: var(--canon-space-3); - } - - .md\:cu-mb-4 { - margin-bottom: var(--canon-space-4); - } - - .md\:cu-mb-5 { - margin-bottom: var(--canon-space-5); - } - - .md\:cu-mb-6 { - margin-bottom: var(--canon-space-6); - } - - .md\:cu-mb-7 { - margin-bottom: var(--canon-space-7); - } - - .md\:cu-mb-8 { - margin-bottom: var(--canon-space-8); - } - - .md\:cu-mb-9 { - margin-bottom: var(--canon-space-9); - } - - .md\:cu-mb-10 { - margin-bottom: var(--canon-space-10); - } - - .md\:cu-mb-11 { - margin-bottom: var(--canon-space-11); - } - - .md\:cu-mb-12 { - margin-bottom: var(--canon-space-12); - } - - .md\:cu-mb-13 { - margin-bottom: var(--canon-space-13); - } - - .md\:cu-mb-14 { - margin-bottom: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-mb { - margin-bottom: var(--pb-lg); - } - - .lg\:cu-mb-0\.5 { - margin-bottom: var(--canon-space-0_5); - } - - .lg\:cu-mb-1 { - margin-bottom: var(--canon-space-1); - } - - .lg\:cu-mb-1\.5 { - margin-bottom: var(--canon-space-1_5); - } - - .lg\:cu-mb-2 { - margin-bottom: var(--canon-space-2); - } - - .lg\:cu-mb-3 { - margin-bottom: var(--canon-space-3); - } - - .lg\:cu-mb-4 { - margin-bottom: var(--canon-space-4); - } - - .lg\:cu-mb-5 { - margin-bottom: var(--canon-space-5); - } - - .lg\:cu-mb-6 { - margin-bottom: var(--canon-space-6); - } - - .lg\:cu-mb-7 { - margin-bottom: var(--canon-space-7); - } - - .lg\:cu-mb-8 { - margin-bottom: var(--canon-space-8); - } - - .lg\:cu-mb-9 { - margin-bottom: var(--canon-space-9); - } - - .lg\:cu-mb-10 { - margin-bottom: var(--canon-space-10); - } - - .lg\:cu-mb-11 { - margin-bottom: var(--canon-space-11); - } - - .lg\:cu-mb-12 { - margin-bottom: var(--canon-space-12); - } - - .lg\:cu-mb-13 { - margin-bottom: var(--canon-space-13); - } - - .lg\:cu-mb-14 { - margin-bottom: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-mb { - margin-bottom: var(--pb-xl); - } - - .xl\:cu-mb-0\.5 { - margin-bottom: var(--canon-space-0_5); - } - - .xl\:cu-mb-1 { - margin-bottom: var(--canon-space-1); - } - - .xl\:cu-mb-1\.5 { - margin-bottom: var(--canon-space-1_5); - } - - .xl\:cu-mb-2 { - margin-bottom: var(--canon-space-2); - } - - .xl\:cu-mb-3 { - margin-bottom: var(--canon-space-3); - } - - .xl\:cu-mb-4 { - margin-bottom: var(--canon-space-4); - } - - .xl\:cu-mb-5 { - margin-bottom: var(--canon-space-5); - } - - .xl\:cu-mb-6 { - margin-bottom: var(--canon-space-6); - } - - .xl\:cu-mb-7 { - margin-bottom: var(--canon-space-7); - } - - .xl\:cu-mb-8 { - margin-bottom: var(--canon-space-8); - } - - .xl\:cu-mb-9 { - margin-bottom: var(--canon-space-9); - } - - .xl\:cu-mb-10 { - margin-bottom: var(--canon-space-10); - } - - .xl\:cu-mb-11 { - margin-bottom: var(--canon-space-11); - } - - .xl\:cu-mb-12 { - margin-bottom: var(--canon-space-12); - } - - .xl\:cu-mb-13 { - margin-bottom: var(--canon-space-13); - } - - .xl\:cu-mb-14 { - margin-bottom: var(--canon-space-14); - } -} - -.cu-my { - margin-top: var(--my); - margin-bottom: var(--my); -} - -.cu-my-0\.5 { - margin-top: var(--canon-space-0_5); - margin-bottom: var(--canon-space-0_5); -} - -.cu-my-1 { - margin-top: var(--canon-space-1); - margin-bottom: var(--canon-space-1); -} - -.cu-my-1\.5 { - margin-top: var(--canon-space-1_5); - margin-bottom: var(--canon-space-1_5); -} - -.cu-my-2 { - margin-top: var(--canon-space-2); - margin-bottom: var(--canon-space-2); -} - -.cu-my-3 { - margin-top: var(--canon-space-3); - margin-bottom: var(--canon-space-3); -} - -.cu-my-4 { - margin-top: var(--canon-space-4); - margin-bottom: var(--canon-space-4); -} - -.cu-my-5 { - margin-top: var(--canon-space-5); - margin-bottom: var(--canon-space-5); -} - -.cu-my-6 { - margin-top: var(--canon-space-6); - margin-bottom: var(--canon-space-6); -} - -.cu-my-7 { - margin-top: var(--canon-space-7); - margin-bottom: var(--canon-space-7); -} - -.cu-my-8 { - margin-top: var(--canon-space-8); - margin-bottom: var(--canon-space-8); -} - -.cu-my-9 { - margin-top: var(--canon-space-9); - margin-bottom: var(--canon-space-9); -} - -.cu-my-10 { - margin-top: var(--canon-space-10); - margin-bottom: var(--canon-space-10); -} - -.cu-my-11 { - margin-top: var(--canon-space-11); - margin-bottom: var(--canon-space-11); -} - -.cu-my-12 { - margin-top: var(--canon-space-12); - margin-bottom: var(--canon-space-12); -} - -.cu-my-13 { - margin-top: var(--canon-space-13); - margin-bottom: var(--canon-space-13); -} - -.cu-my-14 { - margin-top: var(--canon-space-14); - margin-bottom: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-my { - margin-top: var(--py-xs); - margin-bottom: var(--py-xs); - } - - .xs\:cu-my-0\.5 { - margin-top: var(--canon-space-0_5); - margin-bottom: var(--canon-space-0_5); - } - - .xs\:cu-my-1 { - margin-top: var(--canon-space-1); - margin-bottom: var(--canon-space-1); - } - - .xs\:cu-my-1\.5 { - margin-top: var(--canon-space-1_5); - margin-bottom: var(--canon-space-1_5); - } - - .xs\:cu-my-2 { - margin-top: var(--canon-space-2); - margin-bottom: var(--canon-space-2); - } - - .xs\:cu-my-3 { - margin-top: var(--canon-space-3); - margin-bottom: var(--canon-space-3); - } - - .xs\:cu-my-4 { - margin-top: var(--canon-space-4); - margin-bottom: var(--canon-space-4); - } - - .xs\:cu-my-5 { - margin-top: var(--canon-space-5); - margin-bottom: var(--canon-space-5); - } - - .xs\:cu-my-6 { - margin-top: var(--canon-space-6); - margin-bottom: var(--canon-space-6); - } - - .xs\:cu-my-7 { - margin-top: var(--canon-space-7); - margin-bottom: var(--canon-space-7); - } - - .xs\:cu-my-8 { - margin-top: var(--canon-space-8); - margin-bottom: var(--canon-space-8); - } - - .xs\:cu-my-9 { - margin-top: var(--canon-space-9); - margin-bottom: var(--canon-space-9); - } - - .xs\:cu-my-10 { - margin-top: var(--canon-space-10); - margin-bottom: var(--canon-space-10); - } - - .xs\:cu-my-11 { - margin-top: var(--canon-space-11); - margin-bottom: var(--canon-space-11); - } - - .xs\:cu-my-12 { - margin-top: var(--canon-space-12); - margin-bottom: var(--canon-space-12); - } - - .xs\:cu-my-13 { - margin-top: var(--canon-space-13); - margin-bottom: var(--canon-space-13); - } - - .xs\:cu-my-14 { - margin-top: var(--canon-space-14); - margin-bottom: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-my { - margin-top: var(--py-sm); - margin-bottom: var(--py-sm); - } - - .sm\:cu-my-0\.5 { - margin-top: var(--canon-space-0_5); - margin-bottom: var(--canon-space-0_5); - } - - .sm\:cu-my-1 { - margin-top: var(--canon-space-1); - margin-bottom: var(--canon-space-1); - } - - .sm\:cu-my-1\.5 { - margin-top: var(--canon-space-1_5); - margin-bottom: var(--canon-space-1_5); - } - - .sm\:cu-my-2 { - margin-top: var(--canon-space-2); - margin-bottom: var(--canon-space-2); - } - - .sm\:cu-my-3 { - margin-top: var(--canon-space-3); - margin-bottom: var(--canon-space-3); - } - - .sm\:cu-my-4 { - margin-top: var(--canon-space-4); - margin-bottom: var(--canon-space-4); - } - - .sm\:cu-my-5 { - margin-top: var(--canon-space-5); - margin-bottom: var(--canon-space-5); - } - - .sm\:cu-my-6 { - margin-top: var(--canon-space-6); - margin-bottom: var(--canon-space-6); - } - - .sm\:cu-my-7 { - margin-top: var(--canon-space-7); - margin-bottom: var(--canon-space-7); - } - - .sm\:cu-my-8 { - margin-top: var(--canon-space-8); - margin-bottom: var(--canon-space-8); - } - - .sm\:cu-my-9 { - margin-top: var(--canon-space-9); - margin-bottom: var(--canon-space-9); - } - - .sm\:cu-my-10 { - margin-top: var(--canon-space-10); - margin-bottom: var(--canon-space-10); - } - - .sm\:cu-my-11 { - margin-top: var(--canon-space-11); - margin-bottom: var(--canon-space-11); - } - - .sm\:cu-my-12 { - margin-top: var(--canon-space-12); - margin-bottom: var(--canon-space-12); - } - - .sm\:cu-my-13 { - margin-top: var(--canon-space-13); - margin-bottom: var(--canon-space-13); - } - - .sm\:cu-my-14 { - margin-top: var(--canon-space-14); - margin-bottom: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-my { - margin-top: var(--py-md); - margin-bottom: var(--py-md); - } - - .md\:cu-my-0\.5 { - margin-top: var(--canon-space-0_5); - margin-bottom: var(--canon-space-0_5); - } - - .md\:cu-my-1 { - margin-top: var(--canon-space-1); - margin-bottom: var(--canon-space-1); - } - - .md\:cu-my-1\.5 { - margin-top: var(--canon-space-1_5); - margin-bottom: var(--canon-space-1_5); - } - - .md\:cu-my-2 { - margin-top: var(--canon-space-2); - margin-bottom: var(--canon-space-2); - } - - .md\:cu-my-3 { - margin-top: var(--canon-space-3); - margin-bottom: var(--canon-space-3); - } - - .md\:cu-my-4 { - margin-top: var(--canon-space-4); - margin-bottom: var(--canon-space-4); - } - - .md\:cu-my-5 { - margin-top: var(--canon-space-5); - margin-bottom: var(--canon-space-5); - } - - .md\:cu-my-6 { - margin-top: var(--canon-space-6); - margin-bottom: var(--canon-space-6); - } - - .md\:cu-my-7 { - margin-top: var(--canon-space-7); - margin-bottom: var(--canon-space-7); - } - - .md\:cu-my-8 { - margin-top: var(--canon-space-8); - margin-bottom: var(--canon-space-8); - } - - .md\:cu-my-9 { - margin-top: var(--canon-space-9); - margin-bottom: var(--canon-space-9); - } - - .md\:cu-my-10 { - margin-top: var(--canon-space-10); - margin-bottom: var(--canon-space-10); - } - - .md\:cu-my-11 { - margin-top: var(--canon-space-11); - margin-bottom: var(--canon-space-11); - } - - .md\:cu-my-12 { - margin-top: var(--canon-space-12); - margin-bottom: var(--canon-space-12); - } - - .md\:cu-my-13 { - margin-top: var(--canon-space-13); - margin-bottom: var(--canon-space-13); - } - - .md\:cu-my-14 { - margin-top: var(--canon-space-14); - margin-bottom: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-my { - margin-top: var(--py-lg); - margin-bottom: var(--py-lg); - } - - .lg\:cu-my-0\.5 { - margin-top: var(--canon-space-0_5); - margin-bottom: var(--canon-space-0_5); - } - - .lg\:cu-my-1 { - margin-top: var(--canon-space-1); - margin-bottom: var(--canon-space-1); - } - - .lg\:cu-my-1\.5 { - margin-top: var(--canon-space-1_5); - margin-bottom: var(--canon-space-1_5); - } - - .lg\:cu-my-2 { - margin-top: var(--canon-space-2); - margin-bottom: var(--canon-space-2); - } - - .lg\:cu-my-3 { - margin-top: var(--canon-space-3); - margin-bottom: var(--canon-space-3); - } - - .lg\:cu-my-4 { - margin-top: var(--canon-space-4); - margin-bottom: var(--canon-space-4); - } - - .lg\:cu-my-5 { - margin-top: var(--canon-space-5); - margin-bottom: var(--canon-space-5); - } - - .lg\:cu-my-6 { - margin-top: var(--canon-space-6); - margin-bottom: var(--canon-space-6); - } - - .lg\:cu-my-7 { - margin-top: var(--canon-space-7); - margin-bottom: var(--canon-space-7); - } - - .lg\:cu-my-8 { - margin-top: var(--canon-space-8); - margin-bottom: var(--canon-space-8); - } - - .lg\:cu-my-9 { - margin-top: var(--canon-space-9); - margin-bottom: var(--canon-space-9); - } - - .lg\:cu-my-10 { - margin-top: var(--canon-space-10); - margin-bottom: var(--canon-space-10); - } - - .lg\:cu-my-11 { - margin-top: var(--canon-space-11); - margin-bottom: var(--canon-space-11); - } - - .lg\:cu-my-12 { - margin-top: var(--canon-space-12); - margin-bottom: var(--canon-space-12); - } - - .lg\:cu-my-13 { - margin-top: var(--canon-space-13); - margin-bottom: var(--canon-space-13); - } - - .lg\:cu-my-14 { - margin-top: var(--canon-space-14); - margin-bottom: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-my { - margin-top: var(--py-xl); - margin-bottom: var(--py-xl); - } - - .xl\:cu-my-0\.5 { - margin-top: var(--canon-space-0_5); - margin-bottom: var(--canon-space-0_5); - } - - .xl\:cu-my-1 { - margin-top: var(--canon-space-1); - margin-bottom: var(--canon-space-1); - } - - .xl\:cu-my-1\.5 { - margin-top: var(--canon-space-1_5); - margin-bottom: var(--canon-space-1_5); - } - - .xl\:cu-my-2 { - margin-top: var(--canon-space-2); - margin-bottom: var(--canon-space-2); - } - - .xl\:cu-my-3 { - margin-top: var(--canon-space-3); - margin-bottom: var(--canon-space-3); - } - - .xl\:cu-my-4 { - margin-top: var(--canon-space-4); - margin-bottom: var(--canon-space-4); - } - - .xl\:cu-my-5 { - margin-top: var(--canon-space-5); - margin-bottom: var(--canon-space-5); - } - - .xl\:cu-my-6 { - margin-top: var(--canon-space-6); - margin-bottom: var(--canon-space-6); - } - - .xl\:cu-my-7 { - margin-top: var(--canon-space-7); - margin-bottom: var(--canon-space-7); - } - - .xl\:cu-my-8 { - margin-top: var(--canon-space-8); - margin-bottom: var(--canon-space-8); - } - - .xl\:cu-my-9 { - margin-top: var(--canon-space-9); - margin-bottom: var(--canon-space-9); - } - - .xl\:cu-my-10 { - margin-top: var(--canon-space-10); - margin-bottom: var(--canon-space-10); - } - - .xl\:cu-my-11 { - margin-top: var(--canon-space-11); - margin-bottom: var(--canon-space-11); - } - - .xl\:cu-my-12 { - margin-top: var(--canon-space-12); - margin-bottom: var(--canon-space-12); - } - - .xl\:cu-my-13 { - margin-top: var(--canon-space-13); - margin-bottom: var(--canon-space-13); - } - - .xl\:cu-my-14 { - margin-top: var(--canon-space-14); - margin-bottom: var(--canon-space-14); - } -} - -.cu-mx { - margin-left: var(--mx); - margin-right: var(--mx); -} - -.cu-mx-0\.5 { - margin-left: var(--canon-space-0_5); - margin-right: var(--canon-space-0_5); -} - -.cu-mx-1 { - margin-left: var(--canon-space-1); - margin-right: var(--canon-space-1); -} - -.cu-mx-1\.5 { - margin-left: var(--canon-space-1_5); - margin-right: var(--canon-space-1_5); -} - -.cu-mx-2 { - margin-left: var(--canon-space-2); - margin-right: var(--canon-space-2); -} - -.cu-mx-3 { - margin-left: var(--canon-space-3); - margin-right: var(--canon-space-3); -} - -.cu-mx-4 { - margin-left: var(--canon-space-4); - margin-right: var(--canon-space-4); -} - -.cu-mx-5 { - margin-left: var(--canon-space-5); - margin-right: var(--canon-space-5); -} - -.cu-mx-6 { - margin-left: var(--canon-space-6); - margin-right: var(--canon-space-6); -} - -.cu-mx-7 { - margin-left: var(--canon-space-7); - margin-right: var(--canon-space-7); -} - -.cu-mx-8 { - margin-left: var(--canon-space-8); - margin-right: var(--canon-space-8); -} - -.cu-mx-9 { - margin-left: var(--canon-space-9); - margin-right: var(--canon-space-9); -} - -.cu-mx-10 { - margin-left: var(--canon-space-10); - margin-right: var(--canon-space-10); -} - -.cu-mx-11 { - margin-left: var(--canon-space-11); - margin-right: var(--canon-space-11); -} - -.cu-mx-12 { - margin-left: var(--canon-space-12); - margin-right: var(--canon-space-12); -} - -.cu-mx-13 { - margin-left: var(--canon-space-13); - margin-right: var(--canon-space-13); -} - -.cu-mx-14 { - margin-left: var(--canon-space-14); - margin-right: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-mx { - margin-left: var(--px-xs); - margin-right: var(--px-xs); - } - - .xs\:cu-mx-0\.5 { - margin-left: var(--canon-space-0_5); - margin-right: var(--canon-space-0_5); - } - - .xs\:cu-mx-1 { - margin-left: var(--canon-space-1); - margin-right: var(--canon-space-1); - } - - .xs\:cu-mx-1\.5 { - margin-left: var(--canon-space-1_5); - margin-right: var(--canon-space-1_5); - } - - .xs\:cu-mx-2 { - margin-left: var(--canon-space-2); - margin-right: var(--canon-space-2); - } - - .xs\:cu-mx-3 { - margin-left: var(--canon-space-3); - margin-right: var(--canon-space-3); - } - - .xs\:cu-mx-4 { - margin-left: var(--canon-space-4); - margin-right: var(--canon-space-4); - } - - .xs\:cu-mx-5 { - margin-left: var(--canon-space-5); - margin-right: var(--canon-space-5); - } - - .xs\:cu-mx-6 { - margin-left: var(--canon-space-6); - margin-right: var(--canon-space-6); - } - - .xs\:cu-mx-7 { - margin-left: var(--canon-space-7); - margin-right: var(--canon-space-7); - } - - .xs\:cu-mx-8 { - margin-left: var(--canon-space-8); - margin-right: var(--canon-space-8); - } - - .xs\:cu-mx-9 { - margin-left: var(--canon-space-9); - margin-right: var(--canon-space-9); - } - - .xs\:cu-mx-10 { - margin-left: var(--canon-space-10); - margin-right: var(--canon-space-10); - } - - .xs\:cu-mx-11 { - margin-left: var(--canon-space-11); - margin-right: var(--canon-space-11); - } - - .xs\:cu-mx-12 { - margin-left: var(--canon-space-12); - margin-right: var(--canon-space-12); - } - - .xs\:cu-mx-13 { - margin-left: var(--canon-space-13); - margin-right: var(--canon-space-13); - } - - .xs\:cu-mx-14 { - margin-left: var(--canon-space-14); - margin-right: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-mx { - margin-left: var(--px-sm); - margin-right: var(--px-sm); - } - - .sm\:cu-mx-0\.5 { - margin-left: var(--canon-space-0_5); - margin-right: var(--canon-space-0_5); - } - - .sm\:cu-mx-1 { - margin-left: var(--canon-space-1); - margin-right: var(--canon-space-1); - } - - .sm\:cu-mx-1\.5 { - margin-left: var(--canon-space-1_5); - margin-right: var(--canon-space-1_5); - } - - .sm\:cu-mx-2 { - margin-left: var(--canon-space-2); - margin-right: var(--canon-space-2); - } - - .sm\:cu-mx-3 { - margin-left: var(--canon-space-3); - margin-right: var(--canon-space-3); - } - - .sm\:cu-mx-4 { - margin-left: var(--canon-space-4); - margin-right: var(--canon-space-4); - } - - .sm\:cu-mx-5 { - margin-left: var(--canon-space-5); - margin-right: var(--canon-space-5); - } - - .sm\:cu-mx-6 { - margin-left: var(--canon-space-6); - margin-right: var(--canon-space-6); - } - - .sm\:cu-mx-7 { - margin-left: var(--canon-space-7); - margin-right: var(--canon-space-7); - } - - .sm\:cu-mx-8 { - margin-left: var(--canon-space-8); - margin-right: var(--canon-space-8); - } - - .sm\:cu-mx-9 { - margin-left: var(--canon-space-9); - margin-right: var(--canon-space-9); - } - - .sm\:cu-mx-10 { - margin-left: var(--canon-space-10); - margin-right: var(--canon-space-10); - } - - .sm\:cu-mx-11 { - margin-left: var(--canon-space-11); - margin-right: var(--canon-space-11); - } - - .sm\:cu-mx-12 { - margin-left: var(--canon-space-12); - margin-right: var(--canon-space-12); - } - - .sm\:cu-mx-13 { - margin-left: var(--canon-space-13); - margin-right: var(--canon-space-13); - } - - .sm\:cu-mx-14 { - margin-left: var(--canon-space-14); - margin-right: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-mx { - margin-left: var(--px-md); - margin-right: var(--px-md); - } - - .md\:cu-mx-0\.5 { - margin-left: var(--canon-space-0_5); - margin-right: var(--canon-space-0_5); - } - - .md\:cu-mx-1 { - margin-left: var(--canon-space-1); - margin-right: var(--canon-space-1); - } - - .md\:cu-mx-1\.5 { - margin-left: var(--canon-space-1_5); - margin-right: var(--canon-space-1_5); - } - - .md\:cu-mx-2 { - margin-left: var(--canon-space-2); - margin-right: var(--canon-space-2); - } - - .md\:cu-mx-3 { - margin-left: var(--canon-space-3); - margin-right: var(--canon-space-3); - } - - .md\:cu-mx-4 { - margin-left: var(--canon-space-4); - margin-right: var(--canon-space-4); - } - - .md\:cu-mx-5 { - margin-left: var(--canon-space-5); - margin-right: var(--canon-space-5); - } - - .md\:cu-mx-6 { - margin-left: var(--canon-space-6); - margin-right: var(--canon-space-6); - } - - .md\:cu-mx-7 { - margin-left: var(--canon-space-7); - margin-right: var(--canon-space-7); - } - - .md\:cu-mx-8 { - margin-left: var(--canon-space-8); - margin-right: var(--canon-space-8); - } - - .md\:cu-mx-9 { - margin-left: var(--canon-space-9); - margin-right: var(--canon-space-9); - } - - .md\:cu-mx-10 { - margin-left: var(--canon-space-10); - margin-right: var(--canon-space-10); - } - - .md\:cu-mx-11 { - margin-left: var(--canon-space-11); - margin-right: var(--canon-space-11); - } - - .md\:cu-mx-12 { - margin-left: var(--canon-space-12); - margin-right: var(--canon-space-12); - } - - .md\:cu-mx-13 { - margin-left: var(--canon-space-13); - margin-right: var(--canon-space-13); - } - - .md\:cu-mx-14 { - margin-left: var(--canon-space-14); - margin-right: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-mx { - margin-left: var(--px-lg); - margin-right: var(--px-lg); - } - - .lg\:cu-mx-0\.5 { - margin-left: var(--canon-space-0_5); - margin-right: var(--canon-space-0_5); - } - - .lg\:cu-mx-1 { - margin-left: var(--canon-space-1); - margin-right: var(--canon-space-1); - } - - .lg\:cu-mx-1\.5 { - margin-left: var(--canon-space-1_5); - margin-right: var(--canon-space-1_5); - } - - .lg\:cu-mx-2 { - margin-left: var(--canon-space-2); - margin-right: var(--canon-space-2); - } - - .lg\:cu-mx-3 { - margin-left: var(--canon-space-3); - margin-right: var(--canon-space-3); - } - - .lg\:cu-mx-4 { - margin-left: var(--canon-space-4); - margin-right: var(--canon-space-4); - } - - .lg\:cu-mx-5 { - margin-left: var(--canon-space-5); - margin-right: var(--canon-space-5); - } - - .lg\:cu-mx-6 { - margin-left: var(--canon-space-6); - margin-right: var(--canon-space-6); - } - - .lg\:cu-mx-7 { - margin-left: var(--canon-space-7); - margin-right: var(--canon-space-7); - } - - .lg\:cu-mx-8 { - margin-left: var(--canon-space-8); - margin-right: var(--canon-space-8); - } - - .lg\:cu-mx-9 { - margin-left: var(--canon-space-9); - margin-right: var(--canon-space-9); - } - - .lg\:cu-mx-10 { - margin-left: var(--canon-space-10); - margin-right: var(--canon-space-10); - } - - .lg\:cu-mx-11 { - margin-left: var(--canon-space-11); - margin-right: var(--canon-space-11); - } - - .lg\:cu-mx-12 { - margin-left: var(--canon-space-12); - margin-right: var(--canon-space-12); - } - - .lg\:cu-mx-13 { - margin-left: var(--canon-space-13); - margin-right: var(--canon-space-13); - } - - .lg\:cu-mx-14 { - margin-left: var(--canon-space-14); - margin-right: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-mx { - margin-left: var(--px-xl); - margin-right: var(--px-xl); - } - - .xl\:cu-mx-0\.5 { - margin-left: var(--canon-space-0_5); - margin-right: var(--canon-space-0_5); - } - - .xl\:cu-mx-1 { - margin-left: var(--canon-space-1); - margin-right: var(--canon-space-1); - } - - .xl\:cu-mx-1\.5 { - margin-left: var(--canon-space-1_5); - margin-right: var(--canon-space-1_5); - } - - .xl\:cu-mx-2 { - margin-left: var(--canon-space-2); - margin-right: var(--canon-space-2); - } - - .xl\:cu-mx-3 { - margin-left: var(--canon-space-3); - margin-right: var(--canon-space-3); - } - - .xl\:cu-mx-4 { - margin-left: var(--canon-space-4); - margin-right: var(--canon-space-4); - } - - .xl\:cu-mx-5 { - margin-left: var(--canon-space-5); - margin-right: var(--canon-space-5); - } - - .xl\:cu-mx-6 { - margin-left: var(--canon-space-6); - margin-right: var(--canon-space-6); - } - - .xl\:cu-mx-7 { - margin-left: var(--canon-space-7); - margin-right: var(--canon-space-7); - } - - .xl\:cu-mx-8 { - margin-left: var(--canon-space-8); - margin-right: var(--canon-space-8); - } - - .xl\:cu-mx-9 { - margin-left: var(--canon-space-9); - margin-right: var(--canon-space-9); - } - - .xl\:cu-mx-10 { - margin-left: var(--canon-space-10); - margin-right: var(--canon-space-10); - } - - .xl\:cu-mx-11 { - margin-left: var(--canon-space-11); - margin-right: var(--canon-space-11); - } - - .xl\:cu-mx-12 { - margin-left: var(--canon-space-12); - margin-right: var(--canon-space-12); - } - - .xl\:cu-mx-13 { - margin-left: var(--canon-space-13); - margin-right: var(--canon-space-13); - } - - .xl\:cu-mx-14 { - margin-left: var(--canon-space-14); - margin-right: var(--canon-space-14); - } -} - -.cu-display-none { - display: none; -} - -.cu-display-inline { - display: inline; -} - -.cu-display-inline-block { - display: inline-block; -} - -.cu-display-block { - display: block; -} - -@media (width >= 640px) { - .xs\:cu-display-none { - display: none; - } - - .xs\:cu-display-inline { - display: inline; - } - - .xs\:cu-display-inline-block { - display: inline-block; - } - - .xs\:cu-display-block { - display: block; - } -} - -@media (width >= 768px) { - .sm\:cu-display-none { - display: none; - } - - .sm\:cu-display-inline { - display: inline; - } - - .sm\:cu-display-inline-block { - display: inline-block; - } - - .sm\:cu-display-block { - display: block; - } -} - -@media (width >= 1024px) { - .md\:cu-display-none { - display: none; - } - - .md\:cu-display-inline { - display: inline; - } - - .md\:cu-display-inline-block { - display: inline-block; - } - - .md\:cu-display-block { - display: block; - } -} - -@media (width >= 1280px) { - .lg\:cu-display-none { - display: none; - } - - .lg\:cu-display-inline { - display: inline; - } - - .lg\:cu-display-inline-block { - display: inline-block; - } - - .lg\:cu-display-block { - display: block; - } -} - -@media (width >= 1536px) { - .xl\:cu-display-none { - display: none; - } - - .xl\:cu-display-inline { - display: inline; - } - - .xl\:cu-display-inline-block { - display: inline-block; - } - - .xl\:cu-display-block { - display: block; - } -} - -.cu-w { - width: var(--width); -} - -.cu-min-w { - min-width: var(--min-width); -} - -.cu-max-w { - max-width: var(--max-width); -} - -@media (width >= 640px) { - .xs\:cu-w { - width: var(--width); - } - - .xs\:cu-min-w { - min-width: var(--min-width); - } - - .xs\:cu-max-w { - max-width: var(--max-width); - } -} - -@media (width >= 768px) { - .sm\:cu-w { - width: var(--width); - } - - .sm\:cu-min-w { - min-width: var(--min-width); - } - - .sm\:cu-max-w { - max-width: var(--max-width); - } -} - -@media (width >= 1024px) { - .md\:cu-w { - width: var(--width); - } - - .md\:cu-min-w { - min-width: var(--min-width); - } - - .md\:cu-max-w { - max-width: var(--max-width); - } -} - -@media (width >= 1280px) { - .lg\:cu-w { - width: var(--width); - } - - .lg\:cu-min-w { - min-width: var(--min-width); - } - - .lg\:cu-max-w { - max-width: var(--max-width); - } -} - -@media (width >= 1536px) { - .xl\:cu-w { - width: var(--width); - } - - .xl\:cu-min-w { - min-width: var(--min-width); - } - - .xl\:cu-max-w { - max-width: var(--max-width); - } -} - -.cu-h { - height: var(--height); -} - -.cu-min-h { - min-height: var(--min-height); -} - -.cu-max-h { - max-height: var(--max-height); -} - -@media (width >= 640px) { - .xs\:cu-h { - height: var(--height); - } - - .xs\:cu-min-h { - min-height: var(--min-height); - } - - .xs\:cu-max-h { - max-height: var(--max-height); - } -} - -@media (width >= 768px) { - .sm\:cu-h { - height: var(--height); - } - - .sm\:cu-min-h { - min-height: var(--min-height); - } - - .sm\:cu-max-h { - max-height: var(--max-height); - } -} - -@media (width >= 1024px) { - .md\:cu-h { - height: var(--height); - } - - .md\:cu-min-h { - min-height: var(--min-height); - } - - .md\:cu-max-h { - max-height: var(--max-height); - } -} - -@media (width >= 1280px) { - .lg\:cu-h { - height: var(--height); - } - - .lg\:cu-min-h { - min-height: var(--min-height); - } - - .lg\:cu-max-h { - max-height: var(--max-height); - } -} - -@media (width >= 1536px) { - .xl\:cu-h { - height: var(--height); - } - - .xl\:cu-min-h { - min-height: var(--min-height); - } - - .xl\:cu-max-h { - max-height: var(--max-height); - } -} - -.cu-position-absolute { - position: absolute; -} - -.cu-position-fixed { - position: fixed; -} - -.cu-position-sticky { - position: sticky; -} - -.cu-position-relative { - position: relative; -} - -.cu-position-static { - position: static; -} - -@media (width >= 640px) { - .xs\:cu-position-absolute { - position: absolute; - } - - .xs\:cu-position-fixed { - position: fixed; - } - - .xs\:cu-position-sticky { - position: sticky; - } - - .xs\:cu-position-relative { - position: relative; - } - - .xs\:cu-position-static { - position: static; - } -} - -@media (width >= 768px) { - .sm\:cu-position-absolute { - position: absolute; - } - - .sm\:cu-position-fixed { - position: fixed; - } - - .sm\:cu-position-sticky { - position: sticky; - } - - .sm\:cu-position-relative { - position: relative; - } - - .sm\:cu-position-static { - position: static; - } -} - -@media (width >= 1024px) { - .md\:cu-position-absolute { - position: absolute; - } - - .md\:cu-position-fixed { - position: fixed; - } - - .md\:cu-position-sticky { - position: sticky; - } - - .md\:cu-position-relative { - position: relative; - } - - .md\:cu-position-static { - position: static; - } -} - -@media (width >= 1280px) { - .lg\:cu-position-absolute { - position: absolute; - } - - .lg\:cu-position-fixed { - position: fixed; - } - - .lg\:cu-position-sticky { - position: sticky; - } - - .lg\:cu-position-relative { - position: relative; - } - - .lg\:cu-position-static { - position: static; - } -} - -@media (width >= 1536px) { - .xl\:cu-position-absolute { - position: absolute; - } - - .xl\:cu-position-fixed { - position: fixed; - } - - .xl\:cu-position-sticky { - position: sticky; - } - - .xl\:cu-position-relative { - position: relative; - } - - .xl\:cu-position-static { - position: static; - } -} - -.cu-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); -} - -.cu-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); -} - -.cu-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); -} - -.cu-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); -} - -.cu-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); -} - -.cu-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); -} - -.cu-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); -} - -.cu-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); -} - -.cu-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); -} - -.cu-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); -} - -.cu-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); -} - -.cu-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); -} - -.cu-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); -} - -.cu-col-span-1 { - grid-column: span 1 / span 1; -} - -.cu-col-span-2 { - grid-column: span 2 / span 2; -} - -.cu-col-span-3 { - grid-column: span 3 / span 3; -} - -.cu-col-span-4 { - grid-column: span 4 / span 4; -} - -.cu-col-span-5 { - grid-column: span 5 / span 5; -} - -.cu-col-span-6 { - grid-column: span 6 / span 6; -} - -.cu-col-span-7 { - grid-column: span 7 / span 7; -} - -.cu-col-span-8 { - grid-column: span 8 / span 8; -} - -.cu-col-span-9 { - grid-column: span 9 / span 9; -} - -.cu-col-span-10 { - grid-column: span 10 / span 10; -} - -.cu-col-span-11 { - grid-column: span 11 / span 11; -} - -.cu-col-span-12 { - grid-column: span 12 / span 12; -} - -.cu-col-span-auto { - grid-column: span auto / span auto; -} - -.cu-col-start-1 { - grid-column-start: 1; -} - -.cu-col-start-2 { - grid-column-start: 2; -} - -.cu-col-start-3 { - grid-column-start: 3; -} - -.cu-col-start-4 { - grid-column-start: 4; -} - -.cu-col-start-5 { - grid-column-start: 5; -} - -.cu-col-start-6 { - grid-column-start: 6; -} - -.cu-col-start-7 { - grid-column-start: 7; -} - -.cu-col-start-8 { - grid-column-start: 8; -} - -.cu-col-start-9 { - grid-column-start: 9; -} - -.cu-col-start-10 { - grid-column-start: 10; -} - -.cu-col-start-11 { - grid-column-start: 11; -} - -.cu-col-start-12 { - grid-column-start: 12; -} - -.cu-col-start-13 { - grid-column-start: 13; -} - -.cu-col-start-auto { - grid-column-start: auto; -} - -.cu-col-end-1 { - grid-column-end: 1; -} - -.cu-col-end-2 { - grid-column-end: 2; -} - -.cu-col-end-3 { - grid-column-end: 3; -} - -.cu-col-end-4 { - grid-column-end: 4; -} - -.cu-col-end-5 { - grid-column-end: 5; -} - -.cu-col-end-6 { - grid-column-end: 6; -} - -.cu-col-end-7 { - grid-column-end: 7; -} - -.cu-col-end-8 { - grid-column-end: 8; -} - -.cu-col-end-9 { - grid-column-end: 9; -} - -.cu-col-end-10 { - grid-column-end: 10; -} - -.cu-col-end-11 { - grid-column-end: 11; -} - -.cu-col-end-12 { - grid-column-end: 12; -} - -.cu-col-end-13 { - grid-column-end: 13; -} - -.cu-col-end-auto { - grid-column-end: auto; -} - -.cu-row-span-1 { - grid-row: span 1 / span 1; -} - -.cu-row-span-2 { - grid-row: span 2 / span 2; -} - -.cu-row-span-3 { - grid-row: span 3 / span 3; -} - -.cu-row-span-4 { - grid-row: span 4 / span 4; -} - -.cu-row-span-5 { - grid-row: span 5 / span 5; -} - -.cu-row-span-6 { - grid-row: span 6 / span 6; -} - -.cu-row-span-7 { - grid-row: span 7 / span 7; -} - -.cu-row-span-8 { - grid-row: span 8 / span 8; -} - -.cu-row-span-9 { - grid-row: span 9 / span 9; -} - -.cu-row-span-10 { - grid-row: span 10 / span 10; -} - -.cu-row-span-11 { - grid-row: span 11 / span 11; -} - -.cu-row-span-12 { - grid-row: span 12 / span 12; -} - -.cu-row-span-auto { - grid-row: span auto / span auto; -} - -@media (width >= 640px) { - .xs\:cu-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .xs\:cu-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .xs\:cu-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .xs\:cu-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .xs\:cu-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .xs\:cu-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .xs\:cu-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .xs\:cu-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .xs\:cu-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .xs\:cu-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .xs\:cu-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .xs\:cu-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .xs\:cu-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .xs\:cu-col-span-1 { - grid-column: span 1 / span 1; - } - - .xs\:cu-col-span-2 { - grid-column: span 2 / span 2; - } - - .xs\:cu-col-span-3 { - grid-column: span 3 / span 3; - } - - .xs\:cu-col-span-4 { - grid-column: span 4 / span 4; - } - - .xs\:cu-col-span-5 { - grid-column: span 5 / span 5; - } - - .xs\:cu-col-span-6 { - grid-column: span 6 / span 6; - } - - .xs\:cu-col-span-7 { - grid-column: span 7 / span 7; - } - - .xs\:cu-col-span-8 { - grid-column: span 8 / span 8; - } - - .xs\:cu-col-span-9 { - grid-column: span 9 / span 9; - } - - .xs\:cu-col-span-10 { - grid-column: span 10 / span 10; - } - - .xs\:cu-col-span-11 { - grid-column: span 11 / span 11; - } - - .xs\:cu-col-span-12 { - grid-column: span 12 / span 12; - } - - .xs\:cu-col-span-auto { - grid-column: span auto / span auto; - } - - .xs\:cu-col-start-1 { - grid-column-start: 1; - } - - .xs\:cu-col-start-2 { - grid-column-start: 2; - } - - .xs\:cu-col-start-3 { - grid-column-start: 3; - } - - .xs\:cu-col-start-4 { - grid-column-start: 4; - } - - .xs\:cu-col-start-5 { - grid-column-start: 5; - } - - .xs\:cu-col-start-6 { - grid-column-start: 6; - } - - .xs\:cu-col-start-7 { - grid-column-start: 7; - } - - .xs\:cu-col-start-8 { - grid-column-start: 8; - } - - .xs\:cu-col-start-9 { - grid-column-start: 9; - } - - .xs\:cu-col-start-10 { - grid-column-start: 10; - } - - .xs\:cu-col-start-11 { - grid-column-start: 11; - } - - .xs\:cu-col-start-12 { - grid-column-start: 12; - } - - .xs\:cu-col-start-13 { - grid-column-start: 13; - } - - .xs\:cu-col-start-auto { - grid-column-start: auto; - } - - .xs\:cu-col-end-1 { - grid-column-end: 1; - } - - .xs\:cu-col-end-2 { - grid-column-end: 2; - } - - .xs\:cu-col-end-3 { - grid-column-end: 3; - } - - .xs\:cu-col-end-4 { - grid-column-end: 4; - } - - .xs\:cu-col-end-5 { - grid-column-end: 5; - } - - .xs\:cu-col-end-6 { - grid-column-end: 6; - } - - .xs\:cu-col-end-7 { - grid-column-end: 7; - } - - .xs\:cu-col-end-8 { - grid-column-end: 8; - } - - .xs\:cu-col-end-9 { - grid-column-end: 9; - } - - .xs\:cu-col-end-10 { - grid-column-end: 10; - } - - .xs\:cu-col-end-11 { - grid-column-end: 11; - } - - .xs\:cu-col-end-12 { - grid-column-end: 12; - } - - .xs\:cu-col-end-13 { - grid-column-end: 13; - } - - .xs\:cu-col-end-auto { - grid-column-end: auto; - } - - .xs\:cu-row-span-1 { - grid-row: span 1 / span 1; - } - - .xs\:cu-row-span-2 { - grid-row: span 2 / span 2; - } - - .xs\:cu-row-span-3 { - grid-row: span 3 / span 3; - } - - .xs\:cu-row-span-4 { - grid-row: span 4 / span 4; - } - - .xs\:cu-row-span-5 { - grid-row: span 5 / span 5; - } - - .xs\:cu-row-span-6 { - grid-row: span 6 / span 6; - } - - .xs\:cu-row-span-7 { - grid-row: span 7 / span 7; - } - - .xs\:cu-row-span-8 { - grid-row: span 8 / span 8; - } - - .xs\:cu-row-span-9 { - grid-row: span 9 / span 9; - } - - .xs\:cu-row-span-10 { - grid-row: span 10 / span 10; - } - - .xs\:cu-row-span-11 { - grid-row: span 11 / span 11; - } - - .xs\:cu-row-span-12 { - grid-row: span 12 / span 12; - } - - .xs\:cu-row-span-auto { - grid-row: span auto / span auto; - } -} - -@media (width >= 768px) { - .sm\:cu-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .sm\:cu-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .sm\:cu-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .sm\:cu-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .sm\:cu-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .sm\:cu-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .sm\:cu-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .sm\:cu-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .sm\:cu-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .sm\:cu-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .sm\:cu-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .sm\:cu-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .sm\:cu-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .sm\:cu-col-span-1 { - grid-column: span 1 / span 1; - } - - .sm\:cu-col-span-2 { - grid-column: span 2 / span 2; - } - - .sm\:cu-col-span-3 { - grid-column: span 3 / span 3; - } - - .sm\:cu-col-span-4 { - grid-column: span 4 / span 4; - } - - .sm\:cu-col-span-5 { - grid-column: span 5 / span 5; - } - - .sm\:cu-col-span-6 { - grid-column: span 6 / span 6; - } - - .sm\:cu-col-span-7 { - grid-column: span 7 / span 7; - } - - .sm\:cu-col-span-8 { - grid-column: span 8 / span 8; - } - - .sm\:cu-col-span-9 { - grid-column: span 9 / span 9; - } - - .sm\:cu-col-span-10 { - grid-column: span 10 / span 10; - } - - .sm\:cu-col-span-11 { - grid-column: span 11 / span 11; - } - - .sm\:cu-col-span-12 { - grid-column: span 12 / span 12; - } - - .sm\:cu-col-span-auto { - grid-column: span auto / span auto; - } - - .sm\:cu-col-start-1 { - grid-column-start: 1; - } - - .sm\:cu-col-start-2 { - grid-column-start: 2; - } - - .sm\:cu-col-start-3 { - grid-column-start: 3; - } - - .sm\:cu-col-start-4 { - grid-column-start: 4; - } - - .sm\:cu-col-start-5 { - grid-column-start: 5; - } - - .sm\:cu-col-start-6 { - grid-column-start: 6; - } - - .sm\:cu-col-start-7 { - grid-column-start: 7; - } - - .sm\:cu-col-start-8 { - grid-column-start: 8; - } - - .sm\:cu-col-start-9 { - grid-column-start: 9; - } - - .sm\:cu-col-start-10 { - grid-column-start: 10; - } - - .sm\:cu-col-start-11 { - grid-column-start: 11; - } - - .sm\:cu-col-start-12 { - grid-column-start: 12; - } - - .sm\:cu-col-start-13 { - grid-column-start: 13; - } - - .sm\:cu-col-start-auto { - grid-column-start: auto; - } - - .sm\:cu-col-end-1 { - grid-column-end: 1; - } - - .sm\:cu-col-end-2 { - grid-column-end: 2; - } - - .sm\:cu-col-end-3 { - grid-column-end: 3; - } - - .sm\:cu-col-end-4 { - grid-column-end: 4; - } - - .sm\:cu-col-end-5 { - grid-column-end: 5; - } - - .sm\:cu-col-end-6 { - grid-column-end: 6; - } - - .sm\:cu-col-end-7 { - grid-column-end: 7; - } - - .sm\:cu-col-end-8 { - grid-column-end: 8; - } - - .sm\:cu-col-end-9 { - grid-column-end: 9; - } - - .sm\:cu-col-end-10 { - grid-column-end: 10; - } - - .sm\:cu-col-end-11 { - grid-column-end: 11; - } - - .sm\:cu-col-end-12 { - grid-column-end: 12; - } - - .sm\:cu-col-end-13 { - grid-column-end: 13; - } - - .sm\:cu-col-end-auto { - grid-column-end: auto; - } - - .sm\:cu-row-span-1 { - grid-row: span 1 / span 1; - } - - .sm\:cu-row-span-2 { - grid-row: span 2 / span 2; - } - - .sm\:cu-row-span-3 { - grid-row: span 3 / span 3; - } - - .sm\:cu-row-span-4 { - grid-row: span 4 / span 4; - } - - .sm\:cu-row-span-5 { - grid-row: span 5 / span 5; - } - - .sm\:cu-row-span-6 { - grid-row: span 6 / span 6; - } - - .sm\:cu-row-span-7 { - grid-row: span 7 / span 7; - } - - .sm\:cu-row-span-8 { - grid-row: span 8 / span 8; - } - - .sm\:cu-row-span-9 { - grid-row: span 9 / span 9; - } - - .sm\:cu-row-span-10 { - grid-row: span 10 / span 10; - } - - .sm\:cu-row-span-11 { - grid-row: span 11 / span 11; - } - - .sm\:cu-row-span-12 { - grid-row: span 12 / span 12; - } - - .sm\:cu-row-span-auto { - grid-row: span auto / span auto; - } -} - -@media (width >= 1024px) { - .md\:cu-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .md\:cu-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .md\:cu-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .md\:cu-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .md\:cu-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .md\:cu-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .md\:cu-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .md\:cu-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .md\:cu-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .md\:cu-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .md\:cu-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .md\:cu-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .md\:cu-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .md\:cu-col-span-1 { - grid-column: span 1 / span 1; - } - - .md\:cu-col-span-2 { - grid-column: span 2 / span 2; - } - - .md\:cu-col-span-3 { - grid-column: span 3 / span 3; - } - - .md\:cu-col-span-4 { - grid-column: span 4 / span 4; - } - - .md\:cu-col-span-5 { - grid-column: span 5 / span 5; - } - - .md\:cu-col-span-6 { - grid-column: span 6 / span 6; - } - - .md\:cu-col-span-7 { - grid-column: span 7 / span 7; - } - - .md\:cu-col-span-8 { - grid-column: span 8 / span 8; - } - - .md\:cu-col-span-9 { - grid-column: span 9 / span 9; - } - - .md\:cu-col-span-10 { - grid-column: span 10 / span 10; - } - - .md\:cu-col-span-11 { - grid-column: span 11 / span 11; - } - - .md\:cu-col-span-12 { - grid-column: span 12 / span 12; - } - - .md\:cu-col-span-auto { - grid-column: span auto / span auto; - } - - .md\:cu-col-start-1 { - grid-column-start: 1; - } - - .md\:cu-col-start-2 { - grid-column-start: 2; - } - - .md\:cu-col-start-3 { - grid-column-start: 3; - } - - .md\:cu-col-start-4 { - grid-column-start: 4; - } - - .md\:cu-col-start-5 { - grid-column-start: 5; - } - - .md\:cu-col-start-6 { - grid-column-start: 6; - } - - .md\:cu-col-start-7 { - grid-column-start: 7; - } - - .md\:cu-col-start-8 { - grid-column-start: 8; - } - - .md\:cu-col-start-9 { - grid-column-start: 9; - } - - .md\:cu-col-start-10 { - grid-column-start: 10; - } - - .md\:cu-col-start-11 { - grid-column-start: 11; - } - - .md\:cu-col-start-12 { - grid-column-start: 12; - } - - .md\:cu-col-start-13 { - grid-column-start: 13; - } - - .md\:cu-col-start-auto { - grid-column-start: auto; - } - - .md\:cu-col-end-1 { - grid-column-end: 1; - } - - .md\:cu-col-end-2 { - grid-column-end: 2; - } - - .md\:cu-col-end-3 { - grid-column-end: 3; - } - - .md\:cu-col-end-4 { - grid-column-end: 4; - } - - .md\:cu-col-end-5 { - grid-column-end: 5; - } - - .md\:cu-col-end-6 { - grid-column-end: 6; - } - - .md\:cu-col-end-7 { - grid-column-end: 7; - } - - .md\:cu-col-end-8 { - grid-column-end: 8; - } - - .md\:cu-col-end-9 { - grid-column-end: 9; - } - - .md\:cu-col-end-10 { - grid-column-end: 10; - } - - .md\:cu-col-end-11 { - grid-column-end: 11; - } - - .md\:cu-col-end-12 { - grid-column-end: 12; - } - - .md\:cu-col-end-13 { - grid-column-end: 13; - } - - .md\:cu-col-end-auto { - grid-column-end: auto; - } - - .md\:cu-row-span-1 { - grid-row: span 1 / span 1; - } - - .md\:cu-row-span-2 { - grid-row: span 2 / span 2; - } - - .md\:cu-row-span-3 { - grid-row: span 3 / span 3; - } - - .md\:cu-row-span-4 { - grid-row: span 4 / span 4; - } - - .md\:cu-row-span-5 { - grid-row: span 5 / span 5; - } - - .md\:cu-row-span-6 { - grid-row: span 6 / span 6; - } - - .md\:cu-row-span-7 { - grid-row: span 7 / span 7; - } - - .md\:cu-row-span-8 { - grid-row: span 8 / span 8; - } - - .md\:cu-row-span-9 { - grid-row: span 9 / span 9; - } - - .md\:cu-row-span-10 { - grid-row: span 10 / span 10; - } - - .md\:cu-row-span-11 { - grid-row: span 11 / span 11; - } - - .md\:cu-row-span-12 { - grid-row: span 12 / span 12; - } - - .md\:cu-row-span-auto { - grid-row: span auto / span auto; - } -} - -@media (width >= 1280px) { - .lg\:cu-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .lg\:cu-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .lg\:cu-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .lg\:cu-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .lg\:cu-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .lg\:cu-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .lg\:cu-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .lg\:cu-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .lg\:cu-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .lg\:cu-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .lg\:cu-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .lg\:cu-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .lg\:cu-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .lg\:cu-col-span-1 { - grid-column: span 1 / span 1; - } - - .lg\:cu-col-span-2 { - grid-column: span 2 / span 2; - } - - .lg\:cu-col-span-3 { - grid-column: span 3 / span 3; - } - - .lg\:cu-col-span-4 { - grid-column: span 4 / span 4; - } - - .lg\:cu-col-span-5 { - grid-column: span 5 / span 5; - } - - .lg\:cu-col-span-6 { - grid-column: span 6 / span 6; - } - - .lg\:cu-col-span-7 { - grid-column: span 7 / span 7; - } - - .lg\:cu-col-span-8 { - grid-column: span 8 / span 8; - } - - .lg\:cu-col-span-9 { - grid-column: span 9 / span 9; - } - - .lg\:cu-col-span-10 { - grid-column: span 10 / span 10; - } - - .lg\:cu-col-span-11 { - grid-column: span 11 / span 11; - } - - .lg\:cu-col-span-12 { - grid-column: span 12 / span 12; - } - - .lg\:cu-col-span-auto { - grid-column: span auto / span auto; - } - - .lg\:cu-col-start-1 { - grid-column-start: 1; - } - - .lg\:cu-col-start-2 { - grid-column-start: 2; - } - - .lg\:cu-col-start-3 { - grid-column-start: 3; - } - - .lg\:cu-col-start-4 { - grid-column-start: 4; - } - - .lg\:cu-col-start-5 { - grid-column-start: 5; - } - - .lg\:cu-col-start-6 { - grid-column-start: 6; - } - - .lg\:cu-col-start-7 { - grid-column-start: 7; - } - - .lg\:cu-col-start-8 { - grid-column-start: 8; - } - - .lg\:cu-col-start-9 { - grid-column-start: 9; - } - - .lg\:cu-col-start-10 { - grid-column-start: 10; - } - - .lg\:cu-col-start-11 { - grid-column-start: 11; - } - - .lg\:cu-col-start-12 { - grid-column-start: 12; - } - - .lg\:cu-col-start-13 { - grid-column-start: 13; - } - - .lg\:cu-col-start-auto { - grid-column-start: auto; - } - - .lg\:cu-col-end-1 { - grid-column-end: 1; - } - - .lg\:cu-col-end-2 { - grid-column-end: 2; - } - - .lg\:cu-col-end-3 { - grid-column-end: 3; - } - - .lg\:cu-col-end-4 { - grid-column-end: 4; - } - - .lg\:cu-col-end-5 { - grid-column-end: 5; - } - - .lg\:cu-col-end-6 { - grid-column-end: 6; - } - - .lg\:cu-col-end-7 { - grid-column-end: 7; - } - - .lg\:cu-col-end-8 { - grid-column-end: 8; - } - - .lg\:cu-col-end-9 { - grid-column-end: 9; - } - - .lg\:cu-col-end-10 { - grid-column-end: 10; - } - - .lg\:cu-col-end-11 { - grid-column-end: 11; - } - - .lg\:cu-col-end-12 { - grid-column-end: 12; - } - - .lg\:cu-col-end-13 { - grid-column-end: 13; - } - - .lg\:cu-col-end-auto { - grid-column-end: auto; - } - - .lg\:cu-row-span-1 { - grid-row: span 1 / span 1; - } - - .lg\:cu-row-span-2 { - grid-row: span 2 / span 2; - } - - .lg\:cu-row-span-3 { - grid-row: span 3 / span 3; - } - - .lg\:cu-row-span-4 { - grid-row: span 4 / span 4; - } - - .lg\:cu-row-span-5 { - grid-row: span 5 / span 5; - } - - .lg\:cu-row-span-6 { - grid-row: span 6 / span 6; - } - - .lg\:cu-row-span-7 { - grid-row: span 7 / span 7; - } - - .lg\:cu-row-span-8 { - grid-row: span 8 / span 8; - } - - .lg\:cu-row-span-9 { - grid-row: span 9 / span 9; - } - - .lg\:cu-row-span-10 { - grid-row: span 10 / span 10; - } - - .lg\:cu-row-span-11 { - grid-row: span 11 / span 11; - } - - .lg\:cu-row-span-12 { - grid-row: span 12 / span 12; - } - - .lg\:cu-row-span-auto { - grid-row: span auto / span auto; - } -} - -@media (width >= 1536px) { - .xl\:cu-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .xl\:cu-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .xl\:cu-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .xl\:cu-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .xl\:cu-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .xl\:cu-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .xl\:cu-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .xl\:cu-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .xl\:cu-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .xl\:cu-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .xl\:cu-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .xl\:cu-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .xl\:cu-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .xl\:cu-col-span-1 { - grid-column: span 1 / span 1; - } - - .xl\:cu-col-span-2 { - grid-column: span 2 / span 2; - } - - .xl\:cu-col-span-3 { - grid-column: span 3 / span 3; - } - - .xl\:cu-col-span-4 { - grid-column: span 4 / span 4; - } - - .xl\:cu-col-span-5 { - grid-column: span 5 / span 5; - } - - .xl\:cu-col-span-6 { - grid-column: span 6 / span 6; - } - - .xl\:cu-col-span-7 { - grid-column: span 7 / span 7; - } - - .xl\:cu-col-span-8 { - grid-column: span 8 / span 8; - } - - .xl\:cu-col-span-9 { - grid-column: span 9 / span 9; - } - - .xl\:cu-col-span-10 { - grid-column: span 10 / span 10; - } - - .xl\:cu-col-span-11 { - grid-column: span 11 / span 11; - } - - .xl\:cu-col-span-12 { - grid-column: span 12 / span 12; - } - - .xl\:cu-col-span-auto { - grid-column: span auto / span auto; - } - - .xl\:cu-col-start-1 { - grid-column-start: 1; - } - - .xl\:cu-col-start-2 { - grid-column-start: 2; - } - - .xl\:cu-col-start-3 { - grid-column-start: 3; - } - - .xl\:cu-col-start-4 { - grid-column-start: 4; - } - - .xl\:cu-col-start-5 { - grid-column-start: 5; - } - - .xl\:cu-col-start-6 { - grid-column-start: 6; - } - - .xl\:cu-col-start-7 { - grid-column-start: 7; - } - - .xl\:cu-col-start-8 { - grid-column-start: 8; - } - - .xl\:cu-col-start-9 { - grid-column-start: 9; - } - - .xl\:cu-col-start-10 { - grid-column-start: 10; - } - - .xl\:cu-col-start-11 { - grid-column-start: 11; - } - - .xl\:cu-col-start-12 { - grid-column-start: 12; - } - - .xl\:cu-col-start-13 { - grid-column-start: 13; - } - - .xl\:cu-col-start-auto { - grid-column-start: auto; - } - - .xl\:cu-col-end-1 { - grid-column-end: 1; - } - - .xl\:cu-col-end-2 { - grid-column-end: 2; - } - - .xl\:cu-col-end-3 { - grid-column-end: 3; - } - - .xl\:cu-col-end-4 { - grid-column-end: 4; - } - - .xl\:cu-col-end-5 { - grid-column-end: 5; - } - - .xl\:cu-col-end-6 { - grid-column-end: 6; - } - - .xl\:cu-col-end-7 { - grid-column-end: 7; - } - - .xl\:cu-col-end-8 { - grid-column-end: 8; - } - - .xl\:cu-col-end-9 { - grid-column-end: 9; - } - - .xl\:cu-col-end-10 { - grid-column-end: 10; - } - - .xl\:cu-col-end-11 { - grid-column-end: 11; - } - - .xl\:cu-col-end-12 { - grid-column-end: 12; - } - - .xl\:cu-col-end-13 { - grid-column-end: 13; - } - - .xl\:cu-col-end-auto { - grid-column-end: auto; - } - - .xl\:cu-row-span-1 { - grid-row: span 1 / span 1; - } - - .xl\:cu-row-span-2 { - grid-row: span 2 / span 2; - } - - .xl\:cu-row-span-3 { - grid-row: span 3 / span 3; - } - - .xl\:cu-row-span-4 { - grid-row: span 4 / span 4; - } - - .xl\:cu-row-span-5 { - grid-row: span 5 / span 5; - } - - .xl\:cu-row-span-6 { - grid-row: span 6 / span 6; - } - - .xl\:cu-row-span-7 { - grid-row: span 7 / span 7; - } - - .xl\:cu-row-span-8 { - grid-row: span 8 / span 8; - } - - .xl\:cu-row-span-9 { - grid-row: span 9 / span 9; - } - - .xl\:cu-row-span-10 { - grid-row: span 10 / span 10; - } - - .xl\:cu-row-span-11 { - grid-row: span 11 / span 11; - } - - .xl\:cu-row-span-12 { - grid-row: span 12 / span 12; - } - - .xl\:cu-row-span-auto { - grid-row: span auto / span auto; - } -} - -.cu-gap { - gap: var(--gap); -} - -.cu-gap-0\.5 { - gap: var(--canon-space-0_5); -} - -.cu-gap-1 { - gap: var(--canon-space-1); -} - -.cu-gap-1\.5 { - gap: var(--canon-space-1_5); -} - -.cu-gap-2 { - gap: var(--canon-space-2); -} - -.cu-gap-3 { - gap: var(--canon-space-3); -} - -.cu-gap-4 { - gap: var(--canon-space-4); -} - -.cu-gap-5 { - gap: var(--canon-space-5); -} - -.cu-gap-6 { - gap: var(--canon-space-6); -} - -.cu-gap-7 { - gap: var(--canon-space-7); -} - -.cu-gap-8 { - gap: var(--canon-space-8); -} - -.cu-gap-9 { - gap: var(--canon-space-9); -} - -.cu-gap-10 { - gap: var(--canon-space-10); -} - -.cu-gap-11 { - gap: var(--canon-space-11); -} - -.cu-gap-12 { - gap: var(--canon-space-12); -} - -.cu-gap-13 { - gap: var(--canon-space-13); -} - -.cu-gap-14 { - gap: var(--canon-space-14); -} - -@media (width >= 640px) { - .xs\:cu-gap { - gap: var(--gap-xs); - } - - .xs\:cu-gap-0\.5 { - gap: var(--canon-space-0_5); - } - - .xs\:cu-gap-1 { - gap: var(--canon-space-1); - } - - .xs\:cu-gap-1\.5 { - gap: var(--canon-space-1_5); - } - - .xs\:cu-gap-2 { - gap: var(--canon-space-2); - } - - .xs\:cu-gap-3 { - gap: var(--canon-space-3); - } - - .xs\:cu-gap-4 { - gap: var(--canon-space-4); - } - - .xs\:cu-gap-5 { - gap: var(--canon-space-5); - } - - .xs\:cu-gap-6 { - gap: var(--canon-space-6); - } - - .xs\:cu-gap-7 { - gap: var(--canon-space-7); - } - - .xs\:cu-gap-8 { - gap: var(--canon-space-8); - } - - .xs\:cu-gap-9 { - gap: var(--canon-space-9); - } - - .xs\:cu-gap-10 { - gap: var(--canon-space-10); - } - - .xs\:cu-gap-11 { - gap: var(--canon-space-11); - } - - .xs\:cu-gap-12 { - gap: var(--canon-space-12); - } - - .xs\:cu-gap-13 { - gap: var(--canon-space-13); - } - - .xs\:cu-gap-14 { - gap: var(--canon-space-14); - } -} - -@media (width >= 768px) { - .sm\:cu-gap { - gap: var(--gap-sm); - } - - .sm\:cu-gap-0\.5 { - gap: var(--canon-space-0_5); - } - - .sm\:cu-gap-1 { - gap: var(--canon-space-1); - } - - .sm\:cu-gap-1\.5 { - gap: var(--canon-space-1_5); - } - - .sm\:cu-gap-2 { - gap: var(--canon-space-2); - } - - .sm\:cu-gap-3 { - gap: var(--canon-space-3); - } - - .sm\:cu-gap-4 { - gap: var(--canon-space-4); - } - - .sm\:cu-gap-5 { - gap: var(--canon-space-5); - } - - .sm\:cu-gap-6 { - gap: var(--canon-space-6); - } - - .sm\:cu-gap-7 { - gap: var(--canon-space-7); - } - - .sm\:cu-gap-8 { - gap: var(--canon-space-8); - } - - .sm\:cu-gap-9 { - gap: var(--canon-space-9); - } - - .sm\:cu-gap-10 { - gap: var(--canon-space-10); - } - - .sm\:cu-gap-11 { - gap: var(--canon-space-11); - } - - .sm\:cu-gap-12 { - gap: var(--canon-space-12); - } - - .sm\:cu-gap-13 { - gap: var(--canon-space-13); - } - - .sm\:cu-gap-14 { - gap: var(--canon-space-14); - } -} - -@media (width >= 1024px) { - .md\:cu-gap { - gap: var(--gap-md); - } - - .md\:cu-gap-0\.5 { - gap: var(--canon-space-0_5); - } - - .md\:cu-gap-1 { - gap: var(--canon-space-1); - } - - .md\:cu-gap-1\.5 { - gap: var(--canon-space-1_5); - } - - .md\:cu-gap-2 { - gap: var(--canon-space-2); - } - - .md\:cu-gap-3 { - gap: var(--canon-space-3); - } - - .md\:cu-gap-4 { - gap: var(--canon-space-4); - } - - .md\:cu-gap-5 { - gap: var(--canon-space-5); - } - - .md\:cu-gap-6 { - gap: var(--canon-space-6); - } - - .md\:cu-gap-7 { - gap: var(--canon-space-7); - } - - .md\:cu-gap-8 { - gap: var(--canon-space-8); - } - - .md\:cu-gap-9 { - gap: var(--canon-space-9); - } - - .md\:cu-gap-10 { - gap: var(--canon-space-10); - } - - .md\:cu-gap-11 { - gap: var(--canon-space-11); - } - - .md\:cu-gap-12 { - gap: var(--canon-space-12); - } - - .md\:cu-gap-13 { - gap: var(--canon-space-13); - } - - .md\:cu-gap-14 { - gap: var(--canon-space-14); - } -} - -@media (width >= 1280px) { - .lg\:cu-gap { - gap: var(--gap-lg); - } - - .lg\:cu-gap-0\.5 { - gap: var(--canon-space-0_5); - } - - .lg\:cu-gap-1 { - gap: var(--canon-space-1); - } - - .lg\:cu-gap-1\.5 { - gap: var(--canon-space-1_5); - } - - .lg\:cu-gap-2 { - gap: var(--canon-space-2); - } - - .lg\:cu-gap-3 { - gap: var(--canon-space-3); - } - - .lg\:cu-gap-4 { - gap: var(--canon-space-4); - } - - .lg\:cu-gap-5 { - gap: var(--canon-space-5); - } - - .lg\:cu-gap-6 { - gap: var(--canon-space-6); - } - - .lg\:cu-gap-7 { - gap: var(--canon-space-7); - } - - .lg\:cu-gap-8 { - gap: var(--canon-space-8); - } - - .lg\:cu-gap-9 { - gap: var(--canon-space-9); - } - - .lg\:cu-gap-10 { - gap: var(--canon-space-10); - } - - .lg\:cu-gap-11 { - gap: var(--canon-space-11); - } - - .lg\:cu-gap-12 { - gap: var(--canon-space-12); - } - - .lg\:cu-gap-13 { - gap: var(--canon-space-13); - } - - .lg\:cu-gap-14 { - gap: var(--canon-space-14); - } -} - -@media (width >= 1536px) { - .xl\:cu-gap { - gap: var(--gap-xl); - } - - .xl\:cu-gap-0\.5 { - gap: var(--canon-space-0_5); - } - - .xl\:cu-gap-1 { - gap: var(--canon-space-1); - } - - .xl\:cu-gap-1\.5 { - gap: var(--canon-space-1_5); - } - - .xl\:cu-gap-2 { - gap: var(--canon-space-2); - } - - .xl\:cu-gap-3 { - gap: var(--canon-space-3); - } - - .xl\:cu-gap-4 { - gap: var(--canon-space-4); - } - - .xl\:cu-gap-5 { - gap: var(--canon-space-5); - } - - .xl\:cu-gap-6 { - gap: var(--canon-space-6); - } - - .xl\:cu-gap-7 { - gap: var(--canon-space-7); - } - - .xl\:cu-gap-8 { - gap: var(--canon-space-8); - } - - .xl\:cu-gap-9 { - gap: var(--canon-space-9); - } - - .xl\:cu-gap-10 { - gap: var(--canon-space-10); - } - - .xl\:cu-gap-11 { - gap: var(--canon-space-11); - } - - .xl\:cu-gap-12 { - gap: var(--canon-space-12); - } - - .xl\:cu-gap-13 { - gap: var(--canon-space-13); - } - - .xl\:cu-gap-14 { - gap: var(--canon-space-14); - } -} - -.cu-align-start { - align-items: start; -} - -.cu-align-center { - align-items: center; -} - -.cu-align-end { - align-items: end; -} - -.cu-align-stretch { - align-items: stretch; -} - -.cu-jc-start { - justify-content: start; -} - -.cu-jc-center { - justify-content: center; -} - -.cu-jc-end { - justify-content: end; -} - -.cu-jc-between { - justify-content: space-between; -} - -.cu-fd-row { - flex-direction: row; -} - -.cu-fd-column { - flex-direction: column; -} - -.cu-fd-row-reverse { - flex-direction: row-reverse; -} - -.cu-fd-column-reverse { - flex-direction: column-reverse; -} - -@media (width >= 640px) { - .xs\:cu-align-start { - align-items: start; - } - - .xs\:cu-align-center { - align-items: center; - } - - .xs\:cu-align-end { - align-items: end; - } - - .xs\:cu-align-stretch { - align-items: stretch; - } - - .xs\:cu-jc-start { - justify-content: start; - } - - .xs\:cu-jc-center { - justify-content: center; - } - - .xs\:cu-jc-end { - justify-content: end; - } - - .xs\:cu-jc-between { - justify-content: space-between; - } - - .xs\:cu-fd-row { - flex-direction: row; - } - - .xs\:cu-fd-column { - flex-direction: column; - } - - .xs\:cu-fd-row-reverse { - flex-direction: row-reverse; - } - - .xs\:cu-fd-column-reverse { - flex-direction: column-reverse; - } -} - -@media (width >= 768px) { - .sm\:cu-align-start { - align-items: start; - } - - .sm\:cu-align-center { - align-items: center; - } - - .sm\:cu-align-end { - align-items: end; - } - - .sm\:cu-align-stretch { - align-items: stretch; - } - - .sm\:cu-jc-start { - justify-content: start; - } - - .sm\:cu-jc-center { - justify-content: center; - } - - .sm\:cu-jc-end { - justify-content: end; - } - - .sm\:cu-jc-between { - justify-content: space-between; - } - - .sm\:cu-fd-row { - flex-direction: row; - } - - .sm\:cu-fd-column { - flex-direction: column; - } - - .sm\:cu-fd-row-reverse { - flex-direction: row-reverse; - } - - .sm\:cu-fd-column-reverse { - flex-direction: column-reverse; - } -} - -@media (width >= 1024px) { - .md\:cu-align-start { - align-items: start; - } - - .md\:cu-align-center { - align-items: center; - } - - .md\:cu-align-end { - align-items: end; - } - - .md\:cu-align-stretch { - align-items: stretch; - } - - .md\:cu-jc-start { - justify-content: start; - } - - .md\:cu-jc-center { - justify-content: center; - } - - .md\:cu-jc-end { - justify-content: end; - } - - .md\:cu-jc-between { - justify-content: space-between; - } - - .md\:cu-fd-row { - flex-direction: row; - } - - .md\:cu-fd-column { - flex-direction: column; - } - - .md\:cu-fd-row-reverse { - flex-direction: row-reverse; - } - - .md\:cu-fd-column-reverse { - flex-direction: column-reverse; - } -} - -@media (width >= 1280px) { - .lg\:cu-align-start { - align-items: start; - } - - .lg\:cu-align-center { - align-items: center; - } - - .lg\:cu-align-end { - align-items: end; - } - - .lg\:cu-align-stretch { - align-items: stretch; - } - - .lg\:cu-jc-start { - justify-content: start; - } - - .lg\:cu-jc-center { - justify-content: center; - } - - .lg\:cu-jc-end { - justify-content: end; - } - - .lg\:cu-jc-between { - justify-content: space-between; - } - - .lg\:cu-fd-row { - flex-direction: row; - } - - .lg\:cu-fd-column { - flex-direction: column; - } - - .lg\:cu-fd-row-reverse { - flex-direction: row-reverse; - } - - .lg\:cu-fd-column-reverse { - flex-direction: column-reverse; - } -} - -@media (width >= 1536px) { - .xl\:cu-align-start { - align-items: start; - } - - .xl\:cu-align-center { - align-items: center; - } - - .xl\:cu-align-end { - align-items: end; - } - - .xl\:cu-align-stretch { - align-items: stretch; - } - - .xl\:cu-jc-start { - justify-content: start; - } - - .xl\:cu-jc-center { - justify-content: center; - } - - .xl\:cu-jc-end { - justify-content: end; - } - - .xl\:cu-jc-between { - justify-content: space-between; - } - - .xl\:cu-fd-row { - flex-direction: row; - } - - .xl\:cu-fd-column { - flex-direction: column; - } - - .xl\:cu-fd-row-reverse { - flex-direction: row-reverse; - } - - .xl\:cu-fd-column-reverse { - flex-direction: column-reverse; - } -} - -:where(a) { - color: inherit; - text-decoration: none; -} - -:root { - --canon-font-regular: system-ui; - --canon-font-monospace: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace; - --canon-font-weight-regular: 400; - --canon-font-weight-bold: 600; - --canon-font-size-1: .625rem; - --canon-font-size-2: .75rem; - --canon-font-size-3: .875rem; - --canon-font-size-4: 1rem; - --canon-font-size-5: 1.25rem; - --canon-font-size-6: 1.5rem; - --canon-font-size-7: 2rem; - --canon-font-size-8: 3rem; - --canon-font-size-9: 4rem; - --canon-font-size-10: 5.75rem; - --canon-space: .25rem; - --canon-space-0_5: calc(var(--canon-space) * .5); - --canon-space-1: var(--canon-space); - --canon-space-1_5: calc(var(--canon-space) * 1.5); - --canon-space-2: calc(var(--canon-space) * 2); - --canon-space-3: calc(var(--canon-space) * 3); - --canon-space-4: calc(var(--canon-space) * 4); - --canon-space-5: calc(var(--canon-space) * 5); - --canon-space-6: calc(var(--canon-space) * 6); - --canon-space-7: calc(var(--canon-space) * 7); - --canon-space-8: calc(var(--canon-space) * 8); - --canon-space-9: calc(var(--canon-space) * 9); - --canon-space-10: calc(var(--canon-space) * 10); - --canon-space-11: calc(var(--canon-space) * 11); - --canon-space-12: calc(var(--canon-space) * 12); - --canon-space-13: calc(var(--canon-space) * 13); - --canon-space-14: calc(var(--canon-space) * 14); - --canon-radius-1: calc(.125rem); - --canon-radius-2: calc(.25rem); - --canon-radius-3: calc(.5rem); - --canon-radius-4: calc(.75rem); - --canon-radius-5: calc(1rem); - --canon-radius-6: calc(1.25rem); - --canon-radius-full: 9999px; - --canon-black: #000; - --canon-white: #fff; - --canon-gray-1: #f8f8f8; - --canon-gray-2: #ececec; - --canon-gray-3: #d9d9d9; - --canon-gray-4: #c1c1c1; - --canon-gray-5: #9e9e9e; - --canon-gray-6: #8c8c8c; - --canon-gray-7: #757575; - --canon-gray-8: #595959; - --canon-bg: var(--canon-gray-1); - --canon-bg-surface-1: var(--canon-white); - --canon-bg-surface-2: var(--canon-gray-2); - --canon-bg-solid: #1f5493; - --canon-bg-solid-hover: #163a66; - --canon-bg-solid-pressed: #0f2b4e; - --canon-bg-solid-disabled: #ebebeb; - --canon-bg-tint: transparent; - --canon-bg-tint-hover: #1f549366; - --canon-bg-tint-pressed: #1f549399; - --canon-bg-tint-disabled: #ebebeb; - --canon-bg-danger: #feebe7; - --canon-bg-warning: #fff2b2; - --canon-bg-success: #e6f6eb; - --canon-fg-primary: var(--canon-black); - --canon-fg-secondary: var(--canon-gray-7); - --canon-fg-link: #1f5493; - --canon-fg-link-hover: #1f2d5c; - --canon-fg-disabled: #9e9e9e; - --canon-fg-solid: var(--canon-white); - --canon-fg-solid-disabled: #9c9c9c; - --canon-fg-tint: #1f5493; - --canon-fg-tint-disabled: var(--canon-gray-5); - --canon-fg-danger: #e22b2b; - --canon-fg-warning: #e36d05; - --canon-fg-success: #1db954; - --canon-border: #0000001a; - --canon-border-hover: #0003; - --canon-border-pressed: #0006; - --canon-border-disabled: #0000001a; - --canon-border-danger: #f87a7a; - --canon-border-warning: #e36d05; - --canon-border-success: #53db83; - --canon-ring: #1f5493; - --canon-scrollbar: #a0a0a03b; - --canon-scrollbar-thumb: #a0a0a0; -} - -[data-theme="dark"] { - --canon-gray-1: #191919; - --canon-gray-2: #242424; - --canon-gray-3: #373737; - --canon-gray-4: #464646; - --canon-gray-5: #575757; - --canon-gray-6: #7b7b7b; - --canon-gray-7: #9e9e9e; - --canon-gray-8: #b4b4b4; - --canon-bg: var(--canon-black); - --canon-bg-surface-1: var(--canon-gray-1); - --canon-bg-surface-2: var(--canon-gray-2); - --canon-bg-solid: #9cc9ff; - --canon-bg-solid-hover: #83b9fd; - --canon-bg-solid-pressed: #83b9fd; - --canon-bg-solid-disabled: #222; - --canon-bg-tint: transparent; - --canon-bg-tint-hover: #9cc9ff1f; - --canon-bg-tint-pressed: #9cc9ff29; - --canon-bg-tint-disabled: transparent; - --canon-bg-danger: #3b1219; - --canon-bg-warning: #302008; - --canon-bg-success: #132d21; - --canon-fg-primary: var(--canon-white); - --canon-fg-secondary: var(--canon-gray-7); - --canon-fg-link: #9cc9ff; - --canon-fg-link-hover: #7eb5f7; - --canon-fg-disabled: var(--canon-gray-7); - --canon-fg-solid: #101821; - --canon-fg-solid-disabled: var(--canon-gray-5); - --canon-fg-tint: #9cc9ff; - --canon-fg-tint-disabled: var(--canon-gray-5); - --canon-fg-danger: #e22b2b; - --canon-fg-warning: #e36d05; - --canon-fg-success: #1db954; - --canon-border: #fff3; - --canon-border-hover: #fff6; - --canon-border-pressed: #ffffff80; - --canon-border-disabled: #fff3; - --canon-border-danger: #f87a7a; - --canon-border-warning: #e36d05; - --canon-border-success: #53db83; - --canon-ring: #1f5493; - --canon-scrollbar: #3636363a; - --canon-scrollbar-thumb: #575757; -} diff --git a/packages/canon/css/datatable.css b/packages/canon/css/datatable.css deleted file mode 100644 index edef29f500..0000000000 --- a/packages/canon/css/datatable.css +++ /dev/null @@ -1,23 +0,0 @@ -.canon-DataTablePagination { - padding-top: var(--canon-space-5); - justify-content: space-between; - align-items: center; - display: flex; -} - -.canon-DataTablePagination--left { - justify-content: space-between; - align-items: center; - display: flex; -} - -.canon-DataTablePagination--right { - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - display: flex; -} - -.canon-DataTablePagination--select { - min-width: 10.5rem; -} diff --git a/packages/canon/css/flex.css b/packages/canon/css/flex.css deleted file mode 100644 index 44381d64b3..0000000000 --- a/packages/canon/css/flex.css +++ /dev/null @@ -1,3 +0,0 @@ -.canon-Flex { - display: flex; -} diff --git a/packages/canon/css/grid.css b/packages/canon/css/grid.css deleted file mode 100644 index 0bb9267795..0000000000 --- a/packages/canon/css/grid.css +++ /dev/null @@ -1,3 +0,0 @@ -.canon-Grid { - display: grid; -} diff --git a/packages/canon/css/heading.css b/packages/canon/css/heading.css deleted file mode 100644 index 96d6f13fac..0000000000 --- a/packages/canon/css/heading.css +++ /dev/null @@ -1,51 +0,0 @@ -.canon-Heading { - font-family: var(--canon-font-regular); - color: var(--canon-fg-primary); - margin: 0; - padding: 0; - line-height: 100%; -} - -.canon-Heading[data-variant="display"] { - font-size: var(--canon-font-size-10); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title1"] { - font-size: var(--canon-font-size-9); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title2"] { - font-size: var(--canon-font-size-8); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title3"] { - font-size: var(--canon-font-size-7); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title4"] { - font-size: var(--canon-font-size-title4); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title5"] { - font-size: var(--canon-font-size-5); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-color="primary"] { - color: var(--canon-fg-primary); -} - -.canon-Heading[data-color="secondary"] { - color: var(--canon-fg-secondary); -} - -.canon-Heading[data-truncate] { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} diff --git a/packages/canon/css/icon.css b/packages/canon/css/icon.css deleted file mode 100644 index 35b453cb3f..0000000000 --- a/packages/canon/css/icon.css +++ /dev/null @@ -1,4 +0,0 @@ -.canon-Icon { - width: 1rem; - height: 1rem; -} diff --git a/packages/canon/css/iconbutton.css b/packages/canon/css/iconbutton.css deleted file mode 100644 index dc3f9d94c5..0000000000 --- a/packages/canon/css/iconbutton.css +++ /dev/null @@ -1,89 +0,0 @@ -.canon-IconButton { - user-select: none; - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-bold); - cursor: pointer; - border-radius: var(--canon-radius-2); - justify-content: center; - align-items: center; - gap: var(--canon-space-1_5); - border: none; - padding: 0; - display: inline-flex; - - &:disabled { - cursor: not-allowed; - } -} - -.canon-IconButton[data-variant="primary"] { - background-color: var(--canon-bg-solid); - color: var(--canon-fg-solid); - transition: background-color .15s, box-shadow .15s; - - &:hover { - background-color: var(--canon-bg-solid-hover); - } - - &:active { - background-color: var(--canon-bg-solid-pressed); - } - - &:focus-visible { - outline: 2px solid var(--canon-ring); - outline-offset: 2px; - } - - &:disabled { - background-color: var(--canon-bg-solid-disabled); - color: var(--canon-fg-solid-disabled); - } -} - -.canon-IconButton[data-variant="secondary"] { - background-color: var(--canon-bg-surface-1); - box-shadow: inset 0 0 0 1px var(--canon-border); - color: var(--canon-fg-primary); - transition: box-shadow .15s; - - &:hover { - box-shadow: inset 0 0 0 1px var(--canon-border-hover); - } - - &:active { - box-shadow: inset 0 0 0 1px var(--canon-border-pressed); - } - - &:focus-visible { - box-shadow: inset 0 0 0 2px var(--canon-ring); - outline: none; - transition: none; - } - - &:disabled { - box-shadow: inset 0 0 0 1px var(--canon-border-disabled); - color: var(--canon-fg-disabled); - } -} - -.canon-IconButton[data-size="medium"] { - font-size: var(--canon-font-size-4); - width: 40px; - height: 40px; -} - -.canon-IconButton[data-size="small"] { - font-size: var(--canon-font-size-3); - width: 32px; - height: 32px; -} - -.canon-IconButtonIcon[data-size="small"], .canon-IconButtonIcon[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.canon-IconButtonIcon[data-size="medium"], .canon-IconButtonIcon[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} diff --git a/packages/canon/css/link.css b/packages/canon/css/link.css deleted file mode 100644 index 535beb3d9f..0000000000 --- a/packages/canon/css/link.css +++ /dev/null @@ -1,45 +0,0 @@ -.canon-Link { - font-family: var(--canon-font-regular); - color: var(--canon-fg-link); - cursor: pointer; - margin: 0; - padding: 0; - text-decoration-line: none; - - &:hover { - color: var(--canon-fg-link-hover); - text-underline-offset: calc(.025em + 2px); - text-decoration-line: underline; - text-decoration-style: solid; - text-decoration-thickness: min(2px, max(1px, .05em)); - text-decoration-color: color-mix(in srgb, var(--canon-fg-link-hover) 30%, transparent); - } -} - -.canon-Link[data-variant="body"] { - font-size: var(--canon-font-size-3); - line-height: 140%; -} - -.canon-Link[data-variant="subtitle"] { - font-size: var(--canon-font-size-4); - line-height: 140%; -} - -.canon-Link[data-variant="caption"] { - font-size: var(--canon-font-size-2); - line-height: 140%; -} - -.canon-Link[data-variant="label"] { - font-size: var(--canon-font-size-1); - line-height: 140%; -} - -.canon-Link[data-weight="regular"] { - font-weight: var(--canon-font-weight-regular); -} - -.canon-Link[data-weight="bold"] { - font-weight: var(--canon-font-weight-bold); -} diff --git a/packages/canon/css/menu.css b/packages/canon/css/menu.css deleted file mode 100644 index 4c9433275c..0000000000 --- a/packages/canon/css/menu.css +++ /dev/null @@ -1,177 +0,0 @@ -.canon-MenuPositioner { - outline: 0; -} - -.canon-MenuPopup { - background-color: var(--canon-bg-surface-1); - border: 1px solid var(--canon-border); - color: var(--canon-fg-primary); - transform-origin: var(--transform-origin); - max-width: min(var(--available-width), 340px); - max-height: min(var(--available-height), 500px); - padding-bottom: var(--canon-space-1); - border-radius: .375rem; - outline: none; - flex-direction: column; - transition: transform .15s, opacity .15s; - display: flex; - position: relative; - overflow: auto; - - &[data-starting-style], &[data-ending-style] { - opacity: 0; - transform: scale(.9); - } -} - -.canon-MenuItem { - user-select: none; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; - display: flex; - - &:first-child { - margin-top: var(--canon-space-1); - } - - &[data-highlighted] { - background-color: var(--canon-gray-3); - } -} - -.canon-MenuSubmenuTrigger { - user-select: none; - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; - display: flex; - - & .canon-Icon { - color: var(--canon-fg-secondary); - } - - &:first-child { - margin-top: var(--canon-space-1); - } - - &[data-popup-open], &[data-highlighted] { - background-color: var(--canon-gray-3); - - & .canon-Icon { - color: var(--canon-fg-primary); - } - } -} - -.canon-MenuSeparator { - background-color: var(--color-gray-200); - height: 1px; - margin: .375rem 1rem; -} - -.canon-SubmenuComboboxSearch { - padding-inline: var(--canon-space-3); - border: none; - border-bottom: 1px solid var(--canon-border); - background-color: var(--canon-bg-surface-1); - height: 32px; - color: var(--canon-fg-primary); - line-height: 140%; - font-size: var(--canon-font-size-3); - z-index: 1; - outline: none; - position: sticky; - top: 0; - - &::placeholder { - color: var(--canon-fg-secondary); - } - - &:disabled { - opacity: .6; - cursor: not-allowed; - } -} - -.canon-SubmenuComboboxItems { - padding-top: var(--canon-space-2); - outline: none; - flex-direction: column; - display: flex; - overflow-y: auto; -} - -.canon-SubmenuComboboxNoResults { - padding-inline: var(--canon-space-3); - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-4); - color: var(--canon-fg-secondary); - font-size: var(--canon-font-size-3); -} - -.canon-SubmenuComboboxItem { - user-select: none; - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; - display: flex; - - &[data-highlighted] { - background-color: var(--canon-gray-3); - } - - &[data-disabled] { - opacity: .5; - cursor: not-allowed; - } -} - -.canon-SubmenuComboboxItemCheckbox { - width: 16px; - height: 16px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - border: 1px solid var(--canon-border); - background: var(--canon-bg-surface-1); - flex-shrink: 0; - justify-content: center; - align-items: center; - display: flex; -} - -.canon-SubmenuComboboxItemLabel { - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - overflow: hidden; -} diff --git a/packages/canon/css/scrollarea.css b/packages/canon/css/scrollarea.css deleted file mode 100644 index d5809f2d88..0000000000 --- a/packages/canon/css/scrollarea.css +++ /dev/null @@ -1,50 +0,0 @@ -.canon-ScrollAreaRoot { - box-sizing: border-box; - width: 24rem; - max-width: calc(100vw - 8rem); - height: 8.5rem; -} - -.canon-ScrollAreaViewport { - overscroll-behavior: contain; - height: 100%; -} - -.canon-ScrollAreaContent { - padding-block: .75rem; - flex-direction: column; - gap: 1rem; - padding-left: 1rem; - padding-right: 1.5rem; - display: flex; -} - -.canon-ScrollAreaScrollbar { - background-color: var(--canon-scrollbar); - opacity: 0; - border-radius: .375rem; - justify-content: center; - width: .25rem; - margin: .5rem; - transition: opacity .15s .3s; - display: flex; - - &[data-hovering], &[data-scrolling] { - opacity: 1; - transition-duration: 75ms; - transition-delay: 0s; - } - - &:before { - content: ""; - width: 1.25rem; - height: 100%; - position: absolute; - } -} - -.canon-ScrollAreaThumb { - border-radius: inherit; - background-color: var(--canon-scrollbar-thumb); - width: 100%; -} diff --git a/packages/canon/css/select.css b/packages/canon/css/select.css deleted file mode 100644 index 1c23f39201..0000000000 --- a/packages/canon/css/select.css +++ /dev/null @@ -1,188 +0,0 @@ -.canon-Select { - font-family: var(--canon-font-regular); - flex-direction: column; - width: 100%; - display: flex; -} - -.canon-SelectLabel { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - margin-bottom: var(--canon-space-1_5); - cursor: pointer; -} - -.canon-SelectLabel[data-disabled] { - cursor: default; -} - -.canon-SelectDescription { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-secondary); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-SelectError { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-danger); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-SelectTrigger { - box-sizing: border-box; - border-radius: var(--canon-radius-3); - border: 1px solid var(--canon-border); - padding: 0 var(--canon-space-4); - background-color: var(--canon-bg-surface-1); - font-size: var(--canon-font-size-3); - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - cursor: pointer; - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - width: 100%; - transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; - display: flex; -} - -.canon-SelectTrigger::placeholder { - color: var(--canon-fg-secondary); -} - -.canon-SelectTrigger:hover { - border-color: var(--canon-border-hover); -} - -.canon-SelectTrigger:focus-visible { - border-color: var(--canon-border-pressed); - outline: 0; -} - -.canon-SelectTrigger[data-invalid] { - border-color: var(--canon-fg-danger); -} - -.canon-SelectTrigger[data-invalid]:hover, .canon-SelectTrigger[data-invalid]:focus-visible { - border-width: 2px; -} - -.canon-SelectTrigger[data-disabled] { - cursor: not-allowed; - border-color: var(--canon-border-disabled); - color: var(--canon-fg-disabled); -} - -.canon-SelectTrigger[data-size="small"] { - height: 2rem; -} - -.canon-SelectTrigger[data-size="medium"] { - height: 3rem; -} - -.canon-SelectIcon { - margin-left: var(--canon-space-5); - transition: transform .2s; -} - -.canon-SelectTrigger[data-popup-open] .canon-SelectIcon { - transform: rotate(180deg); -} - -.canon-SelectPopup { - box-sizing: border-box; - max-height: var(--available-height); - background-color: var(--canon-bg-surface-1); - border: 1px solid var(--canon-border); - border-radius: var(--canon-radius-3); - padding-block: var(--canon-space-1); - z-index: 1; - transform-origin: var(--transform-origin); - outline: 0; - transition: transform .15s, opacity .15s; - overflow-y: auto; - box-shadow: 0 4px 12px #0003; -} - -.canon-SelectPopup[data-starting-style], .canon-SelectPopup[data-ending-style] { - opacity: 0; - transform: scale(.9); -} - -.canon-SelectItem { - width: var(--anchor-width); - padding-block: var(--canon-space-2); - padding-inline: var(--canon-space-4); - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-3); - cursor: pointer; - user-select: none; - font-size: var(--canon-font-size-3); - align-items: center; - gap: var(--canon-space-2); - outline: none; - grid-template-columns: 1rem 1fr; - grid-template-areas: "icon text"; - display: grid; - position: relative; -} - -.canon-SelectItem[data-highlighted] { - z-index: 0; - color: var(--canon-fg-primary); - position: relative; -} - -.canon-SelectItem[data-highlighted]:before { - content: ""; - z-index: -1; - background-color: var(--canon-bg-tint-hover); - border-radius: .25rem; - position: absolute; - inset-block: 0; - inset-inline: .25rem; -} - -.canon-SelectItem[data-disabled] { - cursor: not-allowed; - color: var(--canon-fg-disabled); -} - -.canon-SelectItemIndicator { - grid-area: icon; - justify-content: center; - align-items: center; - display: flex; -} - -.canon-SelectItemText { - flex: 1; - grid-area: text; -} - -.canon-SelectRequired { - color: var(--canon-fg-secondary); - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - margin-left: var(--canon-space-1); -} - -.canon-SelectIcon { - justify-content: center; - align-items: center; - display: flex; -} - -.canon-SelectValue { - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; - overflow: hidden; -} diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 3107c83908..9a5b19bff8 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9349,96 +9349,38 @@ .canon-Button[data-size="medium"] { font-size: var(--canon-font-size-4); padding: 0 var(--canon-space-3); - height: 40px; + height: 2.5rem; } .canon-Button[data-size="small"] { font-size: var(--canon-font-size-3); padding: 0 var(--canon-space-2); - height: 32px; + height: 2rem; } -.canon-ButtonIcon[data-size="small"], .canon-ButtonIcon[data-size="small"] svg { +.canon-Button[data-size="small"] svg { width: 1rem; height: 1rem; } -.canon-ButtonIcon[data-size="medium"], .canon-ButtonIcon[data-size="medium"] svg { +.canon-Button[data-size="medium"] svg { width: 1.25rem; height: 1.25rem; } -.canon-CollapsiblePanel { - height: var(--collapsible-panel-height); - transition: all .15s ease-out; - display: flex; - overflow: hidden; - - &[data-starting-style], &[data-ending-style] { - height: 0; - } -} - -.canon-DataTableRoot { - gap: var(--canon-space-3); - flex-direction: column; - display: flex; -} - -.canon-DataTablePagination { - padding-top: var(--canon-space-5); - justify-content: space-between; +.canon-ButtonIcon { + justify-content: center; align-items: center; - display: flex; } -.canon-DataTablePagination--left { - justify-content: space-between; - align-items: center; - display: flex; +.canon-ButtonIcon[data-size="small"] { + width: 2rem; + padding: 0; } -.canon-DataTablePagination--right { - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - display: flex; -} - -.canon-DataTablePagination--select { - min-width: 10.5rem; -} - -.canon-Flex { - display: flex; -} - -.canon-Grid { - display: grid; -} - -.canon-Container { - max-width: 120rem; - padding-inline: var(--canon-space-4); - margin-inline: auto; - transition: padding .2s ease-in-out; -} - -@media (width >= 640px) { - .canon-Container { - padding-inline: var(--canon-space-8); - } -} - -@media (width >= 1024px) { - .canon-Container { - padding-inline: var(--canon-space-12); - } -} - -.canon-Icon { - width: 1rem; - height: 1rem; +.canon-ButtonIcon[data-size="medium"] { + width: 2.5rem; + padding: 0; } .canon-CheckboxRoot { @@ -9494,6 +9436,653 @@ display: flex; } +.canon-CollapsiblePanel { + height: var(--collapsible-panel-height); + transition: all .15s ease-out; + display: flex; + overflow: hidden; + + &[data-starting-style], &[data-ending-style] { + height: 0; + } +} + +.canon-Container { + max-width: 120rem; + padding-inline: var(--canon-space-4); + margin-inline: auto; + transition: padding .2s ease-in-out; +} + +@media (width >= 640px) { + .canon-Container { + padding-inline: var(--canon-space-8); + } +} + +@media (width >= 1024px) { + .canon-Container { + padding-inline: var(--canon-space-12); + } +} + +.canon-DataTableRoot { + gap: var(--canon-space-3); + flex-direction: column; + display: flex; +} + +.canon-DataTablePagination { + padding-top: var(--canon-space-5); + justify-content: space-between; + align-items: center; + display: flex; +} + +.canon-DataTablePagination--left { + justify-content: space-between; + align-items: center; + display: flex; +} + +.canon-DataTablePagination--right { + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + display: flex; +} + +.canon-DataTablePagination--select { + min-width: 10.5rem; +} + +.canon-FieldError { + color: var(--canon-fg-danger); + font-size: var(--canon-font-size-2); + font-weight: var(--canon-font-weight-regular); + margin-top: var(--canon-space-2); +} + +.canon-FieldLabelWrapper { + margin-bottom: var(--canon-space-3); + gap: var(--canon-space-1); + flex-direction: column; + display: flex; +} + +.canon-FieldLabel { + color: var(--canon-fg-primary); + cursor: pointer; + font-weight: var(--canon-font-weight-regular); + font-size: var(--canon-font-size-2); + margin-right: auto; +} + +.canon-FieldSecondaryLabel { + color: var(--canon-fg-secondary); + font-weight: var(--canon-font-weight-regular); + margin-left: var(--canon-space-1); +} + +.canon-FieldDescription { + font-weight: var(--canon-font-weight-regular); + font-size: var(--canon-font-size-2); + color: var(--canon-fg-secondary); + margin: 0; +} + +.canon-Flex { + min-width: 0; + display: flex; +} + +.canon-Grid { + display: grid; +} + +.canon-HeaderToolbar { + z-index: 10; + padding-top: 8px; + position: sticky; + top: 0; + + &:before { + content: ""; + background-color: var(--canon-bg); + z-index: 0; + height: 16px; + position: absolute; + top: 0; + left: 0; + right: 0; + } +} + +.canon-HeaderToolbarWrapper { + z-index: 1; + background-color: var(--canon-bg-surface-1); + padding-inline: var(--canon-space-3); + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + color: var(--canon-fg-primary); + flex-direction: row; + justify-content: space-between; + align-items: center; + height: 52px; + display: flex; + position: relative; +} + +.canon-HeaderToolbarContent { + align-items: center; + gap: var(--canon-space-2); + flex-direction: row; + display: flex; +} + +.canon-HeaderToolbarName { + align-items: center; + gap: var(--canon-space-2); + font-size: var(--canon-font-size-3); + font-weight: var(--canon-font-weight-regular); + flex-direction: row; + flex-shrink: 0; + display: flex; +} + +.canon-HeaderToolbarIcon { + width: 16px; + height: 16px; + color: var(--canon-fg-primary); + + & svg { + width: 100%; + height: 100%; + } +} + +.canon-HeaderToolbarOptions { + right: var(--canon-space-2); + position: absolute; + top: 50%; + transform: translateY(-50%); +} + +.canon-HeaderBreadcrumbs { + align-items: center; + gap: var(--canon-space-2); + font-size: var(--canon-font-size-3); + font-weight: var(--canon-font-weight-regular); + flex-direction: row; + display: flex; +} + +.canon-HeaderBreadcrumb { + align-items: center; + gap: var(--canon-space-2); + flex-direction: row; + display: flex; +} + +.canon-HeaderBreadcrumbLink { + color: var(--canon-fg-secondary); + cursor: pointer; + text-decoration: none; + + &[data-active="true"] { + color: var(--canon-fg-primary); + } +} + +.canon-HeaderBreadcrumbSeparator { + width: 16px; + height: 16px; + color: var(--canon-fg-secondary); +} + +.canon-HeaderTabs { + background-color: var(--canon-bg-surface-1); + padding-inline: var(--canon-space-1); + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + --active-tab-left: 0px; + --active-tab-right: 0px; + --active-tab-top: 0px; + --active-tab-bottom: 0px; + --active-tab-width: 0px; + --active-tab-height: 0px; + --hovered-tab-left: 0px; + --hovered-tab-right: 0px; + --hovered-tab-top: 0px; + --hovered-tab-bottom: 0px; + --hovered-tab-width: 0px; + --hovered-tab-height: 0px; + --hovered-tab-opacity: 0; + --hovered-transition-duration: 0s; + flex-direction: row; + align-items: center; + margin-top: 8px; + display: flex; + position: relative; +} + +.canon-HeaderTabList { + flex-direction: row; + display: flex; +} + +.canon-HeaderTab { + font-size: var(--canon-font-size-3); + color: var(--canon-fg-primary); + cursor: pointer; + z-index: 2; + height: 36px; + padding-inline: var(--canon-space-2); + justify-content: center; + align-items: center; + display: flex; + position: relative; +} + +.canon-HeaderTabActive { + content: ""; + left: calc(var(--active-tab-left) + var(--canon-space-2)); + width: calc(var(--active-tab-width) - var(--canon-space-4)); + background-color: var(--canon-fg-primary); + opacity: 1; + border-radius: 4px; + height: 1px; + transition: all .25s ease-out; + position: absolute; + bottom: -1px; +} + +.canon-HeaderTabHovered { + content: ""; + left: var(--hovered-tab-left); + top: calc(var(--hovered-tab-top) + 4px); + width: var(--hovered-tab-width); + height: calc(var(--hovered-tab-height) - 8px); + background-color: var(--canon-gray-2); + opacity: var(--hovered-tab-opacity); + transition: left var(--hovered-transition-duration) ease-out, top var(--hovered-transition-duration) ease-out, width var(--hovered-transition-duration) ease-out, height var(--hovered-transition-duration) ease-out, opacity .15s ease-out; + border-radius: 4px; + position: absolute; +} + +.canon-Heading { + font-family: var(--canon-font-regular); + color: var(--canon-fg-primary); + margin: 0; + padding: 0; + line-height: 100%; +} + +.canon-Heading[data-variant="display"] { + font-size: var(--canon-font-size-10); + font-weight: var(--canon-font-weight-bold); +} + +.canon-Heading[data-variant="title1"] { + font-size: var(--canon-font-size-9); + font-weight: var(--canon-font-weight-bold); +} + +.canon-Heading[data-variant="title2"] { + font-size: var(--canon-font-size-8); + font-weight: var(--canon-font-weight-bold); +} + +.canon-Heading[data-variant="title3"] { + font-size: var(--canon-font-size-7); + font-weight: var(--canon-font-weight-bold); +} + +.canon-Heading[data-variant="title4"] { + font-size: var(--canon-font-size-6); + font-weight: var(--canon-font-weight-bold); +} + +.canon-Heading[data-variant="title5"] { + font-size: var(--canon-font-size-5); + font-weight: var(--canon-font-weight-bold); +} + +.canon-Heading[data-color="primary"] { + color: var(--canon-fg-primary); +} + +.canon-Heading[data-color="secondary"] { + color: var(--canon-fg-secondary); +} + +.canon-Heading[data-truncate] { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; +} + +.canon-Icon { + width: 1rem; + height: 1rem; +} + +.canon-Link { + font-family: var(--canon-font-regular); + color: var(--canon-fg-link); + cursor: pointer; + margin: 0; + padding: 0; + text-decoration-line: none; + + &:hover { + color: var(--canon-fg-link-hover); + text-underline-offset: calc(.025em + 2px); + text-decoration-line: underline; + text-decoration-style: solid; + text-decoration-thickness: min(2px, max(1px, .05em)); + text-decoration-color: color-mix(in srgb, var(--canon-fg-link-hover) 30%, transparent); + } +} + +.canon-Link[data-variant="body"] { + font-size: var(--canon-font-size-3); + line-height: 140%; +} + +.canon-Link[data-variant="subtitle"] { + font-size: var(--canon-font-size-4); + line-height: 140%; +} + +.canon-Link[data-variant="caption"] { + font-size: var(--canon-font-size-2); + line-height: 140%; +} + +.canon-Link[data-variant="label"] { + font-size: var(--canon-font-size-1); + line-height: 140%; +} + +.canon-Link[data-weight="regular"] { + font-weight: var(--canon-font-weight-regular); +} + +.canon-Link[data-weight="bold"] { + font-weight: var(--canon-font-weight-bold); +} + +.canon-MenuPositioner { + z-index: 100; + outline: 0; +} + +.canon-MenuPopup { + background-color: var(--canon-bg-surface-1); + border: 1px solid var(--canon-border); + color: var(--canon-fg-primary); + transform-origin: var(--transform-origin); + max-width: min(var(--available-width), 340px); + max-height: min(var(--available-height), 500px); + padding-bottom: var(--canon-space-1); + border-radius: .375rem; + outline: none; + flex-direction: column; + transition: transform .15s, opacity .15s; + display: flex; + position: relative; + overflow: auto; + + &[data-starting-style], &[data-ending-style] { + opacity: 0; + transform: scale(.9); + } +} + +.canon-MenuItem { + user-select: none; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + flex-shrink: 0; + text-decoration: none; + display: flex; + + &:first-child { + margin-top: var(--canon-space-1); + } + + &[data-highlighted] { + background-color: var(--canon-gray-3); + } +} + +.canon-MenuSubmenuTrigger { + user-select: none; + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + flex-shrink: 0; + text-decoration: none; + display: flex; + + & .canon-Icon { + color: var(--canon-fg-secondary); + } + + &:first-child { + margin-top: var(--canon-space-1); + } + + &[data-popup-open], &[data-highlighted] { + background-color: var(--canon-gray-3); + + & .canon-Icon { + color: var(--canon-fg-primary); + } + } +} + +.canon-MenuSeparator { + background-color: var(--color-gray-200); + height: 1px; + margin: .375rem 1rem; +} + +.canon-SubmenuComboboxSearch { + padding-inline: var(--canon-space-3); + border: none; + border-bottom: 1px solid var(--canon-border); + background-color: var(--canon-bg-surface-1); + width: 100%; + height: 32px; + color: var(--canon-fg-primary); + line-height: 140%; + font-size: var(--canon-font-size-3); + z-index: 1; + outline: none; + position: sticky; + top: 0; + + &::placeholder { + color: var(--canon-fg-secondary); + } + + &:disabled { + opacity: .6; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItems { + padding-top: var(--canon-space-2); + outline: none; + flex-direction: column; + display: flex; + overflow-y: auto; +} + +.canon-SubmenuComboboxNoResults { + padding-inline: var(--canon-space-3); + padding-top: var(--canon-space-2); + padding-bottom: var(--canon-space-4); + color: var(--canon-fg-secondary); + font-size: var(--canon-font-size-3); +} + +.canon-SubmenuComboboxItem { + user-select: none; + justify-content: space-between; + align-items: center; + gap: var(--canon-space-2); + height: 32px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + margin-inline: var(--canon-space-1); + padding-inline: var(--canon-space-2); + font-size: var(--canon-font-size-3); + cursor: pointer; + outline: 0; + flex-shrink: 0; + text-decoration: none; + display: flex; + + &[data-highlighted] { + background-color: var(--canon-gray-3); + } + + &[data-disabled] { + opacity: .5; + cursor: not-allowed; + } +} + +.canon-SubmenuComboboxItemCheckbox { + width: 16px; + height: 16px; + color: var(--canon-fg-primary); + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + background: var(--canon-bg-surface-1); + flex-shrink: 0; + justify-content: center; + align-items: center; + display: flex; +} + +.canon-SubmenuComboboxItemLabel { + text-overflow: ellipsis; + white-space: nowrap; + flex: 1; + overflow: hidden; +} + +.canon-RadioGroup { + color: var(--canon-fg-primary); + flex-direction: column; + display: flex; +} + +.canon-RadioGroup[data-orientation="horizontal"] .canon-RadioGroupContent { + gap: var(--canon-space-4); + flex-direction: row; +} + +.canon-RadioGroupContent { + gap: var(--canon-space-2); + flex-direction: column; + display: flex; +} + +.canon-Radio { + align-items: center; + gap: var(--canon-space-2); + font-size: var(--canon-font-size-2); + color: var(--canon-fg-primary); + forced-color-adjust: none; + display: flex; + position: relative; + + &:before { + content: ""; + box-sizing: border-box; + border: .125rem solid var(--canon-border); + background: var(--canon-gray-1); + border-radius: var(--canon-radius-full); + width: 1rem; + height: 1rem; + transition: all .2s; + display: block; + } + + &[data-pressed]:before { + border-color: var(--canon-border); + } + + &[data-selected] { + &:before { + border-color: var(--canon-bg-solid); + border-width: .25rem; + } + + &[data-pressed]:before { + border-color: var(--canon-bg-solid); + } + } + + &[data-focus-visible]:before { + outline: 2px solid var(--canon-ring); + outline-offset: 2px; + } + + &[data-disabled] { + cursor: not-allowed; + color: var(--canon-fg-disabled); + + &:before { + border-color: var(--canon-border-disabled); + background: var(--canon-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--canon-border-disabled); + } + } + + &[data-invalid]:before, &[data-invalid][data-selected]:before { + border-color: var(--canon-border-danger); + } + + &[data-disabled][data-invalid] { + color: var(--canon-fg-disabled); + + &:before { + border-color: var(--canon-border-disabled); + background: var(--canon-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--canon-border-disabled); + } + } +} + .canon-TableRoot { caption-side: bottom; border-collapse: collapse; @@ -9710,148 +10299,6 @@ overflow: hidden; } -.canon-Heading { - font-family: var(--canon-font-regular); - color: var(--canon-fg-primary); - margin: 0; - padding: 0; - line-height: 100%; -} - -.canon-Heading[data-variant="display"] { - font-size: var(--canon-font-size-10); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title1"] { - font-size: var(--canon-font-size-9); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title2"] { - font-size: var(--canon-font-size-8); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title3"] { - font-size: var(--canon-font-size-7); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title4"] { - font-size: var(--canon-font-size-title4); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-variant="title5"] { - font-size: var(--canon-font-size-5); - font-weight: var(--canon-font-weight-bold); -} - -.canon-Heading[data-color="primary"] { - color: var(--canon-fg-primary); -} - -.canon-Heading[data-color="secondary"] { - color: var(--canon-fg-secondary); -} - -.canon-Heading[data-truncate] { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.canon-IconButton { - user-select: none; - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-bold); - cursor: pointer; - border-radius: var(--canon-radius-2); - justify-content: center; - align-items: center; - gap: var(--canon-space-1_5); - border: none; - padding: 0; - display: inline-flex; - - &:disabled { - cursor: not-allowed; - } -} - -.canon-IconButton[data-variant="primary"] { - background-color: var(--canon-bg-solid); - color: var(--canon-fg-solid); - transition: background-color .15s, box-shadow .15s; - - &:hover { - background-color: var(--canon-bg-solid-hover); - } - - &:active { - background-color: var(--canon-bg-solid-pressed); - } - - &:focus-visible { - outline: 2px solid var(--canon-ring); - outline-offset: 2px; - } - - &:disabled { - background-color: var(--canon-bg-solid-disabled); - color: var(--canon-fg-solid-disabled); - } -} - -.canon-IconButton[data-variant="secondary"] { - background-color: var(--canon-bg-surface-1); - box-shadow: inset 0 0 0 1px var(--canon-border); - color: var(--canon-fg-primary); - transition: box-shadow .15s; - - &:hover { - box-shadow: inset 0 0 0 1px var(--canon-border-hover); - } - - &:active { - box-shadow: inset 0 0 0 1px var(--canon-border-pressed); - } - - &:focus-visible { - box-shadow: inset 0 0 0 2px var(--canon-ring); - outline: none; - transition: none; - } - - &:disabled { - box-shadow: inset 0 0 0 1px var(--canon-border-disabled); - color: var(--canon-fg-disabled); - } -} - -.canon-IconButton[data-size="medium"] { - font-size: var(--canon-font-size-4); - width: 40px; - height: 40px; -} - -.canon-IconButton[data-size="small"] { - font-size: var(--canon-font-size-3); - width: 32px; - height: 32px; -} - -.canon-IconButtonIcon[data-size="small"], .canon-IconButtonIcon[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.canon-IconButtonIcon[data-size="medium"], .canon-IconButtonIcon[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} - .canon-TextField { font-family: var(--canon-font-regular); flex-direction: column; @@ -9859,61 +10306,51 @@ display: flex; } -.canon-TextFieldLabel { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); +.canon-InputWrapper { + position: relative; + + &[data-size="small"] .canon-Input { + height: 2rem; + } + + &[data-size="medium"] .canon-Input { + height: 2.5rem; + } + + &[data-size="small"] .canon-Input[data-icon] { + padding-left: var(--canon-space-8); + } + + &[data-size="medium"] .canon-Input[data-icon] { + padding-left: var(--canon-space-9); + } +} + +.canon-InputIcon { + left: var(--canon-space-3); + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); - margin-bottom: var(--canon-space-1_5); - cursor: pointer; - margin-right: auto; + flex-shrink: 0; + position: absolute; + top: 50%; + transform: translateY(-50%); + + &[data-size="small"], &[data-size="small"] svg { + width: 1rem; + height: 1rem; + } + + &[data-size="medium"], &[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; + } } -.canon-TextFieldLabel[data-disabled] { - cursor: default; -} - -.canon-TextFieldDescription { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-secondary); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-TextFieldError { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-danger); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-TextFieldInputWrapper { +.canon-Input { padding: 0 var(--canon-space-3); border-radius: var(--canon-radius-3); border: 1px solid var(--canon-border); background-color: var(--canon-bg-surface-1); - align-items: center; - display: flex; -} - -.canon-TextFieldIcon { - margin-right: var(--canon-space-1); - color: var(--canon-fg-primary); - flex-shrink: 0; -} - -.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} - -.canon-TextFieldInput { font-size: var(--canon-font-size-3); font-family: var(--canon-font-regular); font-weight: var(--canon-font-weight-regular); @@ -9921,306 +10358,81 @@ width: 100%; height: 100%; cursor: inherit; - background: none; - border: none; - padding: 0; + align-items: center; transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; -} - -.canon-TextFieldInput:not([data-filled]):has( + .canon-TextFieldClearButton) { - padding-right: 1.25rem; -} - -.canon-TextFieldInput[type="search"]::-webkit-search-cancel-button, .canon-TextFieldInput[type="search"]::-webkit-search-decoration { - appearance: none; -} - -.canon-TextFieldClearButton { - margin-left: var(--canon-space-1); - vertical-align: middle; - color: var(--canon-fg-primary); - background: none; - border: none; - padding: 0; - display: none; -} - -.canon-TextFieldInput[data-filled] + .canon-TextFieldClearButton { - display: inline-block; -} - -.canon-TextFieldClearButtonIcon { - display: block; -} - -.canon-TextFieldInput::placeholder { - color: var(--canon-fg-secondary); -} - -.canon-TextFieldInput[data-focused] { - outline-color: var(--canon-border-pressed); - outline-width: 0; -} - -.canon-TextFieldInputWrapper:has( > .canon-TextFieldInput:hover) { - border-color: var(--canon-border-hover); -} - -.canon-TextField[data-focused] .canon-TextFieldInputWrapper { - border-color: var(--canon-border-pressed); -} - -.canon-TextField[data-invalid] .canon-TextFieldInputWrapper { - border-color: var(--canon-fg-danger); -} - -.canon-TextField[data-disabled] .canon-TextFieldInputWrapper { - opacity: .5; - cursor: not-allowed; - border: 1px solid var(--canon-border-disabled); -} - -.canon-TextField[data-disabled] .canon-TextFieldClearButton { - cursor: inherit; -} - -.canon-TextFieldInputWrapper[data-size="small"] { - height: 2rem; -} - -.canon-TextFieldInputWrapper[data-size="medium"] { - height: 2.5rem; -} - -.canon-TextFieldRequired { - color: var(--canon-fg-secondary); - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - margin-left: var(--canon-space-1); -} - -.canon-MenuPositioner { - outline: 0; -} - -.canon-MenuPopup { - background-color: var(--canon-bg-surface-1); - border: 1px solid var(--canon-border); - color: var(--canon-fg-primary); - transform-origin: var(--transform-origin); - max-width: min(var(--available-width), 340px); - max-height: min(var(--available-height), 500px); - padding-bottom: var(--canon-space-1); - border-radius: .375rem; - outline: none; - flex-direction: column; - transition: transform .15s, opacity .15s; - display: flex; - position: relative; - overflow: auto; - - &[data-starting-style], &[data-ending-style] { - opacity: 0; - transform: scale(.9); - } -} - -.canon-MenuItem { - user-select: none; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; display: flex; - &:first-child { - margin-top: var(--canon-space-1); + &::-webkit-search-cancel-button, &::-webkit-search-decoration { + -webkit-appearance: none; } - &[data-highlighted] { - background-color: var(--canon-gray-3); - } -} - -.canon-MenuSubmenuTrigger { - user-select: none; - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; - display: flex; - - & .canon-Icon { - color: var(--canon-fg-secondary); - } - - &:first-child { - margin-top: var(--canon-space-1); - } - - &[data-popup-open], &[data-highlighted] { - background-color: var(--canon-gray-3); - - & .canon-Icon { - color: var(--canon-fg-primary); - } - } -} - -.canon-MenuSeparator { - background-color: var(--color-gray-200); - height: 1px; - margin: .375rem 1rem; -} - -.canon-SubmenuComboboxSearch { - padding-inline: var(--canon-space-3); - border: none; - border-bottom: 1px solid var(--canon-border); - background-color: var(--canon-bg-surface-1); - height: 32px; - color: var(--canon-fg-primary); - line-height: 140%; - font-size: var(--canon-font-size-3); - z-index: 1; - outline: none; - position: sticky; - top: 0; - &::placeholder { color: var(--canon-fg-secondary); } - &:disabled { - opacity: .6; - cursor: not-allowed; + &[data-focused] { + outline-color: var(--canon-border-pressed); + outline-width: 0; } -} -.canon-SubmenuComboboxItems { - padding-top: var(--canon-space-2); - outline: none; - flex-direction: column; - display: flex; - overflow-y: auto; -} + &[data-hovered] { + border-color: var(--canon-border-hover); + } -.canon-SubmenuComboboxNoResults { - padding-inline: var(--canon-space-3); - padding-top: var(--canon-space-2); - padding-bottom: var(--canon-space-4); - color: var(--canon-fg-secondary); - font-size: var(--canon-font-size-3); -} + &[data-focused] { + border-color: var(--canon-border-pressed); + outline-width: 0; + } -.canon-SubmenuComboboxItem { - user-select: none; - justify-content: space-between; - align-items: center; - gap: var(--canon-space-2); - height: 32px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - margin-inline: var(--canon-space-1); - padding-inline: var(--canon-space-2); - font-size: var(--canon-font-size-3); - cursor: pointer; - outline: 0; - flex-shrink: 0; - text-decoration: none; - display: flex; - - &[data-highlighted] { - background-color: var(--canon-gray-3); + &[data-invalid] { + border-color: var(--canon-fg-danger); } &[data-disabled] { opacity: .5; cursor: not-allowed; + border: 1px solid var(--canon-border-disabled); } } -.canon-SubmenuComboboxItemCheckbox { - width: 16px; - height: 16px; - color: var(--canon-fg-primary); - border-radius: var(--canon-radius-2); - border: 1px solid var(--canon-border); - background: var(--canon-bg-surface-1); - flex-shrink: 0; +.canon-SearchField[data-empty] .canon-InputClear { + display: none; +} + +.canon-InputClear { + cursor: pointer; + color: var(--canon-fg-secondary); + background-color: #0000; + border: none; justify-content: center; align-items: center; - display: flex; -} - -.canon-SubmenuComboboxItemLabel { - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - overflow: hidden; -} - -.canon-Link { - font-family: var(--canon-font-regular); - color: var(--canon-fg-link); - cursor: pointer; margin: 0; padding: 0; - text-decoration-line: none; - - &:hover { - color: var(--canon-fg-link-hover); - text-underline-offset: calc(.025em + 2px); - text-decoration-line: underline; - text-decoration-style: solid; - text-decoration-thickness: min(2px, max(1px, .05em)); - text-decoration-color: color-mix(in srgb, var(--canon-fg-link-hover) 30%, transparent); - } + transition: color .2s ease-in-out; + display: flex; + position: absolute; + top: 0; + bottom: 0; + right: 0; } -.canon-Link[data-variant="body"] { - font-size: var(--canon-font-size-3); - line-height: 140%; +.canon-InputClear:hover { + color: var(--canon-fg-primary); } -.canon-Link[data-variant="subtitle"] { - font-size: var(--canon-font-size-4); - line-height: 140%; +.canon-InputClear[data-size="small"] { + width: 2rem; + height: 2rem; } -.canon-Link[data-variant="caption"] { - font-size: var(--canon-font-size-2); - line-height: 140%; +.canon-InputClear[data-size="medium"] { + width: 2.5rem; + height: 2.5rem; } -.canon-Link[data-variant="label"] { - font-size: var(--canon-font-size-1); - line-height: 140%; -} - -.canon-Link[data-weight="regular"] { - font-weight: var(--canon-font-weight-regular); -} - -.canon-Link[data-weight="bold"] { - font-weight: var(--canon-font-weight-bold); +.canon-InputClear svg { + width: 1rem; + height: 1rem; } .canon-TooltipPopup { @@ -10524,3 +10736,61 @@ width: 100%; overflow: hidden; } + +.canon-Switch { + align-items: center; + gap: var(--canon-space-3); + font-size: var(--canon-font-size-3); + color: var(--canon-fg-primary); + cursor: pointer; + display: flex; + position: relative; + + &[data-pressed] .canon-SwitchIndicator { + &:before { + background: var(--canon-fg-solid); + } + } + + &[data-selected] { + & .canon-SwitchIndicator { + background: var(--canon-bg-solid); + + &:before { + background: var(--canon-fg-solid); + transform: translateX(100%); + } + } + + &[data-pressed] { + & .indicator { + background: var(--canon-gray-3); + } + } + } + + &[data-focus-visible] .canon-SwitchIndicator { + outline-offset: 2px; + outline: 2px solid; + } +} + +.canon-SwitchIndicator { + background: var(--canon-gray-3); + border: 2px; + border-radius: 1.143rem; + width: 2rem; + height: 1.143rem; + transition: all .2s; + + &:before { + content: ""; + background: var(--canon-fg-solid); + border-radius: 16px; + width: .857rem; + height: .857rem; + margin: .143rem; + transition: all .2s; + display: block; + } +} diff --git a/packages/canon/css/table.css b/packages/canon/css/table.css deleted file mode 100644 index f14ee3759e..0000000000 --- a/packages/canon/css/table.css +++ /dev/null @@ -1,4 +0,0 @@ -.canon-TableCell { - padding: var(--canon-space-3); - font-size: var(--canon-font-size-3); -} diff --git a/packages/canon/css/tabs.css b/packages/canon/css/tabs.css deleted file mode 100644 index a9bf036c3e..0000000000 --- a/packages/canon/css/tabs.css +++ /dev/null @@ -1,76 +0,0 @@ -.canon-TabsRoot { - border: 1px solid var(--color-gray-200); - border-radius: .375rem; -} - -.canon-TabsList { - z-index: 0; - display: flex; - position: relative; -} - -.canon-TabsTab { - appearance: none; - color: var(--canon-fg-secondary); - user-select: none; - padding-inline: var(--canon-space-3); - height: 2rem; - font-family: inherit; - font-size: .875rem; - font-weight: 500; - line-height: 1.25rem; - font-size: var(--canon-font-size-2); - cursor: pointer; - background: none; - border: 0; - outline: 0; - justify-content: center; - align-items: center; - margin: 0; - padding-block: 0; - transition: color .2s ease-in-out; - display: flex; - - &[data-selected] { - color: var(--canon-fg-primary); - } - - @media (hover: hover) { - &:hover { - color: var(--canon-fg-primary); - } - } - - &:focus-visible { - position: relative; - - &:before { - content: ""; - outline: 1px solid var(--canon-ring); - outline-offset: -1px; - border-radius: .25rem; - position: absolute; - inset: .25rem 0; - } - } -} - -.canon-TabsIndicator { - z-index: -1; - translate: var(--active-tab-left) -50%; - width: var(--active-tab-width); - background-color: var(--canon-bg-solid); - height: 1px; - transition-property: translate, width; - transition-duration: .2s; - transition-timing-function: ease-in-out; - position: absolute; - bottom: 0; - left: 0; -} - -.canon-TabsPanel { - &[hidden] { - display: none; - } -} diff --git a/packages/canon/css/text.css b/packages/canon/css/text.css deleted file mode 100644 index c4f9671816..0000000000 --- a/packages/canon/css/text.css +++ /dev/null @@ -1,59 +0,0 @@ -.canon-Text { - font-family: var(--canon-font-regular); - margin: 0; - padding: 0; -} - -.canon-Text[data-variant="body"] { - font-size: var(--canon-font-size-3); - line-height: 140%; -} - -.canon-Text[data-variant="subtitle"] { - font-size: var(--canon-font-size-4); - line-height: 140%; -} - -.canon-Text[data-variant="caption"] { - font-size: var(--canon-font-size-2); - line-height: 140%; -} - -.canon-Text[data-variant="label"] { - font-size: var(--canon-font-size-1); - line-height: 140%; -} - -.canon-Text[data-weight="regular"] { - font-weight: var(--canon-font-weight-regular); -} - -.canon-Text[data-weight="bold"] { - font-weight: var(--canon-font-weight-bold); -} - -.canon-Text[data-color="primary"] { - color: var(--canon-fg-primary); -} - -.canon-Text[data-color="secondary"] { - color: var(--canon-fg-secondary); -} - -.canon-Text[data-color="danger"] { - color: var(--canon-fg-danger); -} - -.canon-Text[data-color="warning"] { - color: var(--canon-fg-warning); -} - -.canon-Text[data-color="success"] { - color: var(--canon-fg-success); -} - -.canon-Text[data-truncate] { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} diff --git a/packages/canon/css/textfield.css b/packages/canon/css/textfield.css deleted file mode 100644 index c3c1a88ad6..0000000000 --- a/packages/canon/css/textfield.css +++ /dev/null @@ -1,146 +0,0 @@ -.canon-TextField { - font-family: var(--canon-font-regular); - flex-direction: column; - width: 100%; - display: flex; -} - -.canon-TextFieldLabel { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - margin-bottom: var(--canon-space-1_5); - cursor: pointer; - margin-right: auto; -} - -.canon-TextFieldLabel[data-disabled] { - cursor: default; -} - -.canon-TextFieldDescription { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-secondary); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-TextFieldError { - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-danger); - padding-top: var(--canon-space-1_5); - margin: 0; -} - -.canon-TextFieldInputWrapper { - padding: 0 var(--canon-space-3); - border-radius: var(--canon-radius-3); - border: 1px solid var(--canon-border); - background-color: var(--canon-bg-surface-1); - align-items: center; - display: flex; -} - -.canon-TextFieldIcon { - margin-right: var(--canon-space-1); - color: var(--canon-fg-primary); - flex-shrink: 0; -} - -.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} - -.canon-TextFieldInput { - font-size: var(--canon-font-size-3); - font-family: var(--canon-font-regular); - font-weight: var(--canon-font-weight-regular); - color: var(--canon-fg-primary); - width: 100%; - height: 100%; - cursor: inherit; - background: none; - border: none; - padding: 0; - transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; -} - -.canon-TextFieldInput:not([data-filled]):has( + .canon-TextFieldClearButton) { - padding-right: 1.25rem; -} - -.canon-TextFieldInput[type="search"]::-webkit-search-cancel-button, .canon-TextFieldInput[type="search"]::-webkit-search-decoration { - appearance: none; -} - -.canon-TextFieldClearButton { - margin-left: var(--canon-space-1); - vertical-align: middle; - color: var(--canon-fg-primary); - background: none; - border: none; - padding: 0; - display: none; -} - -.canon-TextFieldInput[data-filled] + .canon-TextFieldClearButton { - display: inline-block; -} - -.canon-TextFieldClearButtonIcon { - display: block; -} - -.canon-TextFieldInput::placeholder { - color: var(--canon-fg-secondary); -} - -.canon-TextFieldInput[data-focused] { - outline-color: var(--canon-border-pressed); - outline-width: 0; -} - -.canon-TextFieldInputWrapper:has( > .canon-TextFieldInput:hover) { - border-color: var(--canon-border-hover); -} - -.canon-TextField[data-focused] .canon-TextFieldInputWrapper { - border-color: var(--canon-border-pressed); -} - -.canon-TextField[data-invalid] .canon-TextFieldInputWrapper { - border-color: var(--canon-fg-danger); -} - -.canon-TextField[data-disabled] .canon-TextFieldInputWrapper { - opacity: .5; - cursor: not-allowed; - border: 1px solid var(--canon-border-disabled); -} - -.canon-TextField[data-disabled] .canon-TextFieldClearButton { - cursor: inherit; -} - -.canon-TextFieldInputWrapper[data-size="small"] { - height: 2rem; -} - -.canon-TextFieldInputWrapper[data-size="medium"] { - height: 2.5rem; -} - -.canon-TextFieldRequired { - color: var(--canon-fg-secondary); - font-size: var(--canon-font-size-2); - font-weight: var(--canon-font-weight-regular); - margin-left: var(--canon-space-1); -} diff --git a/packages/canon/css/tooltip.css b/packages/canon/css/tooltip.css deleted file mode 100644 index 05f2bab79f..0000000000 --- a/packages/canon/css/tooltip.css +++ /dev/null @@ -1,61 +0,0 @@ -.canon-TooltipPopup { - box-sizing: border-box; - transform-origin: var(--transform-origin); - background-color: canvas; - background-color: var(--canon-bg-surface-1); - color: var(--canon-fg-primary); - outline: 1px solid var(--canon-border); - box-shadow: 0 10px 15px -3px var(--canon-border), 0 4px 6px -4px var(--canon-border); - border-radius: .375rem; - flex-direction: column; - padding: .25rem .5rem; - font-size: .875rem; - line-height: 1.25rem; - transition: transform .15s, opacity .15s; - display: flex; - - &[data-starting-style], &[data-ending-style] { - opacity: 0; - transform: scale(.9); - } - - &[data-instant] { - transition-duration: 0s; - } -} - -.canon-TooltipArrow { - display: flex; - - &[data-side="top"] { - bottom: -8px; - rotate: 180deg; - } - - &[data-side="bottom"] { - top: -8px; - rotate: none; - } - - &[data-side="left"] { - right: -13px; - rotate: 90deg; - } - - &[data-side="right"] { - left: -13px; - rotate: -90deg; - } -} - -.canon-TooltipArrow-fill { - fill: var(--canon-bg-surface-1); -} - -.canon-TooltipArrow-outer-stroke { - @media (prefers-color-scheme: light) { - & { - fill: var(--canon-border); - } - } -} diff --git a/packages/canon/package.json b/packages/canon/package.json index db10d0f967..167fca0455 100644 --- a/packages/canon/package.json +++ b/packages/canon/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/canon", - "version": "0.4.0", + "version": "0.6.0-next.0", "backstage": { "role": "web-library" }, @@ -44,14 +44,15 @@ "@base-ui-components/react": "1.0.0-alpha.7", "@remixicon/react": "^4.6.0", "@tanstack/react-table": "^8.21.3", - "clsx": "^2.1.1" + "clsx": "^2.1.1", + "motion": "^12.20.1", + "react-aria-components": "^1.10.1" }, "devDependencies": { "@backstage/cli": "workspace:^", "@storybook/addon-essentials": "^8.6.12", "@storybook/addon-interactions": "^8.6.12", "@storybook/addon-styling-webpack": "^1.0.1", - "@storybook/addon-themes": "^8.6.12", "@storybook/addon-webpack5-compiler-swc": "^3.0.0", "@storybook/blocks": "^8.6.12", "@storybook/react": "^8.6.12", diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index bc0ad71e90..000a94f7dc 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -5,26 +5,34 @@ ```ts import { Avatar as Avatar_2 } from '@base-ui-components/react/avatar'; import { Breakpoint as Breakpoint_2 } from '@backstage/canon'; +import { ButtonProps as ButtonProps_2 } from 'react-aria-components'; import { ChangeEvent } from 'react'; import { Collapsible as Collapsible_2 } from '@base-ui-components/react/collapsible'; import { ComponentProps } from 'react'; +import type { ComponentPropsWithRef } from 'react'; import { Context } from 'react'; import type { CSSProperties } from 'react'; +import type { ElementType } from 'react'; import { FC } from 'react'; import { FocusEvent as FocusEvent_2 } from 'react'; import { ForwardRefExoticComponent } from 'react'; import { HTMLAttributes } from 'react'; import { JSX as JSX_2 } from 'react/jsx-runtime'; +import { LinkProps as LinkProps_2 } from 'react-aria-components'; import { Menu as Menu_2 } from '@base-ui-components/react/menu'; -import type { MouseEventHandler } from 'react'; +import type { RadioGroupProps as RadioGroupProps_2 } from 'react-aria-components'; +import type { RadioProps as RadioProps_2 } from 'react-aria-components'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RefAttributes } from 'react'; import type { RemixiconComponentType } from '@remixicon/react'; import { ScrollArea as ScrollArea_2 } from '@base-ui-components/react/scroll-area'; +import type { SearchFieldProps as SearchFieldProps_2 } from 'react-aria-components'; +import type { SwitchProps as SwitchProps_2 } from 'react-aria-components'; import { Table as Table_2 } from '@tanstack/react-table'; import { Tabs as Tabs_2 } from '@base-ui-components/react/tabs'; import { TdHTMLAttributes } from 'react'; +import type { TextFieldProps as TextFieldProps_2 } from 'react-aria-components'; import { ThHTMLAttributes } from 'react'; import { Tooltip as Tooltip_2 } from '@base-ui-components/react/tooltip'; import type { useRender } from '@base-ui-components/react/use-render'; @@ -153,34 +161,60 @@ export const Button: ForwardRefExoticComponent< >; // @public (undocumented) -export type ButtonOwnProps = GetPropDefTypes; - -// @public (undocumented) -export const buttonPropDefs: { - variant: { - type: 'enum'; - values: ('primary' | 'secondary')[]; - className: string; - default: 'primary'; - responsive: true; - }; - size: { - type: 'enum'; - values: ('small' | 'medium')[]; - className: string; - default: 'medium'; - responsive: true; - }; -}; +export const ButtonIcon: ForwardRefExoticComponent< + ButtonIconProps & RefAttributes +>; // @public -export interface ButtonProps - extends Omit, 'children'> { - children: React.ReactNode; +export interface ButtonIconProps extends ButtonProps_2 { + // (undocumented) + icon?: ReactElement; + // (undocumented) + size?: 'small' | 'medium' | Partial>; + // (undocumented) + variant?: + | 'primary' + | 'secondary' + | Partial>; +} + +// @public (undocumented) +export const ButtonLink: ForwardRefExoticComponent< + ButtonLinkProps & RefAttributes +>; + +// @public +export interface ButtonLinkProps extends LinkProps_2 { + // (undocumented) + children?: ReactNode; + // (undocumented) iconEnd?: ReactElement; + // (undocumented) iconStart?: ReactElement; - size?: ButtonOwnProps['size']; - variant?: ButtonOwnProps['variant']; + // (undocumented) + size?: 'small' | 'medium' | Partial>; + // (undocumented) + variant?: + | 'primary' + | 'secondary' + | Partial>; +} + +// @public +export interface ButtonProps extends ButtonProps_2 { + // (undocumented) + children?: ReactNode; + // (undocumented) + iconEnd?: ReactElement; + // (undocumented) + iconStart?: ReactElement; + // (undocumented) + size?: 'small' | 'medium' | Partial>; + // (undocumented) + variant?: + | 'primary' + | 'secondary' + | Partial>; } // @public (undocumented) @@ -212,6 +246,9 @@ export interface CheckboxProps { value?: string; } +// @public +export type ClassNamesMap = Record; + // @public export const Collapsible: { Root: ForwardRefExoticComponent< @@ -234,6 +271,273 @@ export const Collapsible: { // @public (undocumented) export type Columns = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 'auto'; +// @public +export type ComponentClassNames = + (typeof componentDefinitions)[T]['classNames']; + +// @public +export interface ComponentDefinition { + // (undocumented) + classNames: ClassNamesMap; + // (undocumented) + dataAttributes?: DataAttributesMap; +} + +// @public +export type ComponentDefinitionName = keyof typeof componentDefinitions; + +// @public +export const componentDefinitions: { + readonly Avatar: { + readonly classNames: { + readonly root: 'canon-AvatarRoot'; + readonly image: 'canon-AvatarImage'; + readonly fallback: 'canon-AvatarFallback'; + }; + readonly dataAttributes: { + readonly size: readonly ['small', 'medium', 'large']; + }; + }; + readonly Box: { + readonly classNames: { + readonly root: 'canon-Box'; + }; + }; + readonly Button: { + readonly classNames: { + readonly root: 'canon-Button'; + }; + readonly dataAttributes: { + readonly size: readonly ['small', 'medium', 'large']; + readonly variant: readonly ['primary', 'secondary', 'ghost']; + }; + }; + readonly ButtonIcon: { + readonly classNames: { + readonly root: 'canon-ButtonIcon'; + }; + }; + readonly ButtonLink: { + readonly classNames: { + readonly root: 'canon-ButtonLink'; + }; + }; + readonly Checkbox: { + readonly classNames: { + readonly root: 'canon-CheckboxRoot'; + readonly label: 'canon-CheckboxLabel'; + readonly indicator: 'canon-CheckboxIndicator'; + }; + readonly dataAttributes: { + readonly checked: readonly [true, false]; + }; + }; + readonly Collapsible: { + readonly classNames: { + readonly root: 'canon-CollapsibleRoot'; + readonly trigger: 'canon-CollapsibleTrigger'; + readonly panel: 'canon-CollapsiblePanel'; + }; + }; + readonly Container: { + readonly classNames: { + readonly root: 'canon-Container'; + }; + }; + readonly FieldLabel: { + readonly classNames: { + readonly root: 'canon-FieldLabelWrapper'; + readonly label: 'canon-FieldLabel'; + readonly secondaryLabel: 'canon-FieldSecondaryLabel'; + readonly description: 'canon-FieldDescription'; + }; + }; + readonly Flex: { + readonly classNames: { + readonly root: 'canon-Flex'; + }; + }; + readonly Grid: { + readonly classNames: { + readonly root: 'canon-Grid'; + readonly item: 'canon-GridItem'; + }; + }; + readonly Heading: { + readonly classNames: { + readonly root: 'canon-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: 'canon-Icon'; + }; + }; + readonly Link: { + readonly classNames: { + readonly root: 'canon-Link'; + }; + readonly dataAttributes: { + readonly variant: readonly ['subtitle', 'body', 'caption', 'label']; + readonly weight: readonly ['regular', 'bold']; + }; + }; + readonly Menu: { + readonly classNames: { + readonly trigger: 'canon-MenuTrigger'; + readonly backdrop: 'canon-MenuBackdrop'; + readonly positioner: 'canon-MenuPositioner'; + readonly popup: 'canon-MenuPopup'; + readonly arrow: 'canon-MenuArrow'; + readonly item: 'canon-MenuItem'; + readonly group: 'canon-MenuGroup'; + readonly groupLabel: 'canon-MenuGroupLabel'; + readonly radioGroup: 'canon-MenuRadioGroup'; + readonly radioItem: 'canon-MenuRadioItem'; + readonly radioItemIndicator: 'canon-MenuRadioItemIndicator'; + readonly checkboxItem: 'canon-MenuCheckboxItem'; + readonly checkboxItemIndicator: 'canon-MenuCheckboxItemIndicator'; + readonly submenuTrigger: 'canon-MenuSubmenuTrigger'; + readonly separator: 'canon-MenuSeparator'; + }; + }; + readonly RadioGroup: { + readonly classNames: { + readonly root: 'canon-RadioGroup'; + readonly content: 'canon-RadioGroupContent'; + readonly radio: 'canon-Radio'; + }; + }; + readonly ScrollArea: { + readonly classNames: { + readonly root: 'canon-ScrollAreaRoot'; + readonly viewport: 'canon-ScrollAreaViewport'; + readonly scrollbar: 'canon-ScrollAreaScrollbar'; + readonly thumb: 'canon-ScrollAreaThumb'; + }; + }; + readonly SearchField: { + readonly classNames: { + readonly root: 'canon-SearchField'; + readonly clear: 'canon-InputClear'; + }; + }; + readonly Select: { + readonly classNames: { + readonly root: 'canon-Select'; + readonly required: 'canon-SelectRequired'; + readonly trigger: 'canon-SelectTrigger'; + readonly value: 'canon-SelectValue'; + readonly icon: 'canon-SelectIcon'; + readonly popup: 'canon-SelectPopup'; + readonly item: 'canon-SelectItem'; + readonly itemIndicator: 'canon-SelectItemIndicator'; + readonly itemText: 'canon-SelectItemText'; + readonly description: 'canon-SelectDescription'; + readonly error: 'canon-SelectError'; + }; + readonly dataAttributes: { + readonly size: readonly ['small', 'medium']; + }; + }; + readonly Switch: { + readonly classNames: { + readonly root: 'canon-Switch'; + readonly indicator: 'canon-SwitchIndicator'; + }; + }; + readonly Table: { + readonly classNames: { + readonly root: 'canon-TableRoot'; + readonly header: 'canon-TableHeader'; + readonly body: 'canon-TableBody'; + readonly row: 'canon-TableRow'; + readonly head: 'canon-TableHead'; + readonly caption: 'canon-TableCaption'; + readonly cell: 'canon-TableCell'; + readonly cellText: 'canon-TableCellText'; + readonly cellLink: 'canon-TableCellLink'; + readonly cellProfile: 'canon-TableCellProfile'; + readonly cellProfileAvatar: 'canon-TableCellProfileAvatar'; + readonly cellProfileAvatarImage: 'canon-TableCellProfileAvatarImage'; + readonly cellProfileAvatarFallback: 'canon-TableCellProfileAvatarFallback'; + readonly cellProfileName: 'canon-TableCellProfileName'; + readonly cellProfileLink: 'canon-TableCellProfileLink'; + }; + }; + readonly Tabs: { + readonly classNames: { + readonly root: 'canon-TabsRoot'; + readonly list: 'canon-TabsList'; + readonly indicator: 'canon-TabsIndicator'; + readonly tab: 'canon-TabsTab'; + readonly panel: 'canon-TabsPanel'; + }; + }; + readonly Text: { + readonly classNames: { + readonly root: 'canon-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: 'canon-TextField'; + readonly inputWrapper: 'canon-InputWrapper'; + readonly input: 'canon-Input'; + readonly inputIcon: 'canon-InputIcon'; + }; + readonly dataAttributes: { + readonly invalid: readonly [true, false]; + readonly disabled: readonly [true, false]; + }; + }; + readonly Header: { + readonly classNames: { + readonly toolbar: 'canon-HeaderToolbar'; + readonly toolbarWrapper: 'canon-HeaderToolbarWrapper'; + readonly toolbarContent: 'canon-HeaderToolbarContent'; + readonly toolbarOptions: 'canon-HeaderToolbarOptions'; + readonly toolbarIcon: 'canon-HeaderToolbarIcon'; + readonly toolbarName: 'canon-HeaderToolbarName'; + readonly breadcrumbs: 'canon-HeaderBreadcrumbs'; + readonly breadcrumb: 'canon-HeaderBreadcrumb'; + readonly breadcrumbLink: 'canon-HeaderBreadcrumbLink'; + readonly breadcrumbSeparator: 'canon-HeaderBreadcrumbSeparator'; + readonly tabs: 'canon-HeaderTabs'; + readonly tabList: 'canon-HeaderTabList'; + readonly tab: 'canon-HeaderTab'; + readonly tabActive: 'canon-HeaderTabActive'; + readonly tabHovered: 'canon-HeaderTabHovered'; + readonly subNav: 'canon-HeaderSubNav'; + }; + }; + readonly Tooltip: { + readonly classNames: { + readonly trigger: 'canon-TooltipTrigger'; + readonly positioner: 'canon-TooltipPositioner'; + readonly popup: 'canon-TooltipPopup'; + readonly arrow: 'canon-TooltipArrow'; + }; + }; +}; + // @public (undocumented) export const Container: ForwardRefExoticComponent< ContainerProps & RefAttributes @@ -261,6 +565,12 @@ export interface ContainerProps { style?: React.CSSProperties; } +// @public +export type DataAttributesMap = Record; + +// @public +export type DataAttributeValues = readonly (string | number | boolean)[]; + // @public export const DataTable: { Root: ( @@ -355,6 +665,20 @@ export type EnumPropDef = { required?: boolean; }; +// @public (undocumented) +export const FieldLabel: ForwardRefExoticComponent< + FieldLabelProps & RefAttributes +>; + +// @public (undocumented) +export interface FieldLabelProps { + description?: string | null; + htmlFor?: string; + id?: string; + label?: string | null; + secondaryLabel?: string | null; +} + // @public (undocumented) export const Flex: ForwardRefExoticComponent< FlexProps & RefAttributes @@ -612,26 +936,95 @@ export interface GridProps extends SpaceProps { style?: React.CSSProperties; } -// @public (undocumented) -export const Heading: ForwardRefExoticComponent< - Omit & RefAttributes ->; +// @public +export const Header: (props: HeaderProps) => JSX_2.Element; + +// @public +export interface HeaderBreadcrumb { + // (undocumented) + href: string; + // (undocumented) + label: string; +} + +// @public +export interface HeaderOption { + // (undocumented) + label: string; + // (undocumented) + onClick?: () => void; + // (undocumented) + value: string; +} + +// @public +export const HeaderPage: (props: HeaderPageProps) => JSX_2.Element; + +// @public +export interface HeaderPageOption { + // (undocumented) + label: string; + // (undocumented) + onClick?: () => void; + // (undocumented) + value: string; +} + +// @public +export interface HeaderPageProps { + // (undocumented) + description?: string; + // (undocumented) + options?: HeaderPageOption[]; + // (undocumented) + tabs?: HeaderPageTab[]; + // (undocumented) + title?: string; +} + +// @public +export interface HeaderPageTab { + // (undocumented) + href?: string; + // (undocumented) + label: string; +} + +// @public +export interface HeaderProps { + // (undocumented) + breadcrumbs?: HeaderBreadcrumb[]; + // (undocumented) + icon?: React.ReactNode; + // (undocumented) + options?: HeaderOption[]; + // (undocumented) + tabs?: HeaderTab[]; + // (undocumented) + title?: string; +} + +// @public +export interface HeaderTab { + // (undocumented) + href?: string; + // (undocumented) + label: string; +} // @public (undocumented) -export interface HeadingProps - extends Omit, 'color'> { - // (undocumented) - className?: string; - // (undocumented) - color?: - | 'primary' - | 'secondary' - | Partial>; - // (undocumented) - style?: React.CSSProperties; - // (undocumented) - truncate?: boolean; - // (undocumented) +export const Heading: { + ( + props: HeadingProps & { + ref?: React.ComponentPropsWithRef['ref']; + }, + ): React.ReactElement, T>; + displayName: string; +}; + +// @public (undocumented) +export type HeadingOwnProps = { + as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; variant?: | 'display' | 'title1' @@ -645,7 +1038,18 @@ export interface HeadingProps 'display' | 'title1' | 'title2' | 'title3' | 'title4' | 'title5' > >; -} + color?: + | 'primary' + | 'secondary' + | Partial>; + truncate?: boolean; + className?: string; + style?: React.CSSProperties; +}; + +// @public (undocumented) +export type HeadingProps = HeadingOwnProps & + Omit, keyof HeadingOwnProps>; // @public (undocumented) export const heightPropDefs: { @@ -675,40 +1079,6 @@ export type HeightProps = GetPropDefTypes; // @public (undocumented) export const Icon: (props: IconProps) => JSX_2.Element | null; -// @public (undocumented) -export const IconButton: ForwardRefExoticComponent< - IconButtonProps & RefAttributes ->; - -// @public (undocumented) -export type IconButtonOwnProps = GetPropDefTypes; - -// @public (undocumented) -export const iconButtonPropDefs: { - variant: { - type: 'enum'; - values: ('primary' | 'secondary')[]; - className: string; - default: 'primary'; - responsive: true; - }; - size: { - type: 'enum'; - values: ('small' | 'medium')[]; - className: string; - default: 'medium'; - responsive: true; - }; -}; - -// @public -export interface IconButtonProps - extends Omit, 'children'> { - icon: ReactElement; - size?: IconButtonOwnProps['size']; - variant?: IconButtonOwnProps['variant']; -} - // @public (undocumented) export const IconContext: Context; @@ -1020,6 +1390,27 @@ export type PositionProps = GetPropDefTypes; // @public (undocumented) export type PropDef = RegularPropDef | ResponsivePropDef; +// @public (undocumented) +export const Radio: ForwardRefExoticComponent< + RadioProps & RefAttributes +>; + +// @public (undocumented) +export const RadioGroup: ForwardRefExoticComponent< + RadioGroupProps & RefAttributes +>; + +// @public (undocumented) +export interface RadioGroupProps + extends Omit, + Omit { + // (undocumented) + children?: ReactNode; +} + +// @public (undocumented) +export interface RadioProps extends RadioProps_2 {} + // @public (undocumented) export type ReactNodePropDef = { type: 'ReactNode'; @@ -1066,6 +1457,20 @@ export const ScrollArea: { >; }; +// @public (undocumented) +export const SearchField: ForwardRefExoticComponent< + SearchFieldProps & RefAttributes +>; + +// @public (undocumented) +export interface SearchFieldProps + extends SearchFieldProps_2, + Omit { + icon?: ReactNode | false; + placeholder?: string; + size?: 'small' | 'medium' | Partial>; +} + // @public (undocumented) export const Select: ForwardRefExoticComponent< SelectProps & RefAttributes @@ -1161,6 +1566,16 @@ export type StylingPropDef = { parseValue?: (value: string) => string | undefined; }; +// @public (undocumented) +export const Switch: ForwardRefExoticComponent< + SwitchProps & RefAttributes +>; + +// @public (undocumented) +export interface SwitchProps extends SwitchProps_2 { + label?: string; +} + // @public export const Table: { Root: ForwardRefExoticComponent< @@ -1260,9 +1675,14 @@ export interface TabsRootWithoutOrientation > {} // @public (undocumented) -const Text_2: ForwardRefExoticComponent< - Omit & RefAttributes ->; +const Text_2: { + ( + props: TextProps & { + ref?: React.ComponentPropsWithRef['ref']; + }, + ): React.ReactElement, T>; + displayName: string; +}; export { Text_2 as Text }; // @public (undocumented) @@ -1272,23 +1692,23 @@ export const TextField: ForwardRefExoticComponent< // @public (undocumented) export interface TextFieldProps - extends Omit, 'size'> { - className?: string; - description?: string; - error?: string | null; + extends TextFieldProps_2, + Omit { icon?: ReactNode; - label?: string; - name: string; - onClear?: MouseEventHandler; + placeholder?: string; size?: 'small' | 'medium' | Partial>; } // @public (undocumented) -export interface TextProps - extends Omit, 'color'> { - // (undocumented) - className?: string; - // (undocumented) +export type TextOwnProps = { + as?: 'p' | 'span' | 'label'; + variant?: + | 'subtitle' + | 'body' + | 'caption' + | 'label' + | Partial>; + weight?: 'regular' | 'bold' | Partial>; color?: | 'primary' | 'secondary' @@ -1301,20 +1721,14 @@ export interface TextProps 'primary' | 'secondary' | 'danger' | 'warning' | 'success' > >; - // (undocumented) - style?: CSSProperties; - // (undocumented) truncate?: boolean; - // (undocumented) - variant?: - | 'subtitle' - | 'body' - | 'caption' - | 'label' - | Partial>; - // (undocumented) - weight?: 'regular' | 'bold' | Partial>; -} + className?: string; + style?: React.CSSProperties; +}; + +// @public (undocumented) +export type TextProps = TextOwnProps & + Omit, keyof TextOwnProps>; // @public (undocumented) export const Tooltip: { diff --git a/packages/canon/scripts/build-css.mjs b/packages/canon/scripts/build-css.mjs index e76f5138ba..245b3cf282 100644 --- a/packages/canon/scripts/build-css.mjs +++ b/packages/canon/scripts/build-css.mjs @@ -17,89 +17,55 @@ /* eslint-disable no-restricted-imports */ import { transform, bundle } from 'lightningcss'; import fs from 'fs'; -import path from 'path'; import chalk from 'chalk'; -import { glob } from 'glob'; /* eslint-enable no-restricted-imports */ -// Check if core.css and components.css exist -const cssDir = 'src/css'; +const srcFile = 'src/css/styles.css'; const distDir = 'css'; -const componentsDir = 'src/components'; +const distFile = `${distDir}/styles.css`; -// Core files -const cssFiles = [ - { path: `${cssDir}/core.css`, newName: 'core.css' }, - { path: `${cssDir}/components.css`, newName: 'components.css' }, - { path: `${cssDir}/styles.css`, newName: 'styles.css' }, -]; - -// Components files -const componentsFiles = glob - .sync('**/*.css', { cwd: componentsDir }) - .map(file => { - const folderName = file.split('/')[0].toLocaleLowerCase('en-US'); - return { path: `${componentsDir}/${file}`, newName: `${folderName}.css` }; - }); - -// Combine core and components files -cssFiles.push(...componentsFiles); - -// Check if files exist -cssFiles.forEach(file => { - if (!fs.existsSync(file.path)) { - console.error(`${file.originalName} does not exist`); - process.exit(1); - } -}); +// Check if styles.css exists +if (!fs.existsSync(srcFile)) { + console.error(`${srcFile} does not exist`); + process.exit(1); +} // Ensure the dist/css directory exists if (!fs.existsSync(distDir)) { fs.mkdirSync(distDir, { recursive: true }); } -// Add watch mode support const args = process.argv.slice(2); const watchMode = args.includes('--watch'); async function buildCSS(logs = true) { - // Bundle and transform files - cssFiles.forEach(file => { - let { code: bundleCode } = bundle({ - filename: file.path, - }); + const css = fs.readFileSync(srcFile); - let { code } = transform({ - filename: `${distDir}/${file.newName}`, - code: bundleCode, - }); - - fs.writeFileSync(`${distDir}/${file.newName}`, code); - - if (logs) { - console.log(chalk.blue('CSS bundled: ') + file.newName); - } + let { code: bundleCode } = bundle({ + filename: srcFile, }); + const { code } = transform({ + filename: distFile, + code: bundleCode, + minify: false, + }); + fs.writeFileSync(distFile, code); if (logs) { - console.log(chalk.green('CSS files bundled successfully!')); + console.log(chalk.blue('CSS transformed and minified: ') + 'styles.css'); + console.log(chalk.green('CSS file built successfully!')); } } if (watchMode) { - // Watch both directories for changes - [cssDir, componentsDir].forEach(dir => { - fs.watch(dir, { recursive: true }, (eventType, filename) => { - if (filename?.endsWith('.css')) { - console.log( - chalk.yellow(`Changes detected in ${filename}, rebuilding...`), - ); - buildCSS(false).catch(console.error); - } - }); + fs.watch('src/css', { recursive: true }, (eventType, filename) => { + if (filename === 'styles.css') { + console.log( + chalk.yellow(`Changes detected in ${filename}, rebuilding...`), + ); + buildCSS(false).catch(console.error); + } }); - - // Initial build buildCSS().catch(console.error); console.log(chalk.yellow('Watching for CSS changes...')); } else { diff --git a/packages/canon/src/components/Avatar/Avatar.tsx b/packages/canon/src/components/Avatar/Avatar.tsx index 472bec39fb..4e899170de 100644 --- a/packages/canon/src/components/Avatar/Avatar.tsx +++ b/packages/canon/src/components/Avatar/Avatar.tsx @@ -18,28 +18,36 @@ import { forwardRef, ElementRef } from 'react'; import { Avatar as AvatarPrimitive } from '@base-ui-components/react/avatar'; import clsx from 'clsx'; import { AvatarProps } from './types'; +import { useStyles } from '../../hooks/useStyles'; /** @public */ export const Avatar = forwardRef< ElementRef, AvatarProps ->(({ className, src, name, size = 'medium', ...props }, ref) => ( - - - - {(name || '') - .split(' ') - .map(word => word[0]) - .join('') - .toLocaleUpperCase('en-US') - .slice(0, 2)} - - -)); +>((props, ref) => { + const { className, src, name, size = 'medium', ...rest } = props; + const { classNames } = useStyles('Avatar', { + size, + }); + + return ( + + + + {(name || '') + .split(' ') + .map(word => word[0]) + .join('') + .toLocaleUpperCase('en-US') + .slice(0, 2)} + + + ); +}); Avatar.displayName = AvatarPrimitive.Root.displayName; diff --git a/packages/canon/src/components/Box/Box.tsx b/packages/canon/src/components/Box/Box.tsx index 8718c77724..4273ee86f9 100644 --- a/packages/canon/src/components/Box/Box.tsx +++ b/packages/canon/src/components/Box/Box.tsx @@ -24,6 +24,7 @@ import { widthPropDefs } from '../../props/width.props'; import { heightPropDefs } from '../../props/height.props'; import { positionPropDefs } from '../../props/position.props'; import { displayPropDefs } from '../../props/display.props'; +import { useStyles } from '../../hooks/useStyles'; /** @public */ export const Box = forwardRef((props, ref) => { @@ -38,11 +39,12 @@ export const Box = forwardRef((props, ref) => { ...boxPropDefs, }; + const { classNames } = useStyles('Box'); const { className, style } = extractProps(props, propDefs); return createElement(props.as || 'div', { ref, - className: clsx('canon-Box', className), + className: clsx(classNames.root, className), style, children, }); diff --git a/packages/canon/src/components/Button/Button.stories.tsx b/packages/canon/src/components/Button/Button.stories.tsx index fffc31b488..e020ebb64d 100644 --- a/packages/canon/src/components/Button/Button.stories.tsx +++ b/packages/canon/src/components/Button/Button.stories.tsx @@ -18,7 +18,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Button } from './Button'; import { Flex } from '../Flex'; import { Text } from '../Text'; -import { ButtonProps } from './types'; import { Icon } from '../Icon'; const meta = { @@ -34,15 +33,17 @@ const meta = { options: ['primary', 'secondary'], }, }, - args: { - size: 'medium', - variant: 'primary', - }, } satisfies Meta; export default meta; type Story = StoryObj; +export const Default: Story = { + args: { + children: 'Button', + }, +}; + export const Variants: Story = { args: { children: 'Button', @@ -72,12 +73,12 @@ export const Sizes: Story = { }, render: () => ( - + ), }; @@ -117,14 +118,14 @@ export const FullWidth: Story = { }; export const Disabled: Story = { - args: { - children: 'Button', - disabled: true, - }, - render: args => ( + render: () => ( - + ), }; @@ -143,7 +144,8 @@ export const Responsive: Story = { }, }; -const variants: string[] = ['primary', 'secondary']; +const variants = ['primary', 'secondary'] as const; +const sizes = ['small', 'medium'] as const; export const Playground: Story = { args: { @@ -154,25 +156,22 @@ export const Playground: Story = { {variants.map(variant => ( {variant} - {['small', 'medium'].map(size => ( + {sizes.map(size => ( - @@ -180,31 +179,27 @@ export const Playground: Story = { iconStart={} iconEnd={} style={{ width: '200px' }} - variant={variant as ButtonProps['variant']} - size={size as ButtonProps['size']} + variant={variant} + size={size} > Button - diff --git a/packages/canon/src/components/Button/Button.tsx b/packages/canon/src/components/Button/Button.tsx index ab70f168c8..40879e51ed 100644 --- a/packages/canon/src/components/Button/Button.tsx +++ b/packages/canon/src/components/Button/Button.tsx @@ -14,63 +14,43 @@ * limitations under the License. */ -import { forwardRef } from 'react'; import clsx from 'clsx'; -import { useResponsiveValue } from '../../hooks/useResponsiveValue'; - +import { forwardRef, Ref } from 'react'; +import { Button as RAButton } from 'react-aria-components'; import type { ButtonProps } from './types'; +import { useStyles } from '../../hooks/useStyles'; /** @public */ -export const Button = forwardRef( - (props: ButtonProps, ref) => { +export const Button = forwardRef( + (props: ButtonProps, ref: Ref) => { const { - size = 'medium', + size = 'small', variant = 'primary', - disabled, iconStart, iconEnd, children, className, - style, ...rest } = props; - // Get the responsive value for the variant - const responsiveSize = useResponsiveValue(size); - const responsiveVariant = useResponsiveValue(variant); + const { classNames, dataAttributes } = useStyles('Button', { + size, + variant, + }); return ( - + {iconEnd} + ); }, ); -export default Button; +Button.displayName = 'Button'; diff --git a/packages/canon/src/components/Button/index.ts b/packages/canon/src/components/Button/index.ts new file mode 100644 index 0000000000..b9c497ae1f --- /dev/null +++ b/packages/canon/src/components/Button/index.ts @@ -0,0 +1,18 @@ +/* + * 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 * from './Button'; +export * from './types'; diff --git a/packages/canon/src/components/Button/styles.css b/packages/canon/src/components/Button/styles.css index a4afd85c9b..a2274fd907 100644 --- a/packages/canon/src/components/Button/styles.css +++ b/packages/canon/src/components/Button/styles.css @@ -85,23 +85,21 @@ .canon-Button[data-size='medium'] { font-size: var(--canon-font-size-4); padding: 0 var(--canon-space-3); - height: 40px; + height: 2.5rem; } .canon-Button[data-size='small'] { font-size: var(--canon-font-size-3); padding: 0 var(--canon-space-2); - height: 32px; + height: 2rem; } -.canon-ButtonIcon[data-size='small'], -.canon-ButtonIcon[data-size='small'] svg { +.canon-Button[data-size='small'] svg { width: 1rem; height: 1rem; } -.canon-ButtonIcon[data-size='medium'], -.canon-ButtonIcon[data-size='medium'] svg { +.canon-Button[data-size='medium'] svg { width: 1.25rem; height: 1.25rem; } diff --git a/packages/canon/src/components/Button/types.ts b/packages/canon/src/components/Button/types.ts index 4ab62d5683..ad89dbfe50 100644 --- a/packages/canon/src/components/Button/types.ts +++ b/packages/canon/src/components/Button/types.ts @@ -14,40 +14,22 @@ * limitations under the License. */ -import type { ButtonOwnProps } from './Button.props'; -import { ReactElement } from 'react'; +import { Breakpoint } from '@backstage/canon'; +import { ReactElement, ReactNode } from 'react'; +import { ButtonProps as RAButtonProps } from 'react-aria-components'; /** * Properties for {@link Button} * * @public */ -export interface ButtonProps - extends Omit, 'children'> { - /** - * The size of the button - * @defaultValue 'medium' - */ - size?: ButtonOwnProps['size']; - - /** - * The visual variant of the button - * @defaultValue 'primary' - */ - variant?: ButtonOwnProps['variant']; - - /** - * The content of the button - */ - children: React.ReactNode; - - /** - * Optional icon to display at the start of the button - */ +export interface ButtonProps extends RAButtonProps { + size?: 'small' | 'medium' | Partial>; + variant?: + | 'primary' + | 'secondary' + | Partial>; iconStart?: ReactElement; - - /** - * Optional icon to display at the end of the button - */ iconEnd?: ReactElement; + children?: ReactNode; } diff --git a/packages/canon/src/components/IconButton/IconButton.stories.tsx b/packages/canon/src/components/ButtonIcon/ButtonIcon.stories.tsx similarity index 53% rename from packages/canon/src/components/IconButton/IconButton.stories.tsx rename to packages/canon/src/components/ButtonIcon/ButtonIcon.stories.tsx index d16dcd1fcb..c4c811eb92 100644 --- a/packages/canon/src/components/IconButton/IconButton.stories.tsx +++ b/packages/canon/src/components/ButtonIcon/ButtonIcon.stories.tsx @@ -15,15 +15,14 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import { IconButton } from './IconButton'; +import { ButtonIcon } from './ButtonIcon'; import { Flex } from '../Flex'; import { Text } from '../Text'; -import { IconButtonProps } from './types'; import { Icon } from '../Icon'; const meta = { - title: 'Components/IconButton', - component: IconButton, + title: 'Components/ButtonIcon', + component: ButtonIcon, argTypes: { size: { control: 'select', @@ -34,66 +33,44 @@ const meta = { options: ['primary', 'secondary'], }, }, - args: { - size: 'medium', - variant: 'primary', - }, -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; +export const Default: Story = { + render: () => } />, +}; + export const Variants: Story = { - args: { - icon: , - 'aria-label': 'Cloud icon button', - }, - parameters: { - argTypes: { - variant: { - control: false, - }, - }, - }, - render: args => ( - - - + render: () => ( + + } variant="primary" /> + } variant="secondary" /> ), }; export const Sizes: Story = { - args: { - icon: , - 'aria-label': 'Cloud icon button', - }, - render: args => ( - - - + render: () => ( + + } size="small" /> + } size="medium" /> ), }; export const Disabled: Story = { - args: { - icon: , - disabled: true, - 'aria-label': 'Cloud icon button', - }, - render: args => ( - - - + render: () => ( + + } variant="primary" /> + } variant="secondary" /> ), }; export const Responsive: Story = { args: { - icon: , - 'aria-label': 'Cloud icon button', variant: { initial: 'primary', sm: 'secondary', @@ -103,40 +80,39 @@ export const Responsive: Story = { sm: 'medium', }, }, + render: args => } />, }; -const variants: string[] = ['primary', 'secondary']; +const variants = ['primary', 'secondary'] as const; +const sizes = ['small', 'medium'] as const; export const Playground: Story = { - args: { - icon: , - 'aria-label': 'Cloud icon button', - }, render: args => ( {variants.map(variant => ( {variant} - {['small', 'medium'].map(size => ( + {sizes.map(size => ( - } /> - } aria-label="Chevron right icon button" - variant={variant as IconButtonProps['variant']} - size={size as IconButtonProps['size']} + variant={variant} + size={size} /> - } aria-label="Chevron right icon button" - variant={variant as IconButtonProps['variant']} - size={size as IconButtonProps['size']} + variant={variant} + size={size} /> ))} diff --git a/packages/canon/src/components/IconButton/IconButton.tsx b/packages/canon/src/components/ButtonIcon/ButtonIcon.tsx similarity index 51% rename from packages/canon/src/components/IconButton/IconButton.tsx rename to packages/canon/src/components/ButtonIcon/ButtonIcon.tsx index bca012cac0..072ed20963 100644 --- a/packages/canon/src/components/IconButton/IconButton.tsx +++ b/packages/canon/src/components/ButtonIcon/ButtonIcon.tsx @@ -14,17 +14,17 @@ * limitations under the License. */ -import { forwardRef } from 'react'; import clsx from 'clsx'; -import { useResponsiveValue } from '../../hooks/useResponsiveValue'; - -import type { IconButtonProps } from './types'; +import { forwardRef, Ref } from 'react'; +import { Button as RAButton } from 'react-aria-components'; +import type { ButtonIconProps } from './types'; +import { useStyles } from '../../hooks/useStyles'; /** @public */ -export const IconButton = forwardRef( - (props: IconButtonProps, ref) => { +export const ButtonIcon = forwardRef( + (props: ButtonIconProps, ref: Ref) => { const { - size = 'medium', + size = 'small', variant = 'primary', icon, className, @@ -32,28 +32,24 @@ export const IconButton = forwardRef( ...rest } = props; - const responsiveSize = useResponsiveValue(size); - const responsiveVariant = useResponsiveValue(variant); + const { classNames, dataAttributes } = useStyles('Button', { + size, + variant, + }); + + const { classNames: classNamesButtonIcon } = useStyles('ButtonIcon'); return ( - + {icon} + ); }, ); -export default IconButton; +ButtonIcon.displayName = 'ButtonIcon'; diff --git a/packages/canon/src/components/ButtonIcon/index.tsx b/packages/canon/src/components/ButtonIcon/index.tsx new file mode 100644 index 0000000000..686fd844e8 --- /dev/null +++ b/packages/canon/src/components/ButtonIcon/index.tsx @@ -0,0 +1,18 @@ +/* + * 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 * from './ButtonIcon'; +export * from './types'; diff --git a/packages/canon/src/components/IconButton/index.tsx b/packages/canon/src/components/ButtonIcon/styles.css similarity index 73% rename from packages/canon/src/components/IconButton/index.tsx rename to packages/canon/src/components/ButtonIcon/styles.css index 5f9943557e..27c96e696e 100644 --- a/packages/canon/src/components/IconButton/index.tsx +++ b/packages/canon/src/components/ButtonIcon/styles.css @@ -14,7 +14,17 @@ * limitations under the License. */ -export { IconButton } from './IconButton'; -export type { IconButtonProps } from './types'; -export { iconButtonPropDefs } from './IconButton.props'; -export type { IconButtonOwnProps } from './IconButton.props'; +.canon-ButtonIcon { + align-items: center; + justify-content: center; +} + +.canon-ButtonIcon[data-size='small'] { + padding: 0; + width: 2rem; +} + +.canon-ButtonIcon[data-size='medium'] { + padding: 0; + width: 2.5rem; +} diff --git a/packages/canon/src/components/IconButton/types.ts b/packages/canon/src/components/ButtonIcon/types.ts similarity index 56% rename from packages/canon/src/components/IconButton/types.ts rename to packages/canon/src/components/ButtonIcon/types.ts index ece1950d1b..7f8b845de4 100644 --- a/packages/canon/src/components/IconButton/types.ts +++ b/packages/canon/src/components/ButtonIcon/types.ts @@ -14,30 +14,20 @@ * limitations under the License. */ -import type { IconButtonOwnProps } from './IconButton.props'; +import { Breakpoint } from '@backstage/canon'; import { ReactElement } from 'react'; +import { ButtonProps as RAButtonProps } from 'react-aria-components'; /** - * Properties for {@link IconButton} + * Properties for {@link ButtonIcon} * * @public */ -export interface IconButtonProps - extends Omit, 'children'> { - /** - * The size of the button - * @defaultValue 'medium' - */ - size?: IconButtonOwnProps['size']; - - /** - * The visual variant of the button - * @defaultValue 'primary' - */ - variant?: IconButtonOwnProps['variant']; - - /** - * Icon to display in the button - */ - icon: ReactElement; +export interface ButtonIconProps extends RAButtonProps { + size?: 'small' | 'medium' | Partial>; + variant?: + | 'primary' + | 'secondary' + | Partial>; + icon?: ReactElement; } diff --git a/packages/canon/src/components/ButtonLink/ButtonLink.stories.tsx b/packages/canon/src/components/ButtonLink/ButtonLink.stories.tsx new file mode 100644 index 0000000000..abf6e9d278 --- /dev/null +++ b/packages/canon/src/components/ButtonLink/ButtonLink.stories.tsx @@ -0,0 +1,212 @@ +/* + * 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 { Meta, StoryObj } from '@storybook/react'; +import { ButtonLink } from './ButtonLink'; +import { Flex } from '../Flex'; +import { Text } from '../Text'; +import { Icon } from '../Icon'; + +const meta = { + title: 'Components/ButtonLink', + component: ButtonLink, + argTypes: { + size: { + control: 'select', + options: ['small', 'medium'], + }, + variant: { + control: 'select', + options: ['primary', 'secondary'], + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: 'Button', + }, +}; + +export const Variants: Story = { + render: () => ( + + } + variant="primary" + href="https://canon.backstage.io" + target="_blank" + > + Button + + } + variant="secondary" + href="https://canon.backstage.io" + target="_blank" + > + Button + + + ), +}; + +export const Sizes: Story = { + args: { + children: 'Button', + }, + render: () => ( + + }> + Small + + }> + Medium + + + ), +}; + +export const WithIcons: Story = { + args: { + children: 'Button', + }, + render: args => ( + + } /> + } /> + } + iconEnd={} + /> + + ), +}; + +export const FullWidth: Story = { + args: { + children: 'Button', + }, + render: args => ( + + } /> + } /> + } + iconEnd={} + /> + + ), +}; + +export const Disabled: Story = { + render: () => ( + + + Primary + + + Secondary + + + ), +}; + +export const Responsive: Story = { + args: { + children: 'Button', + variant: { + initial: 'primary', + sm: 'secondary', + }, + size: { + xs: 'small', + sm: 'medium', + }, + }, +}; + +const variants = ['primary', 'secondary'] as const; +const sizes = ['small', 'medium'] as const; + +export const Playground: Story = { + args: { + children: 'Button', + }, + render: () => ( + + {variants.map(variant => ( + + {variant} + {sizes.map(size => ( + + + Button + + } + variant={variant} + size={size} + > + Button + + } + variant={variant} + size={size} + > + Button + + } + iconEnd={} + style={{ width: '200px' }} + variant={variant} + size={size} + > + Button + + + Button + + } + variant={variant} + size={size} + isDisabled + > + Button + + } + variant={variant} + size={size} + isDisabled + > + Button + + + ))} + + ))} + + ), +}; diff --git a/packages/canon/src/components/ButtonLink/ButtonLink.tsx b/packages/canon/src/components/ButtonLink/ButtonLink.tsx new file mode 100644 index 0000000000..153643a530 --- /dev/null +++ b/packages/canon/src/components/ButtonLink/ButtonLink.tsx @@ -0,0 +1,58 @@ +/* + * 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 clsx from 'clsx'; +import { forwardRef, Ref } from 'react'; +import { Link as RALink } from 'react-aria-components'; +import type { ButtonLinkProps } from './types'; +import { useStyles } from '../../hooks/useStyles'; + +/** @public */ +export const ButtonLink = forwardRef( + (props: ButtonLinkProps, ref: Ref) => { + const { + size = 'small', + variant = 'primary', + iconStart, + iconEnd, + children, + className, + ...rest + } = props; + + const { classNames, dataAttributes } = useStyles('Button', { + size, + variant, + }); + + const { classNames: classNamesButtonLink } = useStyles('ButtonLink'); + + return ( + + {iconStart} + {children} + {iconEnd} + + ); + }, +); + +ButtonLink.displayName = 'ButtonLink'; diff --git a/packages/canon/src/components/ButtonLink/index.ts b/packages/canon/src/components/ButtonLink/index.ts new file mode 100644 index 0000000000..bbfc696c67 --- /dev/null +++ b/packages/canon/src/components/ButtonLink/index.ts @@ -0,0 +1,18 @@ +/* + * 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 * from './ButtonLink'; +export * from './types'; diff --git a/packages/canon/src/components/ButtonLink/types.ts b/packages/canon/src/components/ButtonLink/types.ts new file mode 100644 index 0000000000..f6524fbe62 --- /dev/null +++ b/packages/canon/src/components/ButtonLink/types.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 { Breakpoint } from '@backstage/canon'; +import { ReactElement, ReactNode } from 'react'; +import { LinkProps as RALinkProps } from 'react-aria-components'; + +/** + * Properties for {@link ButtonLink} + * + * @public + */ +export interface ButtonLinkProps extends RALinkProps { + size?: 'small' | 'medium' | Partial>; + variant?: + | 'primary' + | 'secondary' + | Partial>; + iconStart?: ReactElement; + iconEnd?: ReactElement; + children?: ReactNode; +} diff --git a/packages/canon/src/components/Checkbox/Checkbox.tsx b/packages/canon/src/components/Checkbox/Checkbox.tsx index 5bf6520891..aaa6fb105b 100644 --- a/packages/canon/src/components/Checkbox/Checkbox.tsx +++ b/packages/canon/src/components/Checkbox/Checkbox.tsx @@ -18,6 +18,7 @@ import { forwardRef } from 'react'; import { Checkbox as CheckboxPrimitive } from '@base-ui-components/react/checkbox'; import { Icon } from '@backstage/canon'; import type { CheckboxProps } from './types'; +import { useStyles } from '../../hooks/useStyles'; import clsx from 'clsx'; /** @public */ @@ -35,10 +36,12 @@ export const Checkbox = forwardRef( style, } = props; + const { classNames } = useStyles('Checkbox'); + const checkboxElement = ( ( value={value} style={style} > - + ); return label ? ( -
{`${fromCount} - ${toCount} of ${rowCount}`} - table?.previousPage()} - disabled={!table?.getCanPreviousPage()} + isDisabled={!table?.getCanPreviousPage()} icon={} /> - table?.nextPage()} - disabled={!table?.getCanNextPage()} + isDisabled={!table?.getCanNextPage()} icon={} />
diff --git a/packages/canon/src/components/FieldError/FieldError.stories.tsx b/packages/canon/src/components/FieldError/FieldError.stories.tsx new file mode 100644 index 0000000000..39714d16d2 --- /dev/null +++ b/packages/canon/src/components/FieldError/FieldError.stories.tsx @@ -0,0 +1,87 @@ +/* + * 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 { Meta, StoryObj } from '@storybook/react'; +import { TextField, Input, Form } from 'react-aria-components'; +import { FieldError } from './FieldError'; + +const meta = { + title: 'Forms/FieldError', + component: FieldError, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// Show error with server validation using Form component +export const WithServerValidation: Story = { + render: () => ( +
+ + + + +
+ ), +}; + +// Show error using children +export const WithCustomMessage: Story = { + render: () => ( + + + This is a custom error message. + + ), +}; + +// Show error with render prop function +export const WithRenderProp: Story = { + render: () => ( + 'This field is invalid'} + style={{ + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + }} + > + + + {({ validationErrors }) => + validationErrors.length > 0 ? validationErrors[0] : 'Field is invalid' + } + + + ), +}; diff --git a/packages/canon/src/components/FieldError/FieldError.styles.css b/packages/canon/src/components/FieldError/FieldError.styles.css new file mode 100644 index 0000000000..816eb3c35e --- /dev/null +++ b/packages/canon/src/components/FieldError/FieldError.styles.css @@ -0,0 +1,6 @@ +.canon-FieldError { + color: var(--canon-fg-danger); + font-size: var(--canon-font-size-2); + font-weight: var(--canon-font-weight-regular); + margin-top: var(--canon-space-2); +} diff --git a/packages/canon/src/components/Button/Button.props.ts b/packages/canon/src/components/FieldError/FieldError.tsx similarity index 51% rename from packages/canon/src/components/Button/Button.props.ts rename to packages/canon/src/components/FieldError/FieldError.tsx index e363360afa..b90d7b3bd3 100644 --- a/packages/canon/src/components/Button/Button.props.ts +++ b/packages/canon/src/components/FieldError/FieldError.tsx @@ -14,28 +14,26 @@ * limitations under the License. */ -import type { PropDef, GetPropDefTypes } from '../../props/prop-def'; +import { forwardRef } from 'react'; +import { + FieldError as AriaFieldError, + type FieldErrorProps, +} from 'react-aria-components'; +import clsx from 'clsx'; /** @public */ -export const buttonPropDefs = { - variant: { - type: 'enum', - values: ['primary', 'secondary'], - className: 'canon-Button--variant', - default: 'primary', - responsive: true, - }, - size: { - type: 'enum', - values: ['small', 'medium'], - className: 'canon-Button--size', - default: 'medium', - responsive: true, - }, -} satisfies { - variant: PropDef<'primary' | 'secondary'>; - size: PropDef<'small' | 'medium'>; -}; +export const FieldError = forwardRef( + (props: FieldErrorProps, ref) => { + const { className, ...rest } = props; -/** @public */ -export type ButtonOwnProps = GetPropDefTypes; + return ( + + ); + }, +); + +FieldError.displayName = 'FieldError'; diff --git a/plugins/scaffolder-backend/src/lib/index.ts b/packages/canon/src/components/FieldError/index.ts similarity index 88% rename from plugins/scaffolder-backend/src/lib/index.ts rename to packages/canon/src/components/FieldError/index.ts index 20096f9c03..5b61f83ace 100644 --- a/plugins/scaffolder-backend/src/lib/index.ts +++ b/packages/canon/src/components/FieldError/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Backstage Authors + * 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. @@ -14,4 +14,4 @@ * limitations under the License. */ -export * from './templating'; +export * from './FieldError'; diff --git a/packages/canon/src/components/FieldLabel/FieldLabel.stories.tsx b/packages/canon/src/components/FieldLabel/FieldLabel.stories.tsx new file mode 100644 index 0000000000..a82639eca0 --- /dev/null +++ b/packages/canon/src/components/FieldLabel/FieldLabel.stories.tsx @@ -0,0 +1,65 @@ +/* + * 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 { Meta, StoryObj } from '@storybook/react'; +import { FieldLabel } from './FieldLabel'; + +const meta = { + title: 'Forms/FieldLabel', + component: FieldLabel, + argTypes: { + label: { + control: 'text', + }, + secondaryLabel: { + control: 'text', + }, + description: { + control: 'text', + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + label: 'Label', + }, +}; + +export const WithSecondaryLabel: Story = { + args: { + ...Default.args, + secondaryLabel: 'Secondary Label', + }, +}; + +export const WithDescription: Story = { + args: { + ...Default.args, + description: 'Description', + }, +}; + +export const WithAllFields: Story = { + args: { + ...Default.args, + secondaryLabel: 'Secondary Label', + description: 'Description', + }, +}; diff --git a/packages/canon/src/components/FieldLabel/FieldLabel.styles.css b/packages/canon/src/components/FieldLabel/FieldLabel.styles.css new file mode 100644 index 0000000000..f668d2fd45 --- /dev/null +++ b/packages/canon/src/components/FieldLabel/FieldLabel.styles.css @@ -0,0 +1,27 @@ +.canon-FieldLabelWrapper { + display: flex; + flex-direction: column; + margin-bottom: var(--canon-space-3); + gap: var(--canon-space-1); +} + +.canon-FieldLabel { + color: var(--canon-fg-primary); + margin-right: auto; + cursor: pointer; + font-weight: var(--canon-font-weight-regular); + font-size: var(--canon-font-size-2); +} + +.canon-FieldSecondaryLabel { + color: var(--canon-fg-secondary); + font-weight: var(--canon-font-weight-regular); + margin-left: var(--canon-space-1); +} + +.canon-FieldDescription { + font-weight: var(--canon-font-weight-regular); + font-size: var(--canon-font-size-2); + color: var(--canon-fg-secondary); + margin: 0; +} diff --git a/packages/canon/src/components/FieldLabel/FieldLabel.tsx b/packages/canon/src/components/FieldLabel/FieldLabel.tsx new file mode 100644 index 0000000000..df0735389a --- /dev/null +++ b/packages/canon/src/components/FieldLabel/FieldLabel.tsx @@ -0,0 +1,50 @@ +/* + * Copyright 2025 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 { Label } from 'react-aria-components'; +import { forwardRef } from 'react'; +import type { FieldLabelProps } from './types'; +import { useStyles } from '../../hooks/useStyles'; + +/** @public */ +export const FieldLabel = forwardRef( + (props: FieldLabelProps, ref) => { + const { label, secondaryLabel, description, htmlFor, id, ...rest } = props; + + const { classNames } = useStyles('FieldLabel'); + + if (!label) return null; + + return ( +
+ {label && ( + + )} + {description && ( +
{description}
+ )} +
+ ); + }, +); + +FieldLabel.displayName = 'FieldLabel'; diff --git a/packages/canon/src/components/FieldLabel/index.ts b/packages/canon/src/components/FieldLabel/index.ts new file mode 100644 index 0000000000..b9cebb1bf7 --- /dev/null +++ b/packages/canon/src/components/FieldLabel/index.ts @@ -0,0 +1,18 @@ +/* + * 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 * from './FieldLabel'; +export * from './types'; diff --git a/packages/canon/src/components/FieldLabel/types.ts b/packages/canon/src/components/FieldLabel/types.ts new file mode 100644 index 0000000000..dc4e444133 --- /dev/null +++ b/packages/canon/src/components/FieldLabel/types.ts @@ -0,0 +1,43 @@ +/* + * Copyright 2025 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. + */ + +/** @public */ +export interface FieldLabelProps { + /** + * The label of the text field + */ + label?: string | null; + + /** + * The secondary label of the text field + */ + secondaryLabel?: string | null; + + /** + * The description of the text field + */ + description?: string | null; + + /** + * The HTML for attribute of the text field + */ + htmlFor?: string; + + /** + * The id of the text field + */ + id?: string; +} diff --git a/packages/canon/src/components/Flex/Flex.stories.tsx b/packages/canon/src/components/Flex/Flex.stories.tsx index 91b8dc8fb6..30c527a117 100644 --- a/packages/canon/src/components/Flex/Flex.stories.tsx +++ b/packages/canon/src/components/Flex/Flex.stories.tsx @@ -16,6 +16,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { Flex } from './Flex'; +import { Text } from '../Text'; const meta = { title: 'Layout/Flex', @@ -143,3 +144,24 @@ export const LargeGap: Story = { ), }; + +export const WithTextTruncate: Story = { + render: () => ( + + + + A man looks at a painting in a museum and says, “Brothers and sisters + I have none, but that man's father is my father's son.” Who + is in the painting? + + + + + A man looks at a painting in a museum and says, “Brothers and sisters + I have none, but that man's father is my father's son.” Who + is in the painting? + + + + ), +}; diff --git a/packages/canon/src/components/Flex/Flex.tsx b/packages/canon/src/components/Flex/Flex.tsx index a53e0d28f4..ded4fffffa 100644 --- a/packages/canon/src/components/Flex/Flex.tsx +++ b/packages/canon/src/components/Flex/Flex.tsx @@ -21,6 +21,7 @@ import { flexPropDefs } from './Flex.props'; import { extractProps } from '../../utils/extractProps'; import { gapPropDefs } from '../../props/gap-props'; import { spacingPropDefs } from '../../props/spacing.props'; +import { useStyles } from '../../hooks/useStyles'; /** @public */ export const Flex = forwardRef((props, ref) => { @@ -30,11 +31,12 @@ export const Flex = forwardRef((props, ref) => { ...spacingPropDefs, }; + const { classNames } = useStyles('Flex'); const { className, style } = extractProps(props, propDefs); return createElement('div', { ref, - className: clsx('canon-Flex', className), + className: clsx(classNames.root, className), style, children: props.children, }); diff --git a/packages/canon/src/components/Flex/styles.css b/packages/canon/src/components/Flex/styles.css index 094edffca7..61fb53d257 100644 --- a/packages/canon/src/components/Flex/styles.css +++ b/packages/canon/src/components/Flex/styles.css @@ -16,4 +16,7 @@ .canon-Flex { display: flex; + + /* This helps when using `truncate` on text inside a flex container */ + min-width: 0; } diff --git a/packages/canon/src/components/Grid/Grid.tsx b/packages/canon/src/components/Grid/Grid.tsx index 7bb5486a2d..27257c8972 100644 --- a/packages/canon/src/components/Grid/Grid.tsx +++ b/packages/canon/src/components/Grid/Grid.tsx @@ -21,6 +21,7 @@ import { gridItemPropDefs, gridPropDefs } from './Grid.props'; import clsx from 'clsx'; import type { GridItemProps, GridProps } from './types'; import { spacingPropDefs } from '../../props/spacing.props'; +import { useStyles } from '../../hooks/useStyles'; const GridRoot = forwardRef((props, ref) => { const propDefs = { @@ -29,11 +30,13 @@ const GridRoot = forwardRef((props, ref) => { ...spacingPropDefs, }; + const { classNames } = useStyles('Grid'); + const { className, style } = extractProps(props, propDefs); return createElement('div', { ref, - className: clsx('canon-Grid', className), + className: clsx(classNames.root, className), style, children: props.children, }); @@ -44,11 +47,12 @@ const GridItem = forwardRef((props, ref) => { ...gridItemPropDefs, }; + const { classNames } = useStyles('Grid'); const { className, style } = extractProps(props, propDefs); return createElement('div', { ref, - className: clsx('canon-GridItem', className), + className: clsx(classNames.item, className), style, children: props.children, }); diff --git a/packages/canon/src/components/Header/Header.stories.tsx b/packages/canon/src/components/Header/Header.stories.tsx new file mode 100644 index 0000000000..0554648bc9 --- /dev/null +++ b/packages/canon/src/components/Header/Header.stories.tsx @@ -0,0 +1,155 @@ +/* + * 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 { Meta, StoryObj, StoryFn } from '@storybook/react'; +import { Header } from './Header'; +import { HeaderBreadcrumb, HeaderOption, HeaderTab } from './types'; + +const meta = { + title: 'Components/Header', + component: Header, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const tabs: HeaderTab[] = [ + { + label: 'Overview', + }, + { + label: 'Checks', + }, + { + label: 'Tracks', + }, + { + label: 'Campaigns', + }, + { + label: 'Integrations', + }, +]; + +const breadcrumbs: HeaderBreadcrumb[] = [ + { + label: 'Home', + href: '/', + }, + { + label: 'Dashboard', + href: '/dashboard', + }, + { + label: 'Settings', + href: '/settings', + }, +]; + +const options: HeaderOption[] = [ + { + label: 'Settings', + value: 'settings', + }, + { + label: 'Invite new members', + value: 'invite-new-members', + }, +]; + +// Extract layout decorator as a reusable constant +const layoutDecorator = [ + (Story: StoryFn) => ( + <> +
+
+ +
+
+ + ), +]; + +export const Default: Story = { + args: {}, +}; + +export const WithTabs: Story = { + args: { + tabs, + }, +}; + +export const WithOptions: Story = { + args: { + options, + }, +}; + +export const WithBreadcrumbs: Story = { + args: { + breadcrumbs, + }, +}; + +export const WithAllComponents: Story = { + args: { + options, + tabs, + breadcrumbs, + }, +}; + +export const WithLayout: Story = { + args: { + options, + tabs, + breadcrumbs, + }, + decorators: layoutDecorator, + parameters: { + layout: 'fullscreen', + }, +}; diff --git a/packages/canon/src/components/Header/Header.styles.css b/packages/canon/src/components/Header/Header.styles.css new file mode 100644 index 0000000000..76b7c6bcf4 --- /dev/null +++ b/packages/canon/src/components/Header/Header.styles.css @@ -0,0 +1,193 @@ +/* + * 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. + */ + +.canon-HeaderToolbar { + position: sticky; + top: 0; + z-index: 10; + padding-top: 8px; + + &::before { + content: ''; + position: absolute; + top: 0; + left: 0px; + right: 0px; + height: 16px; + background-color: var(--canon-bg); + z-index: 0; + } +} + +.canon-HeaderToolbarWrapper { + position: relative; + z-index: 1; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + background-color: var(--canon-bg-surface-1); + padding-inline: var(--canon-space-3); + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + color: var(--canon-fg-primary); + height: 52px; +} + +.canon-HeaderToolbarContent { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--canon-space-2); +} + +.canon-HeaderToolbarName { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--canon-space-2); + font-size: var(--canon-font-size-3); + font-weight: var(--canon-font-weight-regular); + flex-shrink: 0; +} + +.canon-HeaderToolbarIcon { + width: 16px; + height: 16px; + color: var(--canon-fg-primary); + + & svg { + width: 100%; + height: 100%; + } +} + +.canon-HeaderToolbarOptions { + position: absolute; + right: var(--canon-space-2); + top: 50%; + transform: translateY(-50%); +} + +.canon-HeaderBreadcrumbs { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--canon-space-2); + font-size: var(--canon-font-size-3); + font-weight: var(--canon-font-weight-regular); +} + +.canon-HeaderBreadcrumb { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--canon-space-2); +} + +.canon-HeaderBreadcrumbLink { + color: var(--canon-fg-secondary); + text-decoration: none; + cursor: pointer; + + &[data-active='true'] { + color: var(--canon-fg-primary); + } +} + +.canon-HeaderBreadcrumbSeparator { + width: 16px; + height: 16px; + color: var(--canon-fg-secondary); +} + +.canon-HeaderTabs { + display: flex; + flex-direction: row; + align-items: center; + background-color: var(--canon-bg-surface-1); + position: relative; + padding-inline: var(--canon-space-1); + border-radius: var(--canon-radius-2); + border: 1px solid var(--canon-border); + margin-top: 8px; + + /* Initialize CSS variables */ + --active-tab-left: 0px; + --active-tab-right: 0px; + --active-tab-top: 0px; + --active-tab-bottom: 0px; + --active-tab-width: 0px; + --active-tab-height: 0px; + + --hovered-tab-left: 0px; + --hovered-tab-right: 0px; + --hovered-tab-top: 0px; + --hovered-tab-bottom: 0px; + --hovered-tab-width: 0px; + --hovered-tab-height: 0px; + --hovered-tab-opacity: 0; + --hovered-transition-duration: 0s; +} + +.canon-HeaderTabList { + display: flex; + flex-direction: row; +} + +.canon-HeaderTab { + font-size: var(--canon-font-size-3); + color: var(--canon-fg-primary); + height: 36px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + position: relative; + z-index: 2; + padding-inline: var(--canon-space-2); +} + +/* Active tab indicator */ +.canon-HeaderTabActive { + content: ''; + position: absolute; + left: calc(var(--active-tab-left) + var(--canon-space-2)); + bottom: -1px; + width: calc(var(--active-tab-width) - var(--canon-space-4)); + height: 1px; + background-color: var(--canon-fg-primary); + border-radius: 4px; + transition: all 0.25s ease-out; + opacity: 1; +} + +/* Hovered tab indicator */ +.canon-HeaderTabHovered { + content: ''; + position: absolute; + left: var(--hovered-tab-left); + top: calc(var(--hovered-tab-top) + 4px); + width: var(--hovered-tab-width); + height: calc(var(--hovered-tab-height) - 8px); + background-color: var(--canon-gray-2); + border-radius: 4px; + opacity: var(--hovered-tab-opacity); + transition: left var(--hovered-transition-duration) ease-out, + top var(--hovered-transition-duration) ease-out, + width var(--hovered-transition-duration) ease-out, + height var(--hovered-transition-duration) ease-out, opacity 0.15s ease-out; +} diff --git a/packages/cli/src/modules/info/alpha.ts b/packages/canon/src/components/Header/Header.tsx similarity index 54% rename from packages/cli/src/modules/info/alpha.ts rename to packages/canon/src/components/Header/Header.tsx index 1e6f761f83..9d7e65a6d1 100644 --- a/packages/cli/src/modules/info/alpha.ts +++ b/packages/canon/src/components/Header/Header.tsx @@ -13,21 +13,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import yargs from 'yargs'; -import { createCliPlugin } from '../../wiring/factory'; -export default createCliPlugin({ - pluginId: 'info', - init: async reg => { - reg.addCommand({ - path: ['info'], - description: 'Show helpful information for debugging and reporting bugs', - execute: async ({ args }) => { - yargs().parse(args); - const { default: command } = - require('./commands/info') as typeof import('./commands/info'); - await command(); - }, - }); - }, -}); +import type { HeaderProps } from './types'; +import { HeaderToolbar } from './HeaderToolbar'; +import { HeaderTabs } from './HeaderTabs'; + +/** + * A component that renders a toolbar. + * + * @public + */ +export const Header = (props: HeaderProps) => { + const { tabs, icon, title, options, breadcrumbs } = props; + + return ( + <> + + + + ); +}; diff --git a/packages/canon/src/components/Header/HeaderTabs.tsx b/packages/canon/src/components/Header/HeaderTabs.tsx new file mode 100644 index 0000000000..b83e27e83d --- /dev/null +++ b/packages/canon/src/components/Header/HeaderTabs.tsx @@ -0,0 +1,92 @@ +/* + * 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 { Tabs, TabList, Tab as AriaTab } from 'react-aria-components'; +import { useStyles } from '../../hooks/useStyles'; +import { useId, useRef, useState } from 'react'; +import { HeaderTabsIndicators } from './HeaderTabsIndicators'; +import type { HeaderProps, HeaderTabProps } from './types'; + +/** + * A component that renders header tabs. + * + * @internal + */ +export const HeaderTabs = (props: HeaderProps) => { + const { tabs } = props; + const { classNames } = useStyles('Header'); + const tabsRef = useRef(null); + const tabRefs = useRef>(new Map()); + const [hoveredKey, setHoveredKey] = useState(null); + const prevHoveredKey = useRef(null); + + const setTabRef = (key: string, element: HTMLDivElement | null) => { + if (element) { + tabRefs.current.set(key, element); + } else { + tabRefs.current.delete(key); + } + }; + + if (!tabs) return null; + + return ( + + + {tabs.map((tab, index) => { + return ( + + ); + })} + + + + ); +}; + +/** + * A component that renders a toolbar tab. + * + * @internal + */ +const Tab = (props: HeaderTabProps) => { + const { tab, setTabRef, setHoveredKey } = props; + const id = useId(); + const { classNames } = useStyles('Header'); + + return ( + setTabRef(id, el as HTMLDivElement)} + onHoverStart={() => setHoveredKey(id)} + onHoverEnd={() => setHoveredKey(null)} + href={tab.href} + > + {tab.label} + + ); +}; diff --git a/packages/canon/src/components/Header/HeaderTabsIndicators.tsx b/packages/canon/src/components/Header/HeaderTabsIndicators.tsx new file mode 100644 index 0000000000..41de56574e --- /dev/null +++ b/packages/canon/src/components/Header/HeaderTabsIndicators.tsx @@ -0,0 +1,161 @@ +/* + * 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 { TabListStateContext } from 'react-aria-components'; +import { useStyles } from '../../hooks/useStyles'; +import { useContext, useEffect, useCallback } from 'react'; +import type { HeaderIndicatorsProps } from './types'; + +/** + * A component that renders the indicators for the toolbar. + * + * @internal + */ +export const HeaderTabsIndicators = (props: HeaderIndicatorsProps) => { + const { tabRefs, tabsRef, hoveredKey, prevHoveredKey } = props; + const { classNames } = useStyles('Header'); + const state = useContext(TabListStateContext); + + const updateCSSVariables = useCallback(() => { + if (!tabsRef.current) return; + + const tabsRect = tabsRef.current.getBoundingClientRect(); + + // Set active tab variables + if (state?.selectedKey) { + const activeTab = tabRefs.current.get(state.selectedKey.toString()); + + if (activeTab) { + const activeRect = activeTab.getBoundingClientRect(); + const relativeLeft = activeRect.left - tabsRect.left; + const relativeTop = activeRect.top - tabsRect.top; + + tabsRef.current.style.setProperty( + '--active-tab-left', + `${relativeLeft}px`, + ); + tabsRef.current.style.setProperty( + '--active-tab-right', + `${relativeLeft + activeRect.width}px`, + ); + tabsRef.current.style.setProperty( + '--active-tab-top', + `${relativeTop}px`, + ); + tabsRef.current.style.setProperty( + '--active-tab-bottom', + `${relativeTop + activeRect.height}px`, + ); + tabsRef.current.style.setProperty( + '--active-tab-width', + `${activeRect.width}px`, + ); + tabsRef.current.style.setProperty( + '--active-tab-height', + `${activeRect.height}px`, + ); + } + } + + // Set hovered tab variables + if (hoveredKey) { + const hoveredTab = tabRefs.current.get(hoveredKey); + if (hoveredTab) { + const hoveredRect = hoveredTab.getBoundingClientRect(); + const relativeLeft = hoveredRect.left - tabsRect.left; + const relativeTop = hoveredRect.top - tabsRect.top; + + tabsRef.current.style.setProperty( + '--hovered-tab-left', + `${relativeLeft}px`, + ); + tabsRef.current.style.setProperty( + '--hovered-tab-right', + `${relativeLeft + hoveredRect.width}px`, + ); + tabsRef.current.style.setProperty( + '--hovered-tab-top', + `${relativeTop}px`, + ); + tabsRef.current.style.setProperty( + '--hovered-tab-bottom', + `${relativeTop + hoveredRect.height}px`, + ); + tabsRef.current.style.setProperty( + '--hovered-tab-width', + `${hoveredRect.width}px`, + ); + tabsRef.current.style.setProperty( + '--hovered-tab-height', + `${hoveredRect.height}px`, + ); + // Control transition timing based on whether this is a new hover session + const isNewHoverSession = prevHoveredKey.current === null; + + if (isNewHoverSession) { + // Starting new hover session: no transitions for position + tabsRef.current.style.setProperty( + '--hovered-transition-duration', + '0s', + ); + // Enable transitions on next frame for future tab switches + requestAnimationFrame(() => { + if (tabsRef.current) { + tabsRef.current.style.setProperty( + '--hovered-transition-duration', + '0.2s', + ); + } + }); + } else { + // Moving between tabs in same session: full transitions + tabsRef.current.style.setProperty( + '--hovered-transition-duration', + '0.2s', + ); + } + + // Update previous hover key for next time + prevHoveredKey.current = hoveredKey; + + tabsRef.current.style.setProperty('--hovered-tab-opacity', '1'); + } + } else { + // When not hovering, hide with opacity and reset for next hover session + tabsRef.current.style.setProperty('--hovered-tab-opacity', '0'); + + // Reset previous hover key so next hover is treated as new session + prevHoveredKey.current = null; + } + }, [state?.selectedKey, hoveredKey]); + + useEffect(() => { + updateCSSVariables(); + }, [updateCSSVariables]); + + useEffect(() => { + const handleResize = () => updateCSSVariables(); + window.addEventListener('resize', handleResize); + return () => window.removeEventListener('resize', handleResize); + }, [updateCSSVariables]); + + return ( + <> +
+
+ + ); +}; diff --git a/packages/canon/src/components/Header/HeaderToolbar.tsx b/packages/canon/src/components/Header/HeaderToolbar.tsx new file mode 100644 index 0000000000..95c01e1c88 --- /dev/null +++ b/packages/canon/src/components/Header/HeaderToolbar.tsx @@ -0,0 +1,164 @@ +/* + * 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 { Link } from 'react-aria-components'; +import { useStyles } from '../../hooks/useStyles'; +import { useRef, useState, useEffect } from 'react'; +import { RiArrowRightSLine, RiMore2Line, RiShapesLine } from '@remixicon/react'; +import type { HeaderProps } from './types'; +import { ButtonIcon } from '../ButtonIcon'; +import { Menu } from '../Menu'; +import { motion, useScroll, useTransform } from 'motion/react'; + +/** + * A component that renders a toolbar. + * + * @internal + */ +export const HeaderToolbar = (props: HeaderProps) => { + const { icon, title, options, breadcrumbs } = props; + const { classNames } = useStyles('Header'); + + const { scrollY } = useScroll(); + const breadcrumbOpacity = useTransform(scrollY, [80, 120], [0, 1]); + + // Refs for collision detection + const toolbarWrapperRef = useRef(null); + const toolbarContentRef = useRef(null); + const toolbarOptionsRef = useRef(null); + + // State for breadcrumb visibility + const [showBreadcrumbs, setShowBreadcrumbs] = useState(true); + + // Set up resize observer + useEffect(() => { + const wrapper = toolbarWrapperRef.current; + if (!wrapper) return; + + const resizeObserver = new ResizeObserver(() => { + const wrapper = toolbarWrapperRef.current; + const content = toolbarContentRef.current; + const options = toolbarOptionsRef.current; + + if (!wrapper || !content) return; + + // Get dimensions + const wrapperRect = wrapper.getBoundingClientRect(); + const wrapperWidth = wrapperRect.width; + const wrapperPadding = 24; // 12px on each side (var(--canon-space-3)) + const availableWidth = wrapperWidth - wrapperPadding; + + // Calculate required width for content + const contentRect = content.getBoundingClientRect(); + const contentWidth = contentRect?.width || 0; + + // Calculate options width (if exists) + const optionsRect = options?.getBoundingClientRect(); + const optionsWidth = optionsRect?.width || 0; + + // Check if we need to hide breadcrumbs + const shouldShowBreadcrumbs = + contentWidth + optionsWidth + 32 <= availableWidth; + + // Only update state if the value actually changed to prevent flickering + setShowBreadcrumbs(prev => + prev !== shouldShowBreadcrumbs ? shouldShowBreadcrumbs : prev, + ); + }); + + resizeObserver.observe(wrapper); + + return () => { + resizeObserver.disconnect(); + }; + }, []); + + return ( +
+
+
+
+
+ {icon || } +
+ {title || 'Your plugin'} +
+ {breadcrumbs && ( + + + {breadcrumbs.map((breadcrumb, index) => ( +
+ + {breadcrumb.label} + + {index < breadcrumbs.length - 1 && ( + + )} +
+ ))} +
+ )} +
+
+ {options && ( + + ( + } + variant="secondary" + /> + )} + /> + + + + {options.map(option => ( + option.onClick?.()} + > + {option.label} + + ))} + + + + + )} +
+
+
+ ); +}; diff --git a/packages/canon/src/components/Button/index.tsx b/packages/canon/src/components/Header/index.tsx similarity index 76% rename from packages/canon/src/components/Button/index.tsx rename to packages/canon/src/components/Header/index.tsx index 9051f1145e..ac55e27fa1 100644 --- a/packages/canon/src/components/Button/index.tsx +++ b/packages/canon/src/components/Header/index.tsx @@ -13,7 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { Button } from './Button'; -export type { ButtonProps } from './types'; -export { buttonPropDefs } from './Button.props'; -export type { ButtonOwnProps } from './Button.props'; + +export { Header } from './Header'; +export type { + HeaderProps, + HeaderTab, + HeaderOption, + HeaderBreadcrumb, +} from './types'; diff --git a/packages/canon/src/components/Header/types.ts b/packages/canon/src/components/Header/types.ts new file mode 100644 index 0000000000..6cdd51b7d6 --- /dev/null +++ b/packages/canon/src/components/Header/types.ts @@ -0,0 +1,79 @@ +/* + * 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 { MutableRefObject } from 'react'; + +/** + * Props for the main Header component. + * + * @public + */ +export interface HeaderProps { + icon?: React.ReactNode; + title?: string; + tabs?: HeaderTab[]; + options?: HeaderOption[]; + breadcrumbs?: HeaderBreadcrumb[]; +} + +/** + * Represents a tab item in the header navigation. + * + * @public + */ +export interface HeaderTab { + label: string; + href?: string; +} + +/** + * Represents an option item in the header dropdown menu. + * + * @public + */ +export interface HeaderOption { + label: string; + value: string; + onClick?: () => void; +} + +/** + * Represents a breadcrumb item in the header. + * + * @public + */ +export interface HeaderBreadcrumb { + label: string; + href: string; +} + +/** + * Props for individual header tab components. + * + * @public + */ +export interface HeaderTabProps { + tab: HeaderTab; + setTabRef: (key: string, element: HTMLDivElement | null) => void; + setHoveredKey: (key: string | null) => void; +} + +export interface HeaderIndicatorsProps { + tabRefs: MutableRefObject>; + tabsRef: MutableRefObject; + hoveredKey: string | null; + prevHoveredKey: MutableRefObject; +} diff --git a/packages/canon/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/canon/src/components/HeaderPage/HeaderPage.stories.tsx new file mode 100644 index 0000000000..1fafb47a44 --- /dev/null +++ b/packages/canon/src/components/HeaderPage/HeaderPage.stories.tsx @@ -0,0 +1,144 @@ +/* + * 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 { Meta, StoryObj, StoryFn } from '@storybook/react'; +import { HeaderPage } from './HeaderPage'; +import { HeaderPageOption, HeaderPageTab } from './types'; + +const meta = { + title: 'Components/HeaderPage', + component: HeaderPage, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const tabs: HeaderPageTab[] = [ + { + label: 'Overview', + }, + { + label: 'Checks', + }, + { + label: 'Tracks', + }, + { + label: 'Campaigns', + }, + { + label: 'Integrations', + }, +]; + +const options: HeaderPageOption[] = [ + { + label: 'Settings', + value: 'settings', + }, + { + label: 'Invite new members', + value: 'invite-new-members', + }, +]; + +// Extract layout decorator as a reusable constant +const layoutDecorator = [ + (Story: StoryFn) => ( + <> +
+
+ +
+
+ + ), +]; + +export const Default: Story = { + args: { + title: 'Header Page', + }, +}; + +export const WithDescription: Story = { + args: { + ...Default.args, + description: 'Header Page Description', + }, +}; + +export const WithTabs: Story = { + args: { + ...Default.args, + tabs, + }, +}; + +export const WithOptions: Story = { + args: { + ...Default.args, + options, + }, +}; + +export const WithEverything: Story = { + args: { + ...Default.args, + description: 'Header Page Description', + tabs, + options, + }, +}; + +export const WithLayout: Story = { + args: { + ...WithEverything.args, + }, + decorators: layoutDecorator, + parameters: { + layout: 'fullscreen', + }, +}; diff --git a/packages/canon/src/components/HeaderPage/HeaderPage.styles.css b/packages/canon/src/components/HeaderPage/HeaderPage.styles.css new file mode 100644 index 0000000000..94adcafa53 --- /dev/null +++ b/packages/canon/src/components/HeaderPage/HeaderPage.styles.css @@ -0,0 +1,15 @@ +/* + * 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. + */ diff --git a/packages/canon/src/components/HeaderPage/HeaderPage.tsx b/packages/canon/src/components/HeaderPage/HeaderPage.tsx new file mode 100644 index 0000000000..36581a4b5b --- /dev/null +++ b/packages/canon/src/components/HeaderPage/HeaderPage.tsx @@ -0,0 +1,71 @@ +/* + * Copyright 2025 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 { HeaderPageProps } from './types'; +import { Heading } from '../Heading'; +import { Text } from '../Text'; +import { Flex } from '../Flex'; +import { Menu } from '../Menu'; +import { ButtonIcon } from '../ButtonIcon'; +import { RiMore2Line } from '@remixicon/react'; + +/** + * A component that renders a header page. + * + * @public + */ +export const HeaderPage = (props: HeaderPageProps) => { + const { title, description, options } = props; + + return ( + + + {title} + {description} + +
+ {options && ( + + ( + } + variant="secondary" + /> + )} + /> + + + + {options.map(option => ( + option.onClick?.()} + > + {option.label} + + ))} + + + + + )} +
+
+ ); +}; diff --git a/packages/canon/src/components/HeaderPage/index.tsx b/packages/canon/src/components/HeaderPage/index.tsx new file mode 100644 index 0000000000..c90a0a93f4 --- /dev/null +++ b/packages/canon/src/components/HeaderPage/index.tsx @@ -0,0 +1,18 @@ +/* + * 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 { HeaderPage } from './HeaderPage'; +export type { HeaderPageProps, HeaderPageTab, HeaderPageOption } from './types'; diff --git a/packages/canon/src/components/HeaderPage/types.ts b/packages/canon/src/components/HeaderPage/types.ts new file mode 100644 index 0000000000..8c146b4596 --- /dev/null +++ b/packages/canon/src/components/HeaderPage/types.ts @@ -0,0 +1,48 @@ +/* + * 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. + */ + +/** + * Props for the main HeaderPage component. + * + * @public + */ +export interface HeaderPageProps { + title?: string; + description?: string; + tabs?: HeaderPageTab[]; + options?: HeaderPageOption[]; +} + +/** + * Represents a tab item in the header page. + * + * @public + */ +export interface HeaderPageTab { + label: string; + href?: string; +} + +/** + * Represents an option item in the header page. + * + * @public + */ +export interface HeaderPageOption { + label: string; + value: string; + onClick?: () => void; +} diff --git a/packages/canon/src/components/Heading/Heading.stories.tsx b/packages/canon/src/components/Heading/Heading.stories.tsx index bb241b5aae..2e608c09a3 100644 --- a/packages/canon/src/components/Heading/Heading.stories.tsx +++ b/packages/canon/src/components/Heading/Heading.stories.tsx @@ -46,6 +46,7 @@ export const AllVariants: Story = { Title 2 Title 3 Title 4 + Title 5 ), }; @@ -95,7 +96,7 @@ export const WrappedInLink: Story = { export const CustomRender: Story = { args: { ...Default.args, - render:

, + as: 'h4', }, }; diff --git a/packages/canon/src/components/Heading/Heading.tsx b/packages/canon/src/components/Heading/Heading.tsx index 6ea2fe006b..4ea8bdcfe6 100644 --- a/packages/canon/src/components/Heading/Heading.tsx +++ b/packages/canon/src/components/Heading/Heading.tsx @@ -14,42 +14,51 @@ * limitations under the License. */ -import { forwardRef, useRef } from 'react'; +import { forwardRef } from 'react'; import clsx from 'clsx'; -import { useResponsiveValue } from '../../hooks/useResponsiveValue'; -import { useRender } from '@base-ui-components/react/use-render'; +import type { ElementType } from 'react'; import type { HeadingProps } from './types'; +import { useStyles } from '../../hooks/useStyles'; + +function HeadingComponent( + { + as, + variant = 'title1', + color = 'primary', + truncate, + className, + style, + ...restProps + }: HeadingProps, + ref: React.Ref, +) { + const Component = as || 'h1'; + + const { classNames, dataAttributes } = useStyles('Heading', { + variant, + color, + }); + + return ( + + ); +} + +HeadingComponent.displayName = 'Heading'; /** @public */ -export const Heading = forwardRef( - (props, ref) => { - const { - variant = 'title1', - color = 'primary', - truncate, - className, - render =

, - ...restProps - } = props; - - const responsiveVariant = useResponsiveValue(variant); - const responsiveColor = useResponsiveValue(color); - const internalRef = useRef(null); - - const { renderElement } = useRender({ - render, - props: { - className: clsx('canon-Heading', className), - ['data-variant']: responsiveVariant, - ['data-color']: responsiveColor, - ['data-truncate']: truncate, - ...restProps, - }, - refs: [ref, internalRef], - }); - - return renderElement(); - }, -); +export const Heading = forwardRef(HeadingComponent) as { + ( + props: HeadingProps & { ref?: React.ComponentPropsWithRef['ref'] }, + ): React.ReactElement, T>; + displayName: string; +}; Heading.displayName = 'Heading'; diff --git a/packages/canon/src/components/Heading/index.ts b/packages/canon/src/components/Heading/index.ts index 69b7c3c1a0..ca9845b122 100644 --- a/packages/canon/src/components/Heading/index.ts +++ b/packages/canon/src/components/Heading/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ -export { Heading } from './Heading'; -export type { HeadingProps } from './types'; +export * from './Heading'; +export * from './types'; diff --git a/packages/canon/src/components/Heading/styles.css b/packages/canon/src/components/Heading/styles.css index 1644da09df..ce3da94f7f 100644 --- a/packages/canon/src/components/Heading/styles.css +++ b/packages/canon/src/components/Heading/styles.css @@ -43,7 +43,7 @@ } .canon-Heading[data-variant='title4'] { - font-size: var(--canon-font-size-title4); + font-size: var(--canon-font-size-6); font-weight: var(--canon-font-weight-bold); } diff --git a/packages/canon/src/components/Heading/types.ts b/packages/canon/src/components/Heading/types.ts index 7a94bdf2a4..f2317462c2 100644 --- a/packages/canon/src/components/Heading/types.ts +++ b/packages/canon/src/components/Heading/types.ts @@ -14,12 +14,12 @@ * limitations under the License. */ -import { Breakpoint } from '../../types'; -import type { useRender } from '@base-ui-components/react/use-render'; +import type { ElementType, ComponentPropsWithRef } from 'react'; +import type { Breakpoint } from '../../types'; /** @public */ -export interface HeadingProps - extends Omit, 'color'> { +export type HeadingOwnProps = { + as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'; variant?: | 'display' | 'title1' @@ -40,4 +40,8 @@ export interface HeadingProps truncate?: boolean; className?: string; style?: React.CSSProperties; -} +}; + +/** @public */ +export type HeadingProps = HeadingOwnProps & + Omit, keyof HeadingOwnProps>; diff --git a/packages/canon/src/components/Icon/Icon.tsx b/packages/canon/src/components/Icon/Icon.tsx index 8877420a84..85b476339d 100644 --- a/packages/canon/src/components/Icon/Icon.tsx +++ b/packages/canon/src/components/Icon/Icon.tsx @@ -18,6 +18,7 @@ import { ComponentType } from 'react'; import { useIcons } from './context'; import type { IconProps } from './types'; import clsx from 'clsx'; +import { useStyles } from '../../hooks/useStyles'; /** @public */ export const Icon = (props: IconProps) => { @@ -31,9 +32,11 @@ export const Icon = (props: IconProps) => { return null; } + const { classNames } = useStyles('Icon'); + return ( ((props, ref) => { ...restProps } = props; - const responsiveVariant = useResponsiveValue(variant); - const responsiveWeight = useResponsiveValue(weight); + const { classNames, dataAttributes } = useStyles('Link', { variant, weight }); const internalRef = useRef(null); const { renderElement } = useRender({ render, props: { - className: clsx('canon-Link', className), - ['data-variant']: responsiveVariant, - ['data-weight']: responsiveWeight, + className: clsx(classNames.root, className), + ...dataAttributes, ...restProps, }, refs: [ref, internalRef], diff --git a/packages/canon/src/components/Menu/Menu.styles.css b/packages/canon/src/components/Menu/Menu.styles.css index 07d257f57f..37fa4731e5 100644 --- a/packages/canon/src/components/Menu/Menu.styles.css +++ b/packages/canon/src/components/Menu/Menu.styles.css @@ -1,5 +1,6 @@ .canon-MenuPositioner { outline: 0; + z-index: 100; } .canon-MenuPopup { @@ -93,6 +94,7 @@ .canon-SubmenuComboboxSearch { padding-inline: var(--canon-space-3); + width: 100%; height: 32px; border: none; border-bottom: 1px solid var(--canon-border); diff --git a/packages/canon/src/components/Menu/Menu.tsx b/packages/canon/src/components/Menu/Menu.tsx index 123b01b283..9c475fdf5f 100644 --- a/packages/canon/src/components/Menu/Menu.tsx +++ b/packages/canon/src/components/Menu/Menu.tsx @@ -20,190 +20,255 @@ import clsx from 'clsx'; import { MenuComponent } from './types'; import { Combobox } from './Combobox'; import { Icon } from '../Icon'; +import { useStyles } from '../../hooks/useStyles'; const MenuTrigger = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuTrigger.displayName = MenuPrimitive.Trigger.displayName; const MenuBackdrop = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuBackdrop.displayName = MenuPrimitive.Backdrop.displayName; const MenuPositioner = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuPositioner.displayName = MenuPrimitive.Positioner.displayName; const MenuPopup = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuPopup.displayName = MenuPrimitive.Popup.displayName; const MenuArrow = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuArrow.displayName = MenuPrimitive.Arrow.displayName; const MenuItem = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuItem.displayName = MenuPrimitive.Item.displayName; const MenuGroup = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuGroup.displayName = MenuPrimitive.Group.displayName; const MenuGroupLabel = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuGroupLabel.displayName = MenuPrimitive.GroupLabel.displayName; const MenuRadioGroup = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuRadioGroup.displayName = MenuPrimitive.RadioGroup.displayName; const MenuRadioItem = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuRadioItem.displayName = MenuPrimitive.RadioItem.displayName; const MenuRadioItemIndicator = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuRadioItemIndicator.displayName = MenuPrimitive.RadioItemIndicator.displayName; const MenuCheckboxItem = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuCheckboxItem.displayName = MenuPrimitive.CheckboxItem.displayName; const MenuCheckboxItemIndicator = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuCheckboxItemIndicator.displayName = MenuPrimitive.CheckboxItemIndicator.displayName; const MenuSubmenuTrigger = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - -
{children}
- -
-)); +>(({ className, children, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + +
{children}
+ +
+ ); +}); MenuSubmenuTrigger.displayName = MenuPrimitive.SubmenuTrigger.displayName; const MenuSeparator = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('Menu'); + + return ( + + ); +}); MenuSeparator.displayName = MenuPrimitive.Separator.displayName; /** @public */ diff --git a/packages/canon/src/components/RadioGroup/RadioGroup.stories.tsx b/packages/canon/src/components/RadioGroup/RadioGroup.stories.tsx new file mode 100644 index 0000000000..4f28e04bfc --- /dev/null +++ b/packages/canon/src/components/RadioGroup/RadioGroup.stories.tsx @@ -0,0 +1,147 @@ +/* + * 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 { Meta, StoryObj } from '@storybook/react'; +import { RadioGroup, Radio } from './RadioGroup'; + +const meta = { + title: 'Forms/RadioGroup', + component: RadioGroup, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + label: 'What is your favorite pokemon?', + }, + render: args => ( + + Bulbasaur + Charmander + Squirtle + + ), +}; + +export const Horizontal: Story = { + args: { + ...Default.args, + orientation: 'horizontal', + }, + render: args => ( + + Bulbasaur + Charmander + Squirtle + + ), +}; + +export const Disabled: Story = { + args: { + ...Default.args, + isDisabled: true, + }, + render: args => ( + + Bulbasaur + Charmander + Squirtle + + ), +}; + +export const DisabledSingle: Story = { + args: { + ...Default.args, + }, + render: args => ( + + Bulbasaur + + Charmander + + Squirtle + + ), +}; + +export const DisabledAndSelected: Story = { + args: { + ...Default.args, + value: 'charmander', + }, + render: args => ( + + Bulbasaur + + Charmander + + Squirtle + + ), +}; + +export const Invalid: Story = { + args: { + ...Default.args, + name: 'pokemon', + isInvalid: true, + }, + render: args => ( + + Bulbasaur + + Charmander + + Squirtle + + ), +}; + +export const Validation: Story = { + args: { + ...Default.args, + name: 'pokemon', + defaultValue: 'charmander', + validationBehavior: 'aria', + validate: value => (value === 'charmander' ? 'Nice try!' : null), + }, + render: args => ( + + Bulbasaur + Charmander + Squirtle + + ), +}; + +export const ReadOnly: Story = { + args: { + ...Default.args, + isReadOnly: true, + defaultValue: 'charmander', + }, + render: args => ( + + Bulbasaur + Charmander + Squirtle + + ), +}; diff --git a/packages/canon/src/components/RadioGroup/RadioGroup.styles.css b/packages/canon/src/components/RadioGroup/RadioGroup.styles.css new file mode 100644 index 0000000000..a712f9031f --- /dev/null +++ b/packages/canon/src/components/RadioGroup/RadioGroup.styles.css @@ -0,0 +1,95 @@ +.canon-RadioGroup { + display: flex; + flex-direction: column; + color: var(--canon-fg-primary); +} + +.canon-RadioGroup[data-orientation='horizontal'] .canon-RadioGroupContent { + flex-direction: row; + gap: var(--canon-space-4); +} + +.canon-RadioGroupContent { + display: flex; + flex-direction: column; + gap: var(--canon-space-2); +} + +.canon-Radio { + display: flex; + /* This is needed so the HiddenInput is positioned correctly */ + position: relative; + align-items: center; + gap: var(--canon-space-2); + font-size: var(--canon-font-size-2); + color: var(--canon-fg-primary); + forced-color-adjust: none; + + &:before { + content: ''; + display: block; + width: 1rem; + height: 1rem; + box-sizing: border-box; + border: 0.125rem solid var(--canon-border); + background: var(--canon-gray-1); + border-radius: var(--canon-radius-full); + transition: all 200ms; + } + + &[data-pressed]:before { + border-color: var(--canon-border); + } + + &[data-selected] { + &:before { + border-color: var(--canon-bg-solid); + border-width: 0.25rem; + } + + &[data-pressed]:before { + border-color: var(--canon-bg-solid); + } + } + + &[data-focus-visible]:before { + outline: 2px solid var(--canon-ring); + outline-offset: 2px; + } + + &[data-disabled] { + cursor: not-allowed; + color: var(--canon-fg-disabled); + + &:before { + border-color: var(--canon-border-disabled); + background: var(--canon-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--canon-border-disabled); + } + } + + &[data-invalid]:before { + border-color: var(--canon-border-danger); + } + + &[data-invalid][data-selected]:before { + border-color: var(--canon-border-danger); + } + + /* Ensure disabled state prevails over invalid state */ + &[data-disabled][data-invalid] { + color: var(--canon-fg-disabled); + + &:before { + border-color: var(--canon-border-disabled); + background: var(--canon-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--canon-border-disabled); + } + } +} diff --git a/packages/canon/src/components/RadioGroup/RadioGroup.tsx b/packages/canon/src/components/RadioGroup/RadioGroup.tsx new file mode 100644 index 0000000000..4363477c1a --- /dev/null +++ b/packages/canon/src/components/RadioGroup/RadioGroup.tsx @@ -0,0 +1,95 @@ +/* + * 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 { forwardRef, useEffect } from 'react'; +import { + RadioGroup as AriaRadioGroup, + Radio as AriaRadio, +} from 'react-aria-components'; +import clsx from 'clsx'; +import { FieldLabel } from '../FieldLabel'; +import { FieldError } from '../FieldError'; +import { useStyles } from '../../hooks/useStyles'; + +import type { RadioGroupProps, RadioProps } from './types'; + +/** @public */ +export const RadioGroup = forwardRef( + (props, ref) => { + const { + className, + label, + secondaryLabel, + description, + isRequired, + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledBy, + children, + ...rest + } = props; + + const { classNames } = useStyles('RadioGroup'); + + useEffect(() => { + if (!label && !ariaLabel && !ariaLabelledBy) { + console.warn( + 'RadioGroup requires either a visible label, aria-label, or aria-labelledby for accessibility', + ); + } + }, [label, ariaLabel, ariaLabelledBy]); + + // If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required. + const secondaryLabelText = + secondaryLabel || (isRequired ? 'Required' : null); + + return ( + + +
{children}
+ +
+ ); + }, +); + +RadioGroup.displayName = 'RadioGroup'; + +/** @public */ +export const Radio = forwardRef((props, ref) => { + const { className, ...rest } = props; + + const { classNames } = useStyles('RadioGroup'); + + return ( + + ); +}); + +RadioGroup.displayName = 'RadioGroup'; diff --git a/packages/canon/src/components/RadioGroup/index.ts b/packages/canon/src/components/RadioGroup/index.ts new file mode 100644 index 0000000000..fd9572f667 --- /dev/null +++ b/packages/canon/src/components/RadioGroup/index.ts @@ -0,0 +1,18 @@ +/* + * 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 * from './RadioGroup'; +export * from './types'; diff --git a/packages/canon/src/components/RadioGroup/types.ts b/packages/canon/src/components/RadioGroup/types.ts new file mode 100644 index 0000000000..029ef4baf9 --- /dev/null +++ b/packages/canon/src/components/RadioGroup/types.ts @@ -0,0 +1,32 @@ +/* + * Copyright 2025 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 { + RadioGroupProps as AriaRadioGroupProps, + RadioProps as AriaRadioProps, +} from 'react-aria-components'; +import type { FieldLabelProps } from '../FieldLabel/types'; +import { ReactNode } from 'react'; + +/** @public */ +export interface RadioGroupProps + extends Omit, + Omit { + children?: ReactNode; +} + +/** @public */ +export interface RadioProps extends AriaRadioProps {} diff --git a/packages/canon/src/components/ScrollArea/ScrollArea.tsx b/packages/canon/src/components/ScrollArea/ScrollArea.tsx index e96e76c29b..44722fbd12 100644 --- a/packages/canon/src/components/ScrollArea/ScrollArea.tsx +++ b/packages/canon/src/components/ScrollArea/ScrollArea.tsx @@ -17,53 +17,70 @@ import { forwardRef } from 'react'; import { ScrollArea as ScrollAreaPrimitive } from '@base-ui-components/react/scroll-area'; import clsx from 'clsx'; +import { useStyles } from '../../hooks/useStyles'; const ScrollAreaRoot = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('ScrollArea'); + + return ( + + ); +}); ScrollAreaRoot.displayName = ScrollAreaPrimitive.Root.displayName; const ScrollAreaViewport = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('ScrollArea'); + + return ( + + ); +}); ScrollAreaViewport.displayName = ScrollAreaPrimitive.Viewport.displayName; const ScrollAreaScrollbar = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('ScrollArea'); + + return ( + + ); +}); ScrollAreaScrollbar.displayName = ScrollAreaPrimitive.Scrollbar.displayName; const ScrollAreaThumb = forwardRef< React.ElementRef, React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)); +>(({ className, ...props }, ref) => { + const { classNames } = useStyles('ScrollArea'); + + return ( + + ); +}); ScrollAreaThumb.displayName = ScrollAreaPrimitive.Thumb.displayName; /** @public */ diff --git a/packages/canon/src/components/SearchField/SearchField.stories.tsx b/packages/canon/src/components/SearchField/SearchField.stories.tsx new file mode 100644 index 0000000000..5b267f585d --- /dev/null +++ b/packages/canon/src/components/SearchField/SearchField.stories.tsx @@ -0,0 +1,154 @@ +/* + * 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 { Meta, StoryObj } from '@storybook/react'; +import { SearchField } from './SearchField'; +import { Form } from 'react-aria-components'; +import { Icon } from '../Icon'; +import { Flex } from '../Flex'; +import { FieldLabel } from '../FieldLabel'; + +const meta = { + title: 'Forms/SearchField', + component: SearchField, + argTypes: { + isRequired: { + control: 'boolean', + }, + icon: { + control: 'object', + }, + placeholder: { + control: 'text', + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + name: 'url', + style: { + maxWidth: '300px', + }, + }, +}; + +export const Sizes: Story = { + args: { + ...Default.args, + }, + render: args => ( + + + + + ), +}; + +export const DefaultValue: Story = { + args: { + ...Default.args, + defaultValue: 'https://example.com', + }, +}; + +export const WithLabel: Story = { + args: { + ...Default.args, + label: 'Label', + }, +}; + +export const WithDescription: Story = { + args: { + ...WithLabel.args, + description: 'Description', + }, +}; + +export const Required: Story = { + args: { + ...WithLabel.args, + isRequired: true, + }, +}; + +export const Disabled: Story = { + args: { + ...Default.args, + isDisabled: true, + }, +}; + +export const WithIcon: Story = { + args: { + ...Default.args, + }, + render: args => ( + } + /> + ), +}; + +export const DisabledWithIcon: Story = { + args: { + ...WithIcon.args, + isDisabled: true, + }, +}; + +export const ShowError: Story = { + args: { + ...WithLabel.args, + }, + render: args => ( +
+ + + ), +}; + +export const Validation: Story = { + args: { + ...WithLabel.args, + validate: value => (value === 'admin' ? 'Nice try!' : null), + }, +}; + +export const CustomField: Story = { + render: () => ( + <> + + + + ), +}; diff --git a/packages/canon/src/components/SearchField/SearchField.styles.css b/packages/canon/src/components/SearchField/SearchField.styles.css new file mode 100644 index 0000000000..70bd20e2ac --- /dev/null +++ b/packages/canon/src/components/SearchField/SearchField.styles.css @@ -0,0 +1,55 @@ +/* + * 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. + */ + +.canon-SearchField[data-empty] .canon-InputClear { + display: none; +} + +.canon-InputClear { + position: absolute; + right: 0; + top: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background-color: transparent; + border: none; + padding: 0; + margin: 0; + cursor: pointer; + color: var(--canon-fg-secondary); + transition: color 0.2s ease-in-out; +} + +.canon-InputClear:hover { + color: var(--canon-fg-primary); +} + +.canon-InputClear[data-size='small'] { + width: 2rem; + height: 2rem; +} + +.canon-InputClear[data-size='medium'] { + width: 2.5rem; + height: 2.5rem; +} + +.canon-InputClear svg { + width: 1rem; + height: 1rem; +} diff --git a/packages/canon/src/components/SearchField/SearchField.tsx b/packages/canon/src/components/SearchField/SearchField.tsx new file mode 100644 index 0000000000..ff54439309 --- /dev/null +++ b/packages/canon/src/components/SearchField/SearchField.tsx @@ -0,0 +1,120 @@ +/* + * 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 { forwardRef, useEffect } from 'react'; +import { + Input, + SearchField as AriaSearchField, + Button, +} from 'react-aria-components'; +import clsx from 'clsx'; +import { FieldLabel } from '../FieldLabel'; +import { FieldError } from '../FieldError'; +import { RiSearch2Line, RiCloseCircleLine } from '@remixicon/react'; +import { useStyles } from '../../hooks/useStyles'; + +import type { SearchFieldProps } from './types'; + +/** @public */ +export const SearchField = forwardRef( + (props, ref) => { + const { + className, + icon, + size = 'small', + label, + secondaryLabel, + description, + isRequired, + placeholder = 'Search', + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledBy, + ...rest + } = props; + + useEffect(() => { + if (!label && !ariaLabel && !ariaLabelledBy) { + console.warn( + 'SearchField requires either a visible label, aria-label, or aria-labelledby for accessibility', + ); + } + }, [label, ariaLabel, ariaLabelledBy]); + + const { classNames: textFieldClassNames, dataAttributes } = useStyles( + 'TextField', + { + size, + }, + ); + + const { classNames: searchFieldClassNames } = useStyles('SearchField', { + size, + }); + + // If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required. + const secondaryLabelText = + secondaryLabel || (isRequired ? 'Required' : null); + + return ( + + +
+ {icon !== false && ( + + )} + + +
+ +
+ ); + }, +); + +SearchField.displayName = 'searchField'; diff --git a/packages/canon/src/components/SearchField/index.ts b/packages/canon/src/components/SearchField/index.ts new file mode 100644 index 0000000000..288c3fe44a --- /dev/null +++ b/packages/canon/src/components/SearchField/index.ts @@ -0,0 +1,18 @@ +/* + * 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 * from './SearchField'; +export * from './types'; diff --git a/packages/canon/src/components/SearchField/types.ts b/packages/canon/src/components/SearchField/types.ts new file mode 100644 index 0000000000..b561292684 --- /dev/null +++ b/packages/canon/src/components/SearchField/types.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2025 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 { SearchFieldProps as AriaSearchFieldProps } from 'react-aria-components'; +import { ReactNode } from 'react'; +import type { Breakpoint } from '../../types'; +import type { FieldLabelProps } from '../FieldLabel/types'; + +/** @public */ +export interface SearchFieldProps + extends AriaSearchFieldProps, + Omit { + /** + * An icon to render before the input + */ + icon?: ReactNode | false; + + /** + * The size of the text field + * @defaultValue 'medium' + */ + size?: 'small' | 'medium' | Partial>; + + /** + * The placeholder text for the input + */ + placeholder?: string; +} diff --git a/packages/canon/src/components/Select/Select.tsx b/packages/canon/src/components/Select/Select.tsx index 3f25ac26de..7bedc5e2a0 100644 --- a/packages/canon/src/components/Select/Select.tsx +++ b/packages/canon/src/components/Select/Select.tsx @@ -20,7 +20,7 @@ import { Icon } from '../Icon'; import clsx from 'clsx'; import './Select.styles.css'; import { SelectProps } from './types'; -import { useResponsiveValue } from '../../hooks/useResponsiveValue'; +import { useStyles } from '../../hooks/useStyles'; /** @public */ export const Select = forwardRef((props, ref) => { @@ -37,8 +37,9 @@ export const Select = forwardRef((props, ref) => { ...rest } = props; - // Get the responsive value for the variant - const responsiveSize = useResponsiveValue(size); + const { classNames, dataAttributes } = useStyles('Select', { + size, + }); // Generate unique IDs for accessibility const selectId = useId(); @@ -58,7 +59,7 @@ export const Select = forwardRef((props, ref) => { ); return ( -
+
{label && (