From 0d4c4db867d890783bd10b57e8b64e5829e0f35f Mon Sep 17 00:00:00 2001 From: Zeshan Ziya Date: Wed, 27 Aug 2025 12:44:46 +0530 Subject: [PATCH 001/244] fix(home): correct clearAll logic to properly handle deletable flag Signed-off-by: Zeshan Ziya --- .../home/src/components/CustomHomepage/CustomHomepageGrid.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx b/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx index 5d85e834e8..807837acf6 100644 --- a/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx +++ b/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx @@ -275,7 +275,7 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => { }; const clearLayout = () => { - setWidgets(widgets.filter(w => !w.deletable)); + setWidgets(widgets.filter(w => w.deletable === false)); }; const changeEditMode = (mode: boolean) => { From 9a3f11889ab275c777d2a88507324e8417b96fb2 Mon Sep 17 00:00:00 2001 From: Zeshan Ziya Date: Wed, 27 Aug 2025 12:45:32 +0530 Subject: [PATCH 002/244] fix(home): add example to deletable flag on customizable home page Signed-off-by: Zeshan Ziya --- packages/app/src/components/home/CustomizableHomePage.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/app/src/components/home/CustomizableHomePage.tsx b/packages/app/src/components/home/CustomizableHomePage.tsx index b592490f2e..1d3cab646b 100644 --- a/packages/app/src/components/home/CustomizableHomePage.tsx +++ b/packages/app/src/components/home/CustomizableHomePage.tsx @@ -37,6 +37,7 @@ const defaultConfig = [ y: 0, width: 24, height: 2, + deletable: false, }, { component: 'HomePageRecentlyVisited', From e7d59d3c72589aaca620a80fbd60daf1b5235ecc Mon Sep 17 00:00:00 2001 From: Zeshan Ziya Date: Wed, 27 Aug 2025 12:46:34 +0530 Subject: [PATCH 003/244] chore: add changeset Signed-off-by: Zeshan Ziya --- .changeset/fuzzy-trams-kick.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/fuzzy-trams-kick.md diff --git a/.changeset/fuzzy-trams-kick.md b/.changeset/fuzzy-trams-kick.md new file mode 100644 index 0000000000..19e12b1073 --- /dev/null +++ b/.changeset/fuzzy-trams-kick.md @@ -0,0 +1,6 @@ +--- +'example-app': patch +'@backstage/plugin-home': patch +--- + +fix(home): correct clearAll logic to properly handle deletable flag From 28d0c0f43c5b8393aa1a807acb00c804aa563e44 Mon Sep 17 00:00:00 2001 From: Zeshan Ziya Date: Wed, 27 Aug 2025 13:00:59 +0530 Subject: [PATCH 004/244] chore: remove example-app from changeset Signed-off-by: Zeshan Ziya --- .changeset/fuzzy-trams-kick.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/fuzzy-trams-kick.md b/.changeset/fuzzy-trams-kick.md index 19e12b1073..71c06891d0 100644 --- a/.changeset/fuzzy-trams-kick.md +++ b/.changeset/fuzzy-trams-kick.md @@ -1,5 +1,4 @@ --- -'example-app': patch '@backstage/plugin-home': patch --- From eea536048833d941f4d2d8d492dcbbf00d4edfc4 Mon Sep 17 00:00:00 2001 From: Brent Swisher Date: Tue, 2 Sep 2025 16:11:06 -0400 Subject: [PATCH 005/244] Add action to fetch the DSN of a Sentry project Signed-off-by: Brent Swisher --- .changeset/long-lizards-notice.md | 5 + .../report.api.md | 15 ++ .../src/actions/fetchDSN.examples.test.ts | 174 +++++++++++++++ .../src/actions/fetchDSN.examples.ts | 57 +++++ .../src/actions/fetchDSN.test.ts | 199 ++++++++++++++++++ .../src/actions/fetchDSN.ts | 104 +++++++++ .../src/index.ts | 1 + .../src/module.ts | 6 +- 8 files changed, 560 insertions(+), 1 deletion(-) create mode 100644 .changeset/long-lizards-notice.md create mode 100644 plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.test.ts create mode 100644 plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.ts create mode 100644 plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.test.ts create mode 100644 plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.ts diff --git a/.changeset/long-lizards-notice.md b/.changeset/long-lizards-notice.md new file mode 100644 index 0000000000..47ac81732f --- /dev/null +++ b/.changeset/long-lizards-notice.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend-module-sentry': patch +--- + +Add sentry:fetch:dsn action to retrieve a Sentry project's DSN diff --git a/plugins/scaffolder-backend-module-sentry/report.api.md b/plugins/scaffolder-backend-module-sentry/report.api.md index 98b3c8b599..7e4701e609 100644 --- a/plugins/scaffolder-backend-module-sentry/report.api.md +++ b/plugins/scaffolder-backend-module-sentry/report.api.md @@ -25,6 +25,21 @@ export function createSentryCreateProjectAction(options: { 'v2' >; +// @public +export function createSentryFetchDSNAction(options: { + config: Config; +}): TemplateAction< + { + organizationSlug: string; + projectSlug: string; + authToken?: string | undefined; + }, + { + [x: string]: any; + }, + 'v2' +>; + // @public const sentryModule: BackendFeature; export default sentryModule; diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.test.ts b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.test.ts new file mode 100644 index 0000000000..609a366408 --- /dev/null +++ b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.test.ts @@ -0,0 +1,174 @@ +/* + * Copyright 2021 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 { registerMswTestHooks } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; +import { ConfigReader } from '@backstage/config'; +import { ActionContext } from '@backstage/plugin-scaffolder-node'; +import { JsonObject } from '@backstage/types'; +import { randomBytes } from 'crypto'; +import { setupServer } from 'msw/node'; +import { HttpResponse, http } from 'msw'; +import { createSentryFetchDSNAction } from './fetchDSN'; +import yaml from 'yaml'; +import { examples } from './fetchDSN.examples'; + +describe('sentry:fetch:dsn action', () => { + const worker = setupServer(); + registerMswTestHooks(worker); + + const createScaffolderConfig = (configData: JsonObject = {}) => ({ + config: new ConfigReader({ + scaffolder: { + ...configData, + }, + }), + }); + + const getActionContext = (): ActionContext<{ + organizationSlug: string; + projectSlug: string; + authToken?: string; + }> => + createMockActionContext({ + workspacePath: './dev/proj', + logger: jest.createMockFromModule('winston'), + input: { + organizationSlug: 'org', + projectSlug: 'project', + authToken: randomBytes(5).toString('hex'), + }, + }); + + const mockSentryKeysResponse = [ + { + id: '12345', + name: 'Default', + public: 'abcdef1234567890', + secret: 'secret1234567890', + projectId: 67890, + isActive: true, + dateCreated: '2021-01-01T00:00:00.000Z', + dsn: { + secret: 'https://abcdef1234567890:secret1234567890@sentry.io/67890', + public: 'https://abcdef1234567890@sentry.io/67890', + csp: 'https://sentry.io/api/67890/csp-report/?sentry_key=abcdef1234567890', + security: + 'https://sentry.io/api/67890/security-report/?sentry_key=abcdef1234567890', + minidump: + 'https://sentry.io/api/67890/minidump/?sentry_key=abcdef1234567890', + nel: 'https://sentry.io/api/67890/nel-report/?sentry_key=abcdef1234567890', + unreal: 'https://sentry.io/api/67890/unreal/abcdef1234567890/', + cdn: 'https://sentry.io/js-sdk-loader/abcdef1234567890.min.js', + }, + browserSdkVersion: '6.x', + browserSdk: { + choices: [ + ['latest', 'latest'], + ['6.x', '6.x'], + ['5.x', '5.x'], + ['4.x', '4.x'], + ], + }, + }, + ]; + + it(`should ${examples[0].description}`, async () => { + expect.assertions(3); + + let input; + try { + input = yaml.parse(examples[0].example).steps[0].input; + } catch (error) { + console.error('Failed to parse YAML:', error); + } + + const action = createSentryFetchDSNAction(createScaffolderConfig()); + const actionContext = getActionContext(); + + worker.use( + http.get( + `https://sentry.io/api/0/projects/${input.organizationSlug}/${input.projectSlug}/keys/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer a14711beb516e1e910d2ede554dc1bf725654ef3c75e5a9106de9aec13d5df96`, + ); + expect(request.headers.get('Content-Type')).toBe(`application/json`); + return HttpResponse.json(mockSentryKeysResponse, { status: 200 }); + }, + ), + ); + + await action.handler({ + ...actionContext, + input: { + ...actionContext.input, + ...input, + }, + }); + expect(actionContext.output).toHaveBeenCalledWith( + 'dsn', + 'https://abcdef1234567890@sentry.io/67890', + ); + }); + + it(`should ${examples[1].description}`, async () => { + expect.assertions(3); + + let input; + try { + input = yaml.parse(examples[1].example).steps[0].input; + } catch (error) { + console.error('Failed to parse YAML:', error); + } + + const sentryScaffolderConfigToken = randomBytes(5).toString('hex'); + const action = createSentryFetchDSNAction( + createScaffolderConfig({ + sentry: { + token: sentryScaffolderConfigToken, + }, + }), + ); + const actionContext = getActionContext(); + actionContext.input.authToken = undefined; + + worker.use( + http.get( + `https://sentry.io/api/0/projects/${input.organizationSlug}/${input.projectSlug}/keys/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer ${sentryScaffolderConfigToken}`, + ); + expect(request.headers.get('Content-Type')).toBe(`application/json`); + return HttpResponse.json(mockSentryKeysResponse, { status: 200 }); + }, + ), + ); + + await action.handler({ + ...actionContext, + input: { + ...actionContext.input, + ...input, + }, + }); + expect(actionContext.output).toHaveBeenCalledWith( + 'dsn', + 'https://abcdef1234567890@sentry.io/67890', + ); + }); +}); diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.ts b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.ts new file mode 100644 index 0000000000..0b1454ebac --- /dev/null +++ b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.ts @@ -0,0 +1,57 @@ +/* + * Copyright 2021 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 { TemplateExample } from '@backstage/plugin-scaffolder-node'; +import yaml from 'yaml'; + +export const examples: TemplateExample[] = [ + { + description: + 'Fetch the DSN for a Sentry project with authentication token.', + example: yaml.stringify({ + steps: [ + { + id: 'fetch-sentry-dsn', + action: 'sentry:fetch:dsn', + name: 'Fetch DSN using auth token', + input: { + organizationSlug: 'my-org', + projectSlug: 'my-project', + authToken: + 'a14711beb516e1e910d2ede554dc1bf725654ef3c75e5a9106de9aec13d5df96', + }, + }, + ], + }), + }, + { + description: + 'Fetch the DSN for a Sentry project using the token from the configuration.', + example: yaml.stringify({ + steps: [ + { + id: 'fetch-sentry-dsn', + action: 'sentry:fetch:dsn', + name: 'Fetch DSN using config token', + input: { + organizationSlug: 'my-org', + projectSlug: 'my-project', + }, + }, + ], + }), + }, +]; diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.test.ts b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.test.ts new file mode 100644 index 0000000000..6396381435 --- /dev/null +++ b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.test.ts @@ -0,0 +1,199 @@ +/* + * Copyright 2021 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 { registerMswTestHooks } from '@backstage/backend-test-utils'; +import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils'; +import { ConfigReader } from '@backstage/config'; +import { InputError } from '@backstage/errors'; +import { ActionContext } from '@backstage/plugin-scaffolder-node'; +import { JsonObject } from '@backstage/types'; +import { randomBytes } from 'crypto'; +import { setupServer } from 'msw/node'; +import { HttpResponse, http } from 'msw'; +import { createSentryFetchDSNAction } from './fetchDSN'; + +describe('sentry:fetch:dsn action', () => { + const worker = setupServer(); + registerMswTestHooks(worker); + + const createScaffolderConfig = (configData: JsonObject = {}) => ({ + config: new ConfigReader({ + scaffolder: { + ...configData, + }, + }), + }); + + const getActionContext = (): ActionContext<{ + organizationSlug: string; + projectSlug: string; + authToken?: string; + }> => + createMockActionContext({ + workspacePath: './dev/proj', + logger: jest.createMockFromModule('winston'), + input: { + organizationSlug: 'org', + projectSlug: 'project', + authToken: randomBytes(5).toString('hex'), + }, + }); + + it('should fetch DSN from sentry project with specified parameters.', async () => { + expect.assertions(3); + + const action = createSentryFetchDSNAction(createScaffolderConfig()); + const actionContext = getActionContext(); + const mockDSN = 'https://test@sentry.io/123'; + + worker.use( + http.get( + `https://sentry.io/api/0/projects/${actionContext.input.organizationSlug}/${actionContext.input.projectSlug}/keys/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer ${actionContext.input.authToken}`, + ); + expect(request.headers.get('Content-Type')).toBe(`application/json`); + return HttpResponse.json([{ dsn: { public: mockDSN } }], { + status: 200, + }); + }, + ), + ); + + await action.handler(actionContext); + expect(actionContext.output).toHaveBeenCalledWith('dsn', mockDSN); + }); + + it('should take Sentry auth token from scaffolder config when input authToken is missing.', async () => { + expect.assertions(3); + + const sentryScaffolderConfigToken = randomBytes(5).toString('hex'); + const action = createSentryFetchDSNAction( + createScaffolderConfig({ + sentry: { + token: sentryScaffolderConfigToken, + }, + }), + ); + const actionContext = getActionContext(); + actionContext.input.authToken = undefined; + const mockDSN = 'https://test@sentry.io/123'; + + worker.use( + http.get( + `https://sentry.io/api/0/projects/${actionContext.input.organizationSlug}/${actionContext.input.projectSlug}/keys/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer ${sentryScaffolderConfigToken}`, + ); + expect(request.headers.get('Content-Type')).toBe(`application/json`); + return HttpResponse.json([{ dsn: { public: mockDSN } }], { + status: 200, + }); + }, + ), + ); + + await action.handler(actionContext); + expect(actionContext.output).toHaveBeenCalledWith('dsn', mockDSN); + }); + + it('should throw InputError when auth token is missing from input parameters and scaffolder config.', async () => { + const action = createSentryFetchDSNAction(createScaffolderConfig()); + const actionContext = getActionContext(); + actionContext.input.authToken = undefined; + + await expect(() => action.handler(actionContext)).rejects.toThrow( + new InputError('No valid sentry token given'), + ); + }); + + it('should throw InputError when sentry API returns unexpected content-type.', async () => { + const action = createSentryFetchDSNAction(createScaffolderConfig()); + const actionContext = getActionContext(); + + worker.use( + http.get( + `https://sentry.io/api/0/projects/${actionContext.input.organizationSlug}/${actionContext.input.projectSlug}/keys/`, + async () => { + return HttpResponse.text('Bad response', { status: 200 }); + }, + ), + ); + + await expect(() => action.handler(actionContext)).rejects.toThrow( + new InputError(`Unexpected Sentry Response Type: Bad response`), + ); + }); + + it('should throw InputError when sentry API returns error status code.', async () => { + const action = createSentryFetchDSNAction(createScaffolderConfig()); + const actionContext = getActionContext(); + + worker.use( + http.get( + `https://sentry.io/api/0/projects/${actionContext.input.organizationSlug}/${actionContext.input.projectSlug}/keys/`, + async () => { + return HttpResponse.json( + { detail: 'Project not found' }, + { status: 404 }, + ); + }, + ), + ); + + await expect(() => action.handler(actionContext)).rejects.toThrow( + new InputError(`Sentry Response was: Project not found`), + ); + }); + + it('should throw InputError when no keys are returned.', async () => { + const action = createSentryFetchDSNAction(createScaffolderConfig()); + const actionContext = getActionContext(); + + worker.use( + http.get( + `https://sentry.io/api/0/projects/${actionContext.input.organizationSlug}/${actionContext.input.projectSlug}/keys/`, + async () => { + return HttpResponse.json([], { status: 200 }); + }, + ), + ); + + await expect(() => action.handler(actionContext)).rejects.toThrow( + new InputError('No keys found for the specified project'), + ); + }); + + it('should throw InputError when no public DSN is found in keys.', async () => { + const action = createSentryFetchDSNAction(createScaffolderConfig()); + const actionContext = getActionContext(); + + worker.use( + http.get( + `https://sentry.io/api/0/projects/${actionContext.input.organizationSlug}/${actionContext.input.projectSlug}/keys/`, + async () => { + return HttpResponse.json([{ dsn: {} }], { status: 200 }); + }, + ), + ); + + await expect(() => action.handler(actionContext)).rejects.toThrow( + new InputError('No public DSN found in project keys'), + ); + }); +}); diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.ts b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.ts new file mode 100644 index 0000000000..d5078ce300 --- /dev/null +++ b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.ts @@ -0,0 +1,104 @@ +/* + * Copyright 2021 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 { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { InputError } from '@backstage/errors'; +import { Config } from '@backstage/config'; + +/** + * Creates the `sentry:fetch:dsn` Scaffolder action. + * + * @remarks + * + * See {@link https://backstage.io/docs/features/software-templates/writing-custom-actions}. + * + * @param options - Configuration of the Sentry API. + * @public + */ +export function createSentryFetchDSNAction(options: { config: Config }) { + const { config } = options; + + return createTemplateAction({ + id: 'sentry:fetch:dsn', + supportsDryRun: true, + schema: { + input: { + organizationSlug: z => + z.string({ + description: 'The slug of the organization the project belongs to', + }), + projectSlug: z => + z.string({ + description: 'The slug of the project to fetch the DSN for', + }), + authToken: z => + z + .string({ + description: + 'authenticate via bearer auth token. Requires one of the following scopes: project:admin, project:read, project:write', + }) + .optional(), + }, + }, + async handler(ctx) { + const { organizationSlug, projectSlug, authToken } = ctx.input; + + const token = authToken + ? authToken + : config.getOptionalString('scaffolder.sentry.token'); + + if (!token) { + throw new InputError(`No valid sentry token given`); + } + + const response = await fetch( + `https://sentry.io/api/0/projects/${organizationSlug}/${projectSlug}/keys/`, + { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + 'Content-Type': 'application/json', + }, + }, + ); + + if (!response.headers.get('content-type')?.includes('application/json')) { + throw new InputError( + `Unexpected Sentry Response Type: ${await response.text()}`, + ); + } + + const keys = await response.json(); + + if (response.status !== 200) { + throw new InputError( + `Sentry Response was: ${keys.detail || 'Unknown error'}`, + ); + } + + if (!Array.isArray(keys) || keys.length === 0) { + throw new InputError('No keys found for the specified project'); + } + + const publicDsn = keys[0]?.dsn?.public; + if (!publicDsn) { + throw new InputError('No public DSN found in project keys'); + } + + ctx.output('dsn', publicDsn); + }, + }); +} diff --git a/plugins/scaffolder-backend-module-sentry/src/index.ts b/plugins/scaffolder-backend-module-sentry/src/index.ts index dc1a68675b..de818d9735 100644 --- a/plugins/scaffolder-backend-module-sentry/src/index.ts +++ b/plugins/scaffolder-backend-module-sentry/src/index.ts @@ -15,4 +15,5 @@ */ export { createSentryCreateProjectAction } from './actions/createProject'; +export { createSentryFetchDSNAction } from './actions/fetchDSN'; export { sentryModule as default } from './module'; diff --git a/plugins/scaffolder-backend-module-sentry/src/module.ts b/plugins/scaffolder-backend-module-sentry/src/module.ts index dcde344262..847a361697 100644 --- a/plugins/scaffolder-backend-module-sentry/src/module.ts +++ b/plugins/scaffolder-backend-module-sentry/src/module.ts @@ -19,6 +19,7 @@ import { } from '@backstage/backend-plugin-api'; import { scaffolderActionsExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha'; import { createSentryCreateProjectAction } from './actions/createProject'; +import { createSentryFetchDSNAction } from './actions/fetchDSN'; /** * @public @@ -35,7 +36,10 @@ export const sentryModule = createBackendModule({ reade: coreServices.urlReader, }, async init({ scaffolder, config }) { - scaffolder.addActions(createSentryCreateProjectAction({ config })); + scaffolder.addActions( + createSentryCreateProjectAction({ config }), + createSentryFetchDSNAction({ config }), + ); }, }); }, From b205ea380d96dacea2e06af2443de07a8f39c530 Mon Sep 17 00:00:00 2001 From: Brent Swisher Date: Tue, 2 Sep 2025 16:19:55 -0400 Subject: [PATCH 006/244] Add new action to README Signed-off-by: Brent Swisher --- plugins/scaffolder-backend-module-sentry/README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugins/scaffolder-backend-module-sentry/README.md b/plugins/scaffolder-backend-module-sentry/README.md index 252585d584..ad5ee96d54 100644 --- a/plugins/scaffolder-backend-module-sentry/README.md +++ b/plugins/scaffolder-backend-module-sentry/README.md @@ -4,6 +4,9 @@ Welcome to the Sentry Module for Scaffolder. Here you can find all Sentry related features to improve your scaffolder: +- Create a Sentry Project +- Fetch the DSN for an existing Sentry Project + ## Getting started You need to configure the action in your backend: @@ -112,6 +115,14 @@ spec: teamSlug: TEAM-SLUG name: ${{ parameters.name }} + - id: fetch-sentry-dsn + if: ${{ parameters.dryRun !== true }} + name: Get the DSN of the newly created Sentry Project + action: sentry:fetch:dsn + input: + organizationSlug: ORG-SLUG + projectSlug: ${{ parameters.name }} + - id: publish if: ${{ parameters.dryRun !== true }} name: Publish From 431130cb833e18d81287e7d301537094e8f05593 Mon Sep 17 00:00:00 2001 From: TA31OU Date: Wed, 13 Aug 2025 09:37:50 +0200 Subject: [PATCH 007/244] Add changeset Signed-off-by: TA31OU (cherry picked from commit ce965429e38c3817432085b97a63447289586af3) --- .changeset/flat-peas-run.md | 6 ++++ .../DependencyGraph/DependencyGraph.tsx | 8 +++++ .../src/components/DependencyGraph/types.ts | 34 +++++++++++++++++++ plugins/catalog-graph/package.json | 2 ++ .../DefaultRenderEdge.tsx | 15 ++++++++ .../EntityRelationsGraph.tsx | 3 ++ .../EntityRelationsGraph/useEntityStore.ts | 2 +- yarn.lock | 2 ++ 8 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 .changeset/flat-peas-run.md create mode 100644 plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx diff --git a/.changeset/flat-peas-run.md b/.changeset/flat-peas-run.md new file mode 100644 index 0000000000..116e8eb449 --- /dev/null +++ b/.changeset/flat-peas-run.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': minor +'@backstage/plugin-catalog-graph': minor +--- + +Added `renderEdge` prop to component in @backstage/core-components to allow custom rendering of graph edges. Fixed local development for EntityRelationsGraph plugin. diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx index d690253b06..f4b3d6bd58 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx @@ -138,6 +138,11 @@ export interface DependencyGraphProps * Weight applied to edges in graph */ edgeWeight?: number; + /** + * Custom edge rendering component + */ + renderEdge?: Types.RenderEdgeFunction; + /** * Custom node rendering component */ @@ -210,6 +215,7 @@ export function DependencyGraph( labelOffset = 10, edgeRanks = 1, edgeWeight = 1, + renderEdge, renderLabel, defs, zoom = 'enabled', @@ -442,6 +448,8 @@ export function DependencyGraph( {graphEdges.map(e => { const edge = graph.current.edge(e) as GraphEdge; if (!edge) return null; + if (renderEdge) return renderEdge({ edge, id: e }); + return ( , ) => ReactNode; + /** + * Properties of {@link DependencyGraphTypes.RenderEdgeFunction} for {@link DependencyGraphTypes.DependencyEdge} + * + * @public + */ + export type RenderEdgeProps = { + edge: DependencyEdge; + id: dagre.Edge; + }; + + /** + * Custom React component for graph {@link DependencyGraphTypes.DependencyEdge} + * + * @public + */ + export type RenderEdgeFunction = (props: { + edge: T & { + points: { x: number; y: number }[]; + label?: string; + labeloffset?: number; + labelpos?: string; + width?: number; + height?: number; + weight?: number; + minlen?: number; + showArrowHeads?: boolean; + from?: string; + to?: string; + relations?: string[]; + }; + id: { v: string; w: string }; + }) => ReactNode; + /** * Graph direction * diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index dd3271f468..7cea775bbe 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -61,6 +61,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "classnames": "^2.3.1", + "d3-shape": "^3.0.0", "lodash": "^4.17.15", "p-limit": "^3.1.0", "qs": "^6.9.4", @@ -76,6 +77,7 @@ "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.0.0", + "@types/d3-shape": "^3.0.1", "@types/react": "^18.0.0", "react": "^18.0.2", "react-dom": "^18.0.2", diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx new file mode 100644 index 0000000000..379ce77f52 --- /dev/null +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx @@ -0,0 +1,15 @@ +/* + * 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. + */ diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx index 933aa230be..f08cd7a760 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/EntityRelationsGraph.tsx @@ -89,6 +89,7 @@ export type EntityRelationsGraphProps = { zoom?: 'enabled' | 'disabled' | 'enable-on-click'; renderNode?: DependencyGraphTypes.RenderNodeFunction; renderLabel?: DependencyGraphTypes.RenderLabelFunction; + renderEdge?: DependencyGraphTypes.RenderEdgeFunction; curve?: 'curveStepBefore' | 'curveMonotoneX'; showArrowHeads?: boolean; }; @@ -114,6 +115,7 @@ export const EntityRelationsGraph = (props: EntityRelationsGraphProps) => { zoom = 'enabled', renderNode, renderLabel, + renderEdge, curve, showArrowHeads, } = props; @@ -156,6 +158,7 @@ export const EntityRelationsGraph = (props: EntityRelationsGraphProps) => { edges={edges} renderNode={renderNode || DefaultRenderNode} renderLabel={renderLabel || DefaultRenderLabel} + renderEdge={renderEdge} direction={direction} className={classes.graph} paddingX={theme.spacing(4)} diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts index c55becdd49..be6ea81f57 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts @@ -64,7 +64,7 @@ export function useEntityStore(): { return; } - const { items } = await catalogClient.getEntitiesByRefs({ entityRefs }); + const { items } = await catalogClient.getEntities(); items.forEach(ent => { if (ent) { const entityRef = stringifyEntityRef(ent); diff --git a/yarn.lock b/yarn.lock index 853749b99e..fde37ae4e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4771,8 +4771,10 @@ __metadata: "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" "@testing-library/user-event": "npm:^14.0.0" + "@types/d3-shape": "npm:^3.0.1" "@types/react": "npm:^18.0.0" classnames: "npm:^2.3.1" + d3-shape: "npm:^3.0.0" lodash: "npm:^4.17.15" p-limit: "npm:^3.1.0" qs: "npm:^6.9.4" From cd961c25d181fb907c1481e9af6dce6fed375552 Mon Sep 17 00:00:00 2001 From: TA31OU Date: Wed, 3 Sep 2025 12:17:06 +0200 Subject: [PATCH 008/244] Revert useEntityStore change Signed-off-by: TA31OU --- .changeset/flat-peas-run.md | 2 +- .../src/components/EntityRelationsGraph/useEntityStore.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/flat-peas-run.md b/.changeset/flat-peas-run.md index 116e8eb449..c09eadecf8 100644 --- a/.changeset/flat-peas-run.md +++ b/.changeset/flat-peas-run.md @@ -3,4 +3,4 @@ '@backstage/plugin-catalog-graph': minor --- -Added `renderEdge` prop to component in @backstage/core-components to allow custom rendering of graph edges. Fixed local development for EntityRelationsGraph plugin. +Added `renderEdge` prop to component in @backstage/core-components to allow custom rendering of graph edges. diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts index be6ea81f57..c55becdd49 100644 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts +++ b/plugins/catalog-graph/src/components/EntityRelationsGraph/useEntityStore.ts @@ -64,7 +64,7 @@ export function useEntityStore(): { return; } - const { items } = await catalogClient.getEntities(); + const { items } = await catalogClient.getEntitiesByRefs({ entityRefs }); items.forEach(ent => { if (ent) { const entityRef = stringifyEntityRef(ent); From 05b7ac0c560c6daa2f2bb0cbc36bdc4db3deeeab Mon Sep 17 00:00:00 2001 From: TA31OU Date: Wed, 3 Sep 2025 13:25:07 +0200 Subject: [PATCH 009/244] Update catalog-graph report-api Signed-off-by: TA31OU --- plugins/catalog-graph/report.api.md | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/catalog-graph/report.api.md b/plugins/catalog-graph/report.api.md index 25479bd9b7..7f001531b8 100644 --- a/plugins/catalog-graph/report.api.md +++ b/plugins/catalog-graph/report.api.md @@ -129,6 +129,7 @@ export type EntityRelationsGraphProps = { zoom?: 'enabled' | 'disabled' | 'enable-on-click'; renderNode?: DependencyGraphTypes.RenderNodeFunction; renderLabel?: DependencyGraphTypes.RenderLabelFunction; + renderEdge?: DependencyGraphTypes.RenderEdgeFunction; curve?: 'curveStepBefore' | 'curveMonotoneX'; showArrowHeads?: boolean; }; From 3c994731243c37dd37ceaa709760e66dfd2ebd1c Mon Sep 17 00:00:00 2001 From: TA31OU Date: Wed, 3 Sep 2025 13:46:28 +0200 Subject: [PATCH 010/244] Update core-components report-api Signed-off-by: TA31OU --- packages/core-components/report-alpha.api.md | 2 +- packages/core-components/report.api.md | 33 ++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/packages/core-components/report-alpha.api.md b/packages/core-components/report-alpha.api.md index 32bd2f4939..e258777b9c 100644 --- a/packages/core-components/report-alpha.api.md +++ b/packages/core-components/report-alpha.api.md @@ -24,10 +24,10 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'signIn.title': 'Sign In'; readonly 'signIn.loginFailed': 'Login failed'; readonly 'signIn.customProvider.title': 'Custom User'; + readonly 'signIn.customProvider.continue': 'Continue'; readonly 'signIn.customProvider.subtitle': 'Enter your own User ID and credentials.\n This selection will not be stored.'; readonly 'signIn.customProvider.userId': 'User ID'; readonly 'signIn.customProvider.tokenInvalid': 'Token is not a valid OpenID Connect JWT Token'; - readonly 'signIn.customProvider.continue': 'Continue'; readonly 'signIn.customProvider.idToken': 'ID Token (optional)'; readonly 'signIn.guestProvider.title': 'Guest'; readonly 'signIn.guestProvider.enter': 'Enter'; diff --git a/packages/core-components/report.api.md b/packages/core-components/report.api.md index fff1d0365a..4998accf01 100644 --- a/packages/core-components/report.api.md +++ b/packages/core-components/report.api.md @@ -18,6 +18,7 @@ import { ComponentType } from 'react'; import { Context } from 'react'; import { default as CSS_2 } from 'csstype'; import { CSSProperties } from 'react'; +import dagre from '@dagrejs/dagre'; import { ElementType } from 'react'; import { ErrorInfo } from 'react'; import IconButton from '@material-ui/core/IconButton'; @@ -273,6 +274,7 @@ export interface DependencyGraphProps paddingY?: number; ranker?: DependencyGraphTypes.Ranker; rankMargin?: number; + renderEdge?: DependencyGraphTypes.RenderEdgeFunction; renderLabel?: DependencyGraphTypes.RenderLabelFunction; renderNode?: DependencyGraphTypes.RenderNodeFunction; showArrowHeads?: boolean; @@ -314,6 +316,33 @@ export namespace DependencyGraphTypes { NETWORK_SIMPLEX = 'network-simplex', TIGHT_TREE = 'tight-tree', } + export type RenderEdgeFunction = (props: { + edge: T & { + points: { + x: number; + y: number; + }[]; + label?: string; + labeloffset?: number; + labelpos?: string; + width?: number; + height?: number; + weight?: number; + minlen?: number; + showArrowHeads?: boolean; + from?: string; + to?: string; + relations?: string[]; + }; + id: { + v: string; + w: string; + }; + }) => ReactNode; + export type RenderEdgeProps = { + edge: DependencyEdge; + id: dagre.Edge; + }; export type RenderLabelFunction = ( props: RenderLabelProps, ) => ReactNode; @@ -1548,8 +1577,8 @@ export type WarningPanelClassKey = // Warnings were encountered during analysis: // -// src/components/DependencyGraph/types.d.ts:22:9 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode" -// src/components/DependencyGraph/types.d.ts:26:9 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode" +// src/components/DependencyGraph/types.d.ts:23:9 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode" +// src/components/DependencyGraph/types.d.ts:27:9 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode" // src/components/TabbedLayout/RoutedTabs.d.ts:8:5 - (ae-forgotten-export) The symbol "SubRoute_2" needs to be exported by the entry point index.d.ts // src/components/Table/Table.d.ts:20:5 - (ae-forgotten-export) The symbol "SelectedFilters" needs to be exported by the entry point index.d.ts // src/layout/ErrorBoundary/ErrorBoundary.d.ts:8:5 - (ae-forgotten-export) The symbol "SlackChannel" needs to be exported by the entry point index.d.ts From c0990e2586588b8167f1b95cf9b1ad29c7705ac3 Mon Sep 17 00:00:00 2001 From: TA31OU Date: Wed, 3 Sep 2025 14:00:53 +0200 Subject: [PATCH 011/244] Update core-components report-api (again) Signed-off-by: TA31OU --- packages/core-components/report-alpha.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-components/report-alpha.api.md b/packages/core-components/report-alpha.api.md index e258777b9c..32bd2f4939 100644 --- a/packages/core-components/report-alpha.api.md +++ b/packages/core-components/report-alpha.api.md @@ -24,10 +24,10 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'signIn.title': 'Sign In'; readonly 'signIn.loginFailed': 'Login failed'; readonly 'signIn.customProvider.title': 'Custom User'; - readonly 'signIn.customProvider.continue': 'Continue'; readonly 'signIn.customProvider.subtitle': 'Enter your own User ID and credentials.\n This selection will not be stored.'; readonly 'signIn.customProvider.userId': 'User ID'; readonly 'signIn.customProvider.tokenInvalid': 'Token is not a valid OpenID Connect JWT Token'; + readonly 'signIn.customProvider.continue': 'Continue'; readonly 'signIn.customProvider.idToken': 'ID Token (optional)'; readonly 'signIn.guestProvider.title': 'Guest'; readonly 'signIn.guestProvider.enter': 'Enter'; From c67eb95bd2a512fbc72741cf8af85d9415085653 Mon Sep 17 00:00:00 2001 From: Brent Swisher Date: Mon, 8 Sep 2025 08:10:02 -0400 Subject: [PATCH 012/244] Fix status code of unit test Signed-off-by: Brent Swisher --- .../src/actions/fetchDSN.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.test.ts b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.test.ts index 6396381435..4140bf893b 100644 --- a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.test.ts +++ b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.test.ts @@ -130,7 +130,7 @@ describe('sentry:fetch:dsn action', () => { http.get( `https://sentry.io/api/0/projects/${actionContext.input.organizationSlug}/${actionContext.input.projectSlug}/keys/`, async () => { - return HttpResponse.text('Bad response', { status: 200 }); + return HttpResponse.text('Bad response', { status: 400 }); }, ), ); From 4d2816dbe908db34a8ecd13e4cb899d6d1b196b5 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 10 Sep 2025 13:54:15 +0100 Subject: [PATCH 013/244] First pass improving theming docs Signed-off-by: Charles de Dreuille --- docs/conf/user-interface/icons.md | 124 +++++ docs/conf/user-interface/index.md | 471 +++++++++++++++++ docs/conf/user-interface/logo.md | 25 + docs/conf/user-interface/sidebar.md | 93 ++++ docs/dls/component-design-guidelines.md | 6 +- docs/dls/design.md | 2 +- docs/features/search/how-to-guides.md | 2 +- docs/getting-started/app-custom-theme.md | 613 ----------------------- microsite/sidebars.ts | 11 +- 9 files changed, 729 insertions(+), 618 deletions(-) create mode 100644 docs/conf/user-interface/icons.md create mode 100644 docs/conf/user-interface/index.md create mode 100644 docs/conf/user-interface/logo.md create mode 100644 docs/conf/user-interface/sidebar.md delete mode 100644 docs/getting-started/app-custom-theme.md diff --git a/docs/conf/user-interface/icons.md b/docs/conf/user-interface/icons.md new file mode 100644 index 0000000000..44b8782430 --- /dev/null +++ b/docs/conf/user-interface/icons.md @@ -0,0 +1,124 @@ +--- +id: icons +title: Customizing Icons +sidebar_label: Icons +description: Customizing Icons +--- + +So far you've seen how to create your own theme and add your own logo, in the following sections you'll be shown how to override the existing icons and how to add more icons + +## Custom Icons + +You can also customize the Project's _default_ icons. + +You can change the following [icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx). + +### Requirements + +- Files in `.svg` format +- React components created for the icons + +### Create React Component + +In your front-end application, locate the `src` folder. We suggest creating the `assets/icons` directory and `CustomIcons.tsx` file. + +```tsx title="customIcons.tsx" +import { SvgIcon, SvgIconProps } from '@material-ui/core'; + +export const ExampleIcon = (props: SvgIconProps) => ( + + + +); +``` + +### Using the custom icon + +Supply your custom icon in `packages/app/src/App.tsx` + +```tsx title="packages/app/src/App.tsx" +/* highlight-add-next-line */ +import { ExampleIcon } from './assets/icons/CustomIcons' + + +const app = createApp({ + apis, + components: { + {/* ... */} + }, + themes: [ + {/* ... */} + ], + /* highlight-add-start */ + icons: { + github: ExampleIcon, + }, + /* highlight-add-end */ + bindRoutes({ bind }) { + {/* ... */} + } +}) +``` + +## Adding Icons + +You can add more icons, if the [default icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx) do not fit your needs, so that they can be used in other places like for Links in your entities. For this example we'll be using icons from[Material UI](https://v4.mui.com/components/material-icons/) and specifically the `AlarmIcon`. Here's how to do that: + +1. First you will want to open your `App.tsx` in `/packages/app/src` +2. Then you want to import your icon, add this to the rest of your imports: `import AlarmIcon from '@material-ui/icons/Alarm';` +3. Next you want to add the icon like this to your `createApp`: + + ```tsx title="packages/app/src/App.tsx" + const app = createApp({ + apis: ..., + plugins: ..., + /* highlight-add-start */ + icons: { + alert: AlarmIcon, + }, + /* highlight-add-end */ + themes: ..., + components: ..., + }); + ``` + +4. Now we can reference `alert` for our icon in our entity links like this: + + ```yaml + apiVersion: backstage.io/v1alpha1 + kind: Component + metadata: + name: artist-lookup + description: Artist Lookup + links: + - url: https://example.com/alert + title: Alerts + icon: alert + ``` + + And this is the result: + + ![Example Link with Alert icon](../../assets/getting-started/add-icons-links-example.png) + + Another way you can use these icons is from the `AppContext` like this: + + ```ts + import { useApp } from '@backstage/core-plugin-api'; + + const app = useApp(); + const alertIcon = app.getSystemIcon('alert'); + ``` + + You might want to use this method if you have an icon you want to use in several locations. + +:::note Note + +If the icon is not available as one of the default icons or one you've added then it will fall back to Material UI's `LanguageIcon` + +::: diff --git a/docs/conf/user-interface/index.md b/docs/conf/user-interface/index.md new file mode 100644 index 0000000000..9be726d2dc --- /dev/null +++ b/docs/conf/user-interface/index.md @@ -0,0 +1,471 @@ +--- +id: index +title: Customizing Your App's UI +sidebar_label: Introduction +description: Learn how to customize the look and feel of your Backstage app, including theming and branding options. +--- + +Backstage offers built-in support for both light and dark themes, making it easy to get started with a professional look and feel. But many teams want to go further—tailoring the interface to reflect their organization’s unique brand, identity, and experience. + +This section explores the different ways you can customize the appearance of your Backstage instance. You'll learn how the theming system is structured today, how to work with the two coexisting UI systems, and how to define themes that align with your visual language. + +## Theming architecture overview + +Backstage currently supports two parallel UI systems. The original theming and component model is built on Material UI (MUI), a popular React-based framework. More recently, Backstage introduced Backstage UI (BUI), a custom-designed, CSS-first system developed to meet the platform’s evolving needs. Both systems are supported today, with many parts of the ecosystem still using MUI while new components adopt BUI. + +
+
+

MUI (Legacy)

+
    +
  • Theming: JS-based with UnifiedThemeProvider
  • +
  • Coverage: Most existing plugins
  • +
  • Documentation: mui.com
  • +
+
+
+

Backstage UI (New)

+
    +
  • Theming: CSS variables and tokens
  • +
  • Coverage: Growing, focused on new work
  • +
  • Documentation: ui.backstage.io
  • +
+
+
+ +:::info +We recognize that maintaining two separate theming systems is not ideal. Because of the fundamental architectural differences between MUI and Backstage UI, it can be challenging to automate theme updates or know exactly which theme to modify for a given component. Our recommendation is to inspect the component’s code and check its class names: if you see a class name starting with `bui`, you should use the Backstage UI theming approach to style it. +::: + +## Creating custom themes + +During the transition to Backstage UI, you will need to maintain themes in two places: some components and plugins still rely on MUI, while others use Backstage UI. At this time, there is no automated solution to generate MUI themes from your Backstage UI theme, so you will need to manage both separately until the migration is complete. + +```tsx title="packages/app/src/App.tsx" +/* highlight-add-start */ +import { lightTheme, darkTheme } from './themes'; // MUI themes +import './styles.css'; // Backstage UI (BUI) theme +/* highlight-add-end */ + +const app = createApp({ + apis, + components, + /* highlight-add-start */ + themes: [ + { + id: 'light', + title: 'Light theme', + variant: 'light', + icon: , + Provider: ({ children }) => ( + + ), + }, + { + id: 'dark', + title: 'Dark theme', + variant: 'dark', + icon: , + Provider: ({ children }) => ( + + ), + }, + ], + /* highlight-add-end */ +}); +``` + +| Name | Description | +| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | Each theme has a unique `id` | +| `title` | This will be shown in the settings page to select the right theme. | +| `variant` | This can be either `light` or `dark`. This is also refered as `mode`. On the `body` of your app we are inserting a data attribute to set the theme based on this value `data-theme-mode="light"`. | +| `icon` | This will be shown in the settings page as a visual element to complement the title. | +| `Provider` | This is needed to set the legacy theme with MUI only. This will be become redundant later on when we fully replace with BUI but for now you need to have it for MUI to work. BUI is based on CSS and don't rely on any global providers. | + +:::note +Your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `themes.light` and `themes.dark` from [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). Be sure to provide both `light` and `dark` modes so users can choose their preference. +::: + +## Create a theme for Backstage UI (New) + +Backstage UI is built entirely using CSS. By default we are providing a default theme that include all our core CSS variables and component styles. To start customising Backstage UI to match your brand you need to create a new CSS file and import it directly in `packages/app/src/App.tsx`. All styles declared in this file will override the default styles. As your file grow you can organise it the way you want or even import multiple files. + +Backstage UI is using light by default under `:root` but you can target it more specifically using the data attribute for mode + +```css title="packages/app/src/styles.css" +:root { + /* Use :root to set styles for both light and dark themes */ + .bui-Button { + background-color: #000; + color: #fff; + } +} + +[data-theme-mode='light'] { + /* Light theme specific styles */ +  --bui-bg: #f8f8f8; + --bui-fg-primary: #000; +} + +[data-theme-mode='dark'] { + /* Dark theme specific styles */ +  --bui-bg: #333333; + --bui-fg-primary: #fff; +} +``` + +### Available tokens + +### Component class names + +### Custom font + +## Create a theme for MUI (Legacy) + +To customize the appearance of your Backstage app using the legacy MUI theming system, you can define your own theme by extending the built-in light or dark themes. This is done using the createUnifiedTheme utility provided by the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. This function allows you to override key aspects of the theme—such as color palette, typography, spacing, and shape—while preserving Backstage’s base configuration and component compatibility. + +The example below shows how to create a new theme based on the default light theme: + +```ts title="packages/app/src/themes.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; + +export const lightTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + }), + fontFamily: 'Comic Sans MS', + defaultPageTheme: 'home', +}); + +export const darkTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.dark, + }), + fontFamily: 'Comic Sans MS', + defaultPageTheme: 'home', +}); +``` + +You can also create a theme from scratch that matches the `BackstageTheme` type exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). See the +[Material UI docs on theming](https://material-ui.com/customization/theming/) for more information about how that can be done. + +
+ Example of a custom MUI theme + +For a more complete example of a custom theme including Backstage and Material UI component overrides, see the [Aperture theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts) from the [Backstage demo site](https://demo.backstage.io). + +```ts title="packages/app/src/themes.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + genPageTheme, + palettes, + shapes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: { + ...palettes.light, + primary: { + main: '#343b58', + }, + secondary: { + main: '#565a6e', + }, + error: { + main: '#8c4351', + }, + warning: { + main: '#8f5e15', + }, + info: { + main: '#34548a', + }, + success: { + main: '#485e30', + }, + background: { + default: '#d5d6db', + paper: '#d5d6db', + }, + banner: { + info: '#34548a', + error: '#8c4351', + text: '#343b58', + link: '#565a6e', + }, + errorBackground: '#8c4351', + warningBackground: '#8f5e15', + infoBackground: '#343b58', + navigation: { + background: '#343b58', + indicator: '#8f5e15', + color: '#d5d6db', + selectedColor: '#ffffff', + }, + }, + }), + defaultPageTheme: 'home', + fontFamily: 'Comic Sans MS', + /* below drives the header colors */ + pageTheme: { + home: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), + documentation: genPageTheme({ + colors: ['#8c4351', '#343b58'], + shape: shapes.wave2, + }), + tool: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.round }), + service: genPageTheme({ + colors: ['#8c4351', '#343b58'], + shape: shapes.wave, + }), + website: genPageTheme({ + colors: ['#8c4351', '#343b58'], + shape: shapes.wave, + }), + library: genPageTheme({ + colors: ['#8c4351', '#343b58'], + shape: shapes.wave, + }), + other: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), + app: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), + apis: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), + }, +}); +``` + +
+ +
+ Custom Typography + +When creating a custom theme you can also customize various aspects of the default typography, here's an example using simplified theme: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + typography: { + htmlFontSize: 16, + fontFamily: 'Arial, sans-serif', + h1: { + fontSize: 54, + fontWeight: 700, + marginBottom: 10, + }, + h2: { + fontSize: 40, + fontWeight: 700, + marginBottom: 8, + }, + h3: { + fontSize: 32, + fontWeight: 700, + marginBottom: 6, + }, + h4: { + fontWeight: 700, + fontSize: 28, + marginBottom: 6, + }, + h5: { + fontWeight: 700, + fontSize: 24, + marginBottom: 4, + }, + h6: { + fontWeight: 700, + fontSize: 20, + marginBottom: 2, + }, + }, + defaultPageTheme: 'home', + }), +}); +``` + +If you wanted to only override a sub-set of the typography setting, for example just `h1` then you would do this: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + defaultTypography, + palettes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + typography: { + ...defaultTypography, + htmlFontSize: 16, + fontFamily: 'Roboto, sans-serif', + h1: { + fontSize: 72, + fontWeight: 700, + marginBottom: 10, + }, + }, + defaultPageTheme: 'home', + }), +}); +``` + +
+ +
+ Custom Fonts + +To add custom fonts, you first need to store the font so that it can be imported. We suggest creating the `assets/fonts` directory in your front-end application `src` folder. + +You can then declare the font style following the `@font-face` syntax from [Material UI Typography](https://mui.com/material-ui/customization/typography/). + +After that you can then utilize the `styleOverrides` of `MuiCssBaseline` under components to add a font to the `@font-face` array. + +```ts title="packages/app/src/theme/myTheme.ts" +import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2'; + +const myCustomFont = { + fontFamily: 'My-Custom-Font', + fontStyle: 'normal', + fontDisplay: 'swap', + fontWeight: 300, + src: ` + local('My-Custom-Font'), + url(${MyCustomFont}) format('woff2'), + `, +}; + +export const myTheme = createUnifiedTheme({ + fontFamily: 'My-Custom-Font', + palette: palettes.light, + components: { + MuiCssBaseline: { + styleOverrides: { + '@font-face': [myCustomFont], + }, + }, + }, +}); +``` + +If you want to utilize different or multiple fonts, then you can set the top level `fontFamily` to what you want for your body, and then override `fontFamily` in `typography` to control fonts for various headings. + +```ts title="packages/app/src/theme/myTheme.ts" +import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2'; +import myAwesomeFont from '../assets/fonts/My-Awesome-Font.woff2'; + +const myCustomFont = { + fontFamily: 'My-Custom-Font', + fontStyle: 'normal', + fontDisplay: 'swap', + fontWeight: 300, + src: ` + local('My-Custom-Font'), + url(${MyCustomFont}) format('woff2'), + `, +}; + +const myAwesomeFont = { + fontFamily: 'My-Awesome-Font', + fontStyle: 'normal', + fontDisplay: 'swap', + fontWeight: 300, + src: ` + local('My-Awesome-Font'), + url(${myAwesomeFont}) format('woff2'), + `, +}; + +export const myTheme = createUnifiedTheme({ + fontFamily: 'My-Custom-Font', + components: { + MuiCssBaseline: { + styleOverrides: { + '@font-face': [myCustomFont, myAwesomeFont], + }, + }, + }, + ...createBaseThemeOptions({ + palette: palettes.light, + typography: { + ...defaultTypography, + htmlFontSize: 16, + fontFamily: 'My-Custom-Font', + h1: { + fontSize: 72, + fontWeight: 700, + marginBottom: 10, + fontFamily: 'My-Awesome-Font', + }, + }, + defaultPageTheme: 'home', + }), +}); +``` + +
+ +
+ Overriding Backstage and Material UI components styles + +When creating a custom theme you would be applying different values to component's CSS rules that use the theme object. For example, a Backstage component's styles might look like this: + +```tsx +const useStyles = makeStyles( + theme => ({ + header: { + padding: theme.spacing(3), + boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)', + backgroundImage: theme.page.backgroundImage, + }, + }), + { name: 'BackstageHeader' }, +); +``` + +Notice how the `padding` is getting its value from `theme.spacing`, that means that setting a value for spacing in your custom theme would affect this component padding property and the same goes for `backgroundImage` which uses `theme.page.backgroundImage`. However, the `boxShadow` property doesn't reference any value from the theme, that means that creating a custom theme wouldn't be enough to alter the `box-shadow` property or to add css rules that aren't already defined like a margin. For these cases you should also create an override. + +Here's how you would do that: + +```ts title="packages/app/src/theme/myTheme.ts" +import { + createBaseThemeOptions, + createUnifiedTheme, + palettes, +} from '@backstage/theme'; + +export const myTheme = createUnifiedTheme({ + ...createBaseThemeOptions({ + palette: palettes.light, + }), + fontFamily: 'Comic Sans MS', + defaultPageTheme: 'home', + components: { + BackstageHeader: { + styleOverrides: { + header: ({ theme }) => ({ + width: 'auto', + margin: '20px', + boxShadow: 'none', + borderBottom: `4px solid ${theme.palette.primary.main}`, + }), + }, + }, + }, +}); +``` + +
diff --git a/docs/conf/user-interface/logo.md b/docs/conf/user-interface/logo.md new file mode 100644 index 0000000000..35789d6330 --- /dev/null +++ b/docs/conf/user-interface/logo.md @@ -0,0 +1,25 @@ +--- +id: logo +title: Customizing Your Logo +sidebar_label: Logo +description: Learn how to customize your logo. +--- + +In addition to a custom theme, you can also customize the logo displayed at the far top left of the site. + +In your frontend app, locate `src/components/Root/` folder. You'll find two components: + +- `LogoFull.tsx` - A larger logo used when the Sidebar navigation is opened. +- `LogoIcon.tsx` - A smaller logo used when the Sidebar navigation is closed. + +To replace the images, you can simply replace the relevant code in those components with raw SVG definitions. + +You can also use another web image format such as PNG by importing it. To do this, place your new image into a new subdirectory such as `src/components/Root/logo/my-company-logo.png`, and then add this code: + +```tsx +import MyCustomLogoFull from './logo/my-company-logo.png'; + +const LogoFull = () => { + return ; +}; +``` diff --git a/docs/conf/user-interface/sidebar.md b/docs/conf/user-interface/sidebar.md new file mode 100644 index 0000000000..f66e6bd106 --- /dev/null +++ b/docs/conf/user-interface/sidebar.md @@ -0,0 +1,93 @@ +--- +id: sidebar +title: Customizing Your Sidebar +sidebar_label: Sidebar +description: Learn how to customize the look and feel of your Sidebar. +--- + +As you've seen there are many ways that you can customize your Backstage app. The following section will show you how you can customize the sidebar. + +## Sidebar Sub-menu + +For this example we'll show you how you can expand the sidebar with a sub-menu: + +1. Open the `Root.tsx` file located in `packages/app/src/components/Root` as this is where the sidebar code lives +2. Then we want to add the following import for `useApp`: + + ```tsx title="packages/app/src/components/Root/Root.tsx" + import { useApp } from '@backstage/core-plugin-api'; + ``` + +3. Then update the `@backstage/core-components` import like this: + + ```tsx title="packages/app/src/components/Root/Root.tsx" + import { + Sidebar, + sidebarConfig, + SidebarDivider, + SidebarGroup, + SidebarItem, + SidebarPage, + SidebarScrollWrapper, + SidebarSpace, + useSidebarOpenState, + Link, + /* highlight-add-start */ + GroupIcon, + SidebarSubmenu, + SidebarSubmenuItem, + /* highlight-add-end */ + } from '@backstage/core-components'; + ``` + +4. Finally replace `` with this: + + ```tsx title="packages/app/src/components/Root/Root.tsx" + + + + + + + + + + + + + + ``` + +When you startup your Backstage app and hover over the Home option on the sidebar you'll now see a nice sub-menu appear with links to the various Kinds in your Catalog. It would look like this: + +![Sidebar sub-menu example](./../../assets/getting-started/sidebar-submenu-example.png) + +You can see more ways to use this in the [Storybook Sidebar examples](https://backstage.io/storybook/?path=/story/layout-sidebar--sample-scalable-sidebar) diff --git a/docs/dls/component-design-guidelines.md b/docs/dls/component-design-guidelines.md index 35e2f987d2..17e9d1f11a 100644 --- a/docs/dls/component-design-guidelines.md +++ b/docs/dls/component-design-guidelines.md @@ -103,6 +103,8 @@ accessibility. [7]: https://v4.mui.com/components/cards/ [8]: https://v4.mui.com/customization/palette/#default-values [9]: https://v4.mui.com/customization/typography/ -[10]: https://backstage.io/docs/getting-started/app-custom-theme -[11]: https://backstage.io/docs/getting-started/app-custom-theme#overriding-backstage-and-material-ui-components-styles +[10]: https://backstage.io/docs/conf/user-interface + + + [12]: https://v4.mui.com/customization/default-theme/#explore diff --git a/docs/dls/design.md b/docs/dls/design.md index 7e2ae90528..e988d1032f 100644 --- a/docs/dls/design.md +++ b/docs/dls/design.md @@ -127,7 +127,7 @@ your own plugin for Backstage. **[Discord](https://discord.gg/backstage-687207715902193673)** - all design questions should be directed to the _#design_ channel. -**[Customize Backstage's look and feel](https://backstage.io/docs/getting-started/app-custom-theme)** - +**[Customizing Your App's UI](https://backstage.io/docs/conf/user-interface)** - How to customize the look and feel of your Backstage instance by extending the theme. diff --git a/docs/features/search/how-to-guides.md b/docs/features/search/how-to-guides.md index 7055db1138..f0823ac47e 100644 --- a/docs/features/search/how-to-guides.md +++ b/docs/features/search/how-to-guides.md @@ -116,7 +116,7 @@ indexBuilder.addCollator({ The default highlighting styling for matched terms in search results is your browsers default styles for the `` HTML tag. If you want to customize how highlighted terms look you can follow Backstage's guide on how to -[Customize the look-and-feel of your App](https://backstage.io/docs/getting-started/app-custom-theme) +[Customizing Your App's UI](https://backstage.io/docs/conf/user-interface) to create an override with your preferred styling. For example, using the new MUI V4+V5 unified theming method, the following will result diff --git a/docs/getting-started/app-custom-theme.md b/docs/getting-started/app-custom-theme.md deleted file mode 100644 index 38f2fd4c98..0000000000 --- a/docs/getting-started/app-custom-theme.md +++ /dev/null @@ -1,613 +0,0 @@ ---- -id: app-custom-theme -title: Customize the look-and-feel of your App -description: Documentation on Customizing look and feel of the App ---- - -Backstage ships with a default theme with a light and dark mode variant. The themes are provided as a part of the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package, which also includes utilities for customizing the default theme, or creating completely new themes. - -## Creating a Custom Theme - -The easiest way to create a new theme is to use the `createUnifiedTheme` function exported by the [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme) package. You can use it to override some basic parameters of the default theme such as the color palette and font. - -For example, you can create a new theme based on the default light theme like this: - -```ts title="packages/app/src/theme/myTheme.ts" -import { - createBaseThemeOptions, - createUnifiedTheme, - palettes, -} from '@backstage/theme'; - -export const myTheme = createUnifiedTheme({ - ...createBaseThemeOptions({ - palette: palettes.light, - }), - fontFamily: 'Comic Sans MS', - defaultPageTheme: 'home', -}); -``` - -:::note Note - -we recommend creating a `theme` folder in `packages/app/src` to place your theme file to keep things nicely organized. - -::: - -You can also create a theme from scratch that matches the `BackstageTheme` type exported by [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). See the -[Material UI docs on theming](https://material-ui.com/customization/theming/) for more information about how that can be done. - -## Using your Custom Theme - -To add a custom theme to your Backstage app, you pass it as configuration to `createApp`. - -For example, adding the theme that we created in the previous section can be done like this: - -```tsx title="packages/app/src/App.tsx" -import { createApp } from '@backstage/app-defaults'; -import { ThemeProvider } from '@material-ui/core/styles'; -import CssBaseline from '@material-ui/core/CssBaseline'; -import LightIcon from '@material-ui/icons/WbSunny'; -import { UnifiedThemeProvider} from '@backstage/theme'; -import { myTheme } from './themes/myTheme'; - -const app = createApp({ - apis: ..., - plugins: ..., - themes: [{ - id: 'my-theme', - title: 'My Custom Theme', - variant: 'light', - icon: , - Provider: ({ children }) => ( - - ), - }] -}) -``` - -Note that your list of custom themes overrides the default themes. If you still want to use the default themes, they are exported as `themes.light` and `themes.dark` from [`@backstage/theme`](https://www.npmjs.com/package/@backstage/theme). - -## Example of a custom theme - -```ts title="packages/app/src/theme/myTheme.ts" -import { - createBaseThemeOptions, - createUnifiedTheme, - genPageTheme, - palettes, - shapes, -} from '@backstage/theme'; - -export const myTheme = createUnifiedTheme({ - ...createBaseThemeOptions({ - palette: { - ...palettes.light, - primary: { - main: '#343b58', - }, - secondary: { - main: '#565a6e', - }, - error: { - main: '#8c4351', - }, - warning: { - main: '#8f5e15', - }, - info: { - main: '#34548a', - }, - success: { - main: '#485e30', - }, - background: { - default: '#d5d6db', - paper: '#d5d6db', - }, - banner: { - info: '#34548a', - error: '#8c4351', - text: '#343b58', - link: '#565a6e', - }, - errorBackground: '#8c4351', - warningBackground: '#8f5e15', - infoBackground: '#343b58', - navigation: { - background: '#343b58', - indicator: '#8f5e15', - color: '#d5d6db', - selectedColor: '#ffffff', - }, - }, - }), - defaultPageTheme: 'home', - fontFamily: 'Comic Sans MS', - /* below drives the header colors */ - pageTheme: { - home: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), - documentation: genPageTheme({ - colors: ['#8c4351', '#343b58'], - shape: shapes.wave2, - }), - tool: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.round }), - service: genPageTheme({ - colors: ['#8c4351', '#343b58'], - shape: shapes.wave, - }), - website: genPageTheme({ - colors: ['#8c4351', '#343b58'], - shape: shapes.wave, - }), - library: genPageTheme({ - colors: ['#8c4351', '#343b58'], - shape: shapes.wave, - }), - other: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), - app: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), - apis: genPageTheme({ colors: ['#8c4351', '#343b58'], shape: shapes.wave }), - }, -}); -``` - -For a more complete example of a custom theme including Backstage and Material UI component overrides, see the [Aperture theme](https://github.com/backstage/demo/blob/master/packages/app/src/theme/aperture.ts) from the [Backstage demo site](https://demo.backstage.io). - -## Custom Typography - -When creating a custom theme you can also customize various aspects of the default typography, here's an example using simplified theme: - -```ts title="packages/app/src/theme/myTheme.ts" -import { - createBaseThemeOptions, - createUnifiedTheme, - palettes, -} from '@backstage/theme'; - -export const myTheme = createUnifiedTheme({ - ...createBaseThemeOptions({ - palette: palettes.light, - typography: { - htmlFontSize: 16, - fontFamily: 'Arial, sans-serif', - h1: { - fontSize: 54, - fontWeight: 700, - marginBottom: 10, - }, - h2: { - fontSize: 40, - fontWeight: 700, - marginBottom: 8, - }, - h3: { - fontSize: 32, - fontWeight: 700, - marginBottom: 6, - }, - h4: { - fontWeight: 700, - fontSize: 28, - marginBottom: 6, - }, - h5: { - fontWeight: 700, - fontSize: 24, - marginBottom: 4, - }, - h6: { - fontWeight: 700, - fontSize: 20, - marginBottom: 2, - }, - }, - defaultPageTheme: 'home', - }), -}); -``` - -If you wanted to only override a sub-set of the typography setting, for example just `h1` then you would do this: - -```ts title="packages/app/src/theme/myTheme.ts" -import { - createBaseThemeOptions, - createUnifiedTheme, - defaultTypography, - palettes, -} from '@backstage/theme'; - -export const myTheme = createUnifiedTheme({ - ...createBaseThemeOptions({ - palette: palettes.light, - typography: { - ...defaultTypography, - htmlFontSize: 16, - fontFamily: 'Roboto, sans-serif', - h1: { - fontSize: 72, - fontWeight: 700, - marginBottom: 10, - }, - }, - defaultPageTheme: 'home', - }), -}); -``` - -## Custom Fonts - -To add custom fonts, you first need to store the font so that it can be imported. We suggest creating the `assets/fonts` directory in your front-end application `src` folder. - -You can then declare the font style following the `@font-face` syntax from [Material UI Typography](https://mui.com/material-ui/customization/typography/). - -After that you can then utilize the `styleOverrides` of `MuiCssBaseline` under components to add a font to the `@font-face` array. - -```ts title="packages/app/src/theme/myTheme.ts" -import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2'; - -const myCustomFont = { - fontFamily: 'My-Custom-Font', - fontStyle: 'normal', - fontDisplay: 'swap', - fontWeight: 300, - src: ` - local('My-Custom-Font'), - url(${MyCustomFont}) format('woff2'), - `, -}; - -export const myTheme = createUnifiedTheme({ - fontFamily: 'My-Custom-Font', - palette: palettes.light, - components: { - MuiCssBaseline: { - styleOverrides: { - '@font-face': [myCustomFont], - }, - }, - }, -}); -``` - -If you want to utilize different or multiple fonts, then you can set the top level `fontFamily` to what you want for your body, and then override `fontFamily` in `typography` to control fonts for various headings. - -```ts title="packages/app/src/theme/myTheme.ts" -import MyCustomFont from '../assets/fonts/My-Custom-Font.woff2'; -import myAwesomeFont from '../assets/fonts/My-Awesome-Font.woff2'; - -const myCustomFont = { - fontFamily: 'My-Custom-Font', - fontStyle: 'normal', - fontDisplay: 'swap', - fontWeight: 300, - src: ` - local('My-Custom-Font'), - url(${MyCustomFont}) format('woff2'), - `, -}; - -const myAwesomeFont = { - fontFamily: 'My-Awesome-Font', - fontStyle: 'normal', - fontDisplay: 'swap', - fontWeight: 300, - src: ` - local('My-Awesome-Font'), - url(${myAwesomeFont}) format('woff2'), - `, -}; - -export const myTheme = createUnifiedTheme({ - fontFamily: 'My-Custom-Font', - components: { - MuiCssBaseline: { - styleOverrides: { - '@font-face': [myCustomFont, myAwesomeFont], - }, - }, - }, - ...createBaseThemeOptions({ - palette: palettes.light, - typography: { - ...defaultTypography, - htmlFontSize: 16, - fontFamily: 'My-Custom-Font', - h1: { - fontSize: 72, - fontWeight: 700, - marginBottom: 10, - fontFamily: 'My-Awesome-Font', - }, - }, - defaultPageTheme: 'home', - }), -}); -``` - -## Overriding Backstage and Material UI components styles - -When creating a custom theme you would be applying different values to component's CSS rules that use the theme object. For example, a Backstage component's styles might look like this: - -```tsx -const useStyles = makeStyles( - theme => ({ - header: { - padding: theme.spacing(3), - boxShadow: '0 0 8px 3px rgba(20, 20, 20, 0.3)', - backgroundImage: theme.page.backgroundImage, - }, - }), - { name: 'BackstageHeader' }, -); -``` - -Notice how the `padding` is getting its value from `theme.spacing`, that means that setting a value for spacing in your custom theme would affect this component padding property and the same goes for `backgroundImage` which uses `theme.page.backgroundImage`. However, the `boxShadow` property doesn't reference any value from the theme, that means that creating a custom theme wouldn't be enough to alter the `box-shadow` property or to add css rules that aren't already defined like a margin. For these cases you should also create an override. - -Here's how you would do that: - -```ts title="packages/app/src/theme/myTheme.ts" -import { - createBaseThemeOptions, - createUnifiedTheme, - palettes, -} from '@backstage/theme'; - -export const myTheme = createUnifiedTheme({ - ...createBaseThemeOptions({ - palette: palettes.light, - }), - fontFamily: 'Comic Sans MS', - defaultPageTheme: 'home', - components: { - BackstageHeader: { - styleOverrides: { - header: ({ theme }) => ({ - width: 'auto', - margin: '20px', - boxShadow: 'none', - borderBottom: `4px solid ${theme.palette.primary.main}`, - }), - }, - }, - }, -}); -``` - -## Custom Logo - -In addition to a custom theme, you can also customize the logo displayed at the far top left of the site. - -In your frontend app, locate `src/components/Root/` folder. You'll find two components: - -- `LogoFull.tsx` - A larger logo used when the Sidebar navigation is opened. -- `LogoIcon.tsx` - A smaller logo used when the Sidebar navigation is closed. - -To replace the images, you can simply replace the relevant code in those components with raw SVG definitions. - -You can also use another web image format such as PNG by importing it. To do this, place your new image into a new subdirectory such as `src/components/Root/logo/my-company-logo.png`, and then add this code: - -```tsx -import MyCustomLogoFull from './logo/my-company-logo.png'; - -const LogoFull = () => { - return ; -}; -``` - -## Icons - -So far you've seen how to create your own theme and add your own logo, in the following sections you'll be shown how to override the existing icons and how to add more icons - -### Custom Icons - -You can also customize the Project's _default_ icons. - -You can change the following [icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx). - -#### Requirements - -- Files in `.svg` format -- React components created for the icons - -#### Create React Component - -In your front-end application, locate the `src` folder. We suggest creating the `assets/icons` directory and `CustomIcons.tsx` file. - -```tsx title="customIcons.tsx" -import { SvgIcon, SvgIconProps } from '@material-ui/core'; - -export const ExampleIcon = (props: SvgIconProps) => ( - - - -); -``` - -#### Using the custom icon - -Supply your custom icon in `packages/app/src/App.tsx` - -```tsx title="packages/app/src/App.tsx" -/* highlight-add-next-line */ -import { ExampleIcon } from './assets/icons/CustomIcons' - - -const app = createApp({ - apis, - components: { - {/* ... */} - }, - themes: [ - {/* ... */} - ], - /* highlight-add-start */ - icons: { - github: ExampleIcon, - }, - /* highlight-add-end */ - bindRoutes({ bind }) { - {/* ... */} - } -}) -``` - -### Adding Icons - -You can add more icons, if the [default icons](https://github.com/backstage/backstage/blob/master/packages/app-defaults/src/defaults/icons.tsx) do not fit your needs, so that they can be used in other places like for Links in your entities. For this example we'll be using icons from[Material UI](https://v4.mui.com/components/material-icons/) and specifically the `AlarmIcon`. Here's how to do that: - -1. First you will want to open your `App.tsx` in `/packages/app/src` -2. Then you want to import your icon, add this to the rest of your imports: `import AlarmIcon from '@material-ui/icons/Alarm';` -3. Next you want to add the icon like this to your `createApp`: - - ```tsx title="packages/app/src/App.tsx" - const app = createApp({ - apis: ..., - plugins: ..., - /* highlight-add-start */ - icons: { - alert: AlarmIcon, - }, - /* highlight-add-end */ - themes: ..., - components: ..., - }); - ``` - -4. Now we can reference `alert` for our icon in our entity links like this: - - ```yaml - apiVersion: backstage.io/v1alpha1 - kind: Component - metadata: - name: artist-lookup - description: Artist Lookup - links: - - url: https://example.com/alert - title: Alerts - icon: alert - ``` - - And this is the result: - - ![Example Link with Alert icon](../assets/getting-started/add-icons-links-example.png) - - Another way you can use these icons is from the `AppContext` like this: - - ```ts - import { useApp } from '@backstage/core-plugin-api'; - - const app = useApp(); - const alertIcon = app.getSystemIcon('alert'); - ``` - - You might want to use this method if you have an icon you want to use in several locations. - -:::note Note - -If the icon is not available as one of the default icons or one you've added then it will fall back to Material UI's `LanguageIcon` - -::: - -## Custom Sidebar - -As you've seen there are many ways that you can customize your Backstage app. The following section will show you how you can customize the sidebar. - -### Sidebar Sub-menu - -For this example we'll show you how you can expand the sidebar with a sub-menu: - -1. Open the `Root.tsx` file located in `packages/app/src/components/Root` as this is where the sidebar code lives -2. Then we want to add the following import for `useApp`: - - ```tsx title="packages/app/src/components/Root/Root.tsx" - import { useApp } from '@backstage/core-plugin-api'; - ``` - -3. Then update the `@backstage/core-components` import like this: - - ```tsx title="packages/app/src/components/Root/Root.tsx" - import { - Sidebar, - sidebarConfig, - SidebarDivider, - SidebarGroup, - SidebarItem, - SidebarPage, - SidebarScrollWrapper, - SidebarSpace, - useSidebarOpenState, - Link, - /* highlight-add-start */ - GroupIcon, - SidebarSubmenu, - SidebarSubmenuItem, - /* highlight-add-end */ - } from '@backstage/core-components'; - ``` - -4. Finally replace `` with this: - - ```tsx title="packages/app/src/components/Root/Root.tsx" - - - - - - - - - - - - - - ``` - -When you startup your Backstage app and hover over the Home option on the sidebar you'll now see a nice sub-menu appear with links to the various Kinds in your Catalog. It would look like this: - -![Sidebar sub-menu example](./../assets/getting-started/sidebar-submenu-example.png) - -You can see more ways to use this in the [Storybook Sidebar examples](https://backstage.io/storybook/?path=/story/layout-sidebar--sample-scalable-sidebar) - -## Custom Homepage - -In addition to a custom theme, a custom logo, you can also customize the -homepage of your app. Read the full guide on the [next page](homepage.md). - -## Migrating to Material UI v5 - -We now support Material UI v5 in Backstage. Check out our [migration guide](../tutorials/migrate-to-mui5.md) to get started. diff --git a/microsite/sidebars.ts b/microsite/sidebars.ts index 5a408d5d1f..b7e89825ca 100644 --- a/microsite/sidebars.ts +++ b/microsite/sidebars.ts @@ -35,7 +35,6 @@ export default { 'getting-started/config/database', 'getting-started/config/authentication', 'getting-started/configure-app-with-plugins', - 'getting-started/app-custom-theme', 'getting-started/homepage', ], }, @@ -398,6 +397,16 @@ export default { 'conf/reading', 'conf/writing', 'conf/defining', + { + type: 'category', + label: 'User Interface', + items: [ + 'conf/user-interface/index', + 'conf/user-interface/logo', + 'conf/user-interface/icons', + 'conf/user-interface/sidebar', + ], + }, ], Framework: [ { From f23cd8862150f64f109a6cbff2bcce9931fd67fc Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 10 Sep 2025 13:56:59 +0100 Subject: [PATCH 014/244] Fix spelling mistakes Signed-off-by: Charles de Dreuille --- docs/conf/user-interface/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf/user-interface/index.md b/docs/conf/user-interface/index.md index 9be726d2dc..5f2d355137 100644 --- a/docs/conf/user-interface/index.md +++ b/docs/conf/user-interface/index.md @@ -78,7 +78,7 @@ const app = createApp({ | ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `id` | Each theme has a unique `id` | | `title` | This will be shown in the settings page to select the right theme. | -| `variant` | This can be either `light` or `dark`. This is also refered as `mode`. On the `body` of your app we are inserting a data attribute to set the theme based on this value `data-theme-mode="light"`. | +| `variant` | This can be either `light` or `dark`. This is also referred to as `mode`. On the `body` of your app we are inserting a data attribute to set the theme based on this value: `data-theme-mode="light"`. | | `icon` | This will be shown in the settings page as a visual element to complement the title. | | `Provider` | This is needed to set the legacy theme with MUI only. This will be become redundant later on when we fully replace with BUI but for now you need to have it for MUI to work. BUI is based on CSS and don't rely on any global providers. | From 8b25afdf12c0cbfc54a5e5e57eedb9460bb9b874 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 11 Sep 2025 11:32:32 +0100 Subject: [PATCH 015/244] Fix link error Signed-off-by: Charles de Dreuille --- docs/getting-started/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 252884dc54..876af4f0a5 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -157,7 +157,7 @@ Choose the correct next steps for your user role, if you're likely to be deployi - Configuring Backstage - [Adding plugins](./configure-app-with-plugins.md) - - [Customizing the theme](./app-custom-theme.md) + - [Customizing Your App's UI](../conf/user-interface/index.md) - [Populating the homepage](./homepage.md) ### Developer From 99f7e737d61a67aa8879aa10647fbab1b901e94c Mon Sep 17 00:00:00 2001 From: TA31OU Date: Thu, 11 Sep 2025 14:45:29 +0200 Subject: [PATCH 016/244] Merge Signed-off-by: TA31OU --- .changeset/angry-heads-design.md | 5 + .changeset/better-eagles-tickle.md | 5 + .changeset/big-cameras-turn.md | 5 + .changeset/brave-jars-speak.md | 5 + .changeset/chilly-llamas-attend.md | 5 + .changeset/clear-houses-wonder.md | 5 + .changeset/cold-garlics-care.md | 5 + .changeset/create-app-1757429965.md | 5 + .changeset/dirty-spies-drop.md | 5 + .changeset/eighty-numbers-act.md | 5 + .changeset/eleven-doors-down.md | 5 + .changeset/eleven-doors-own.md | 5 + .changeset/funny-eagles-try.md | 7 + .changeset/giant-buttons-flash.md | 5 + .changeset/gold-words-smoke.md | 5 + .changeset/heavy-cats-unite.md | 6 + .changeset/heavy-lies-listen.md | 5 + .changeset/hot-friends-act.md | 5 + .changeset/hungry-carrots-grow.md | 5 + .changeset/itchy-moons-start.md | 5 + .changeset/kind-eyes-worry.md | 5 + .changeset/late-swans-press.md | 5 + .changeset/lemon-jobs-create.md | 5 + .changeset/lovely-actors-love.md | 5 + .changeset/pre.json | 26 +- .changeset/quiet-papayas-mate.md | 5 + .changeset/red-shrimps-fall.md | 5 + .changeset/silent-results-stick.md | 5 + .changeset/stupid-areas-share.md | 5 + .changeset/tangy-squids-film.md | 5 + .changeset/ten-boxes-lie.md | 5 + .changeset/thin-phones-press.md | 5 + .changeset/tiny-spoons-mix.md | 5 + .changeset/tired-cobras-fly.md | 5 + .changeset/warm-emus-itch.md | 5 + .changeset/wet-onions-sneeze.md | 5 + .changeset/young-doodles-enter.md | 5 + .../config/vocabularies/Backstage/accept.txt | 2 + app-config.yaml | 5 + docs/auth/index.md | 1 + docs/auth/openshift/provider.md | 130 +++ .../core-services/actions-registry.md | 2 +- docs/backend-system/core-services/cache.md | 33 + docs/conf/index.md | 22 +- docs/contribute/project-structure.md | 4 - .../well-known-annotations.md | 2 +- docs/features/techdocs/FAQ.md | 6 + .../building-plugins/01-index.md | 2 +- docs/getting-started/index.md | 10 +- docs/references/glossary.md | 2 +- docs/releases/v1.43.0-next.2-changelog.md | 695 ++++++++++++++ lerna.json | 6 - microsite/data/plugins/datacontract.yaml | 10 + .../pluginsSearch/pluginsSearch.tsx | 19 + microsite/src/pages/plugins/index.tsx | 84 +- .../src/pages/plugins/plugins.module.scss | 14 + package.json | 2 +- packages/app-defaults/src/defaults/apis.ts | 18 + packages/app-next/CHANGELOG.md | 27 + packages/app-next/app-config.yaml | 1 - packages/app-next/package.json | 3 +- packages/app/CHANGELOG.md | 25 + packages/app/package.json | 2 +- packages/app/src/identityProviders.ts | 7 + packages/backend-defaults/CHANGELOG.md | 11 + packages/backend-defaults/package.json | 2 +- .../entrypoints/cache/CacheManager.test.ts | 143 +++ .../src/entrypoints/cache/CacheManager.ts | 24 +- .../CHANGELOG.md | 11 + .../package.json | 2 +- packages/backend/package.json | 1 + packages/backend/src/index.ts | 1 + packages/catalog-client/CHANGELOG.md | 23 + packages/catalog-client/package.json | 2 +- packages/cli/CHANGELOG.md | 8 + packages/cli/package.json | 2 +- .../src/modules/build/lib/bundler/config.ts | 8 + packages/config-loader/CHANGELOG.md | 6 + packages/config-loader/package.json | 2 +- .../config-loader/src/schema/collect.test.ts | 10 - .../src/sources/ConfigSources.test.ts | 13 + .../src/sources/ConfigSources.ts | 28 + packages/core-app-api/report.api.md | 7 + .../src/apis/implementations/auth/index.ts | 1 + .../auth/openshift/OpenShiftAuth.ts | 52 ++ .../implementations/auth/openshift/index.ts | 5 +- packages/core-compat-api/CHANGELOG.md | 7 + packages/core-compat-api/package.json | 2 +- packages/core-components/CHANGELOG.md | 7 + packages/core-components/package.json | 4 +- packages/core-components/report-alpha.api.md | 1 + packages/core-components/report.api.md | 1 + .../DependencyGraph/DependencyGraph.test.tsx | 25 +- .../DependencyGraph/DependencyGraph.tsx | 202 ++-- .../HeaderIconLinkRow/HeaderIconLinkRow.tsx | 1 + packages/core-components/src/translation.ts | 3 + packages/core-plugin-api/report.api.md | 5 + .../src/apis/definitions/auth.ts | 17 + packages/create-app/CHANGELOG.md | 6 + packages/create-app/package.json | 2 +- packages/dev-utils/CHANGELOG.md | 8 + packages/dev-utils/package.json | 2 +- .../frontend-defaults/src/createApp.test.tsx | 1 + packages/frontend-plugin-api/report.api.md | 3 + .../src/apis/definitions/auth.ts | 1 + ...eInstanceGithubCredentialsProvider.test.ts | 36 + ...SingleInstanceGithubCredentialsProvider.ts | 10 +- packages/repo-tools/CHANGELOG.md | 7 + packages/repo-tools/package.json | 2 +- packages/ui/CHANGELOG.md | 7 + packages/ui/package.json | 2 +- packages/yarn-plugin/package.json | 1 + .../util/getCurrentBackstageVersion.test.ts | 16 +- .../src/util/getCurrentBackstageVersion.ts | 14 +- plugins/api-docs/CHANGELOG.md | 10 + plugins/api-docs/package.json | 2 +- plugins/app-backend/CHANGELOG.md | 10 + plugins/app-backend/package.json | 2 +- plugins/app-backend/src/index.ts | 1 - plugins/app-node/CHANGELOG.md | 7 + plugins/app-node/package.json | 2 +- plugins/app/report.api.md | 15 + plugins/app/src/defaultApis.ts | 22 + .../.eslintrc.js | 1 + .../README.md | 5 + .../catalog-info.yaml | 10 + .../config.d.ts | 44 + .../dev/index.ts | 26 + .../package.json | 55 ++ .../report.api.md | 28 + .../src/authenticator.test.ts | 226 +++++ .../src/authenticator.ts | 184 ++++ .../src/index.ts | 25 + .../src/module.ts | 45 + .../src/resolvers.ts | 68 ++ plugins/auth-backend/CHANGELOG.md | 10 + ...20250909120000_oidc_client_registration.js | 159 ++++ plugins/auth-backend/package.json | 4 +- plugins/auth-backend/report.sql.md | 53 ++ plugins/auth-backend/src/authPlugin.ts | 3 + .../src/database/OidcDatabase.test.ts | 293 ++++++ .../auth-backend/src/database/OidcDatabase.ts | 397 ++++++++ plugins/auth-backend/src/migrations.test.ts | 118 +++ .../src/service/OidcRouter.test.ts | 875 +++++++++++++++--- .../auth-backend/src/service/OidcRouter.ts | 383 +++++++- .../src/service/OidcService.test.ts | 789 ++++++++++++++++ .../auth-backend/src/service/OidcService.ts | 347 ++++++- plugins/auth-backend/src/service/router.ts | 11 + plugins/auth-node/CHANGELOG.md | 8 + plugins/auth-node/package.json | 3 +- plugins/auth-react/CHANGELOG.md | 8 + plugins/auth-react/package.json | 3 +- plugins/auth/.eslintrc.js | 1 + plugins/auth/CHANGELOG.md | 12 + plugins/auth/README.md | 16 + plugins/auth/catalog-info.yaml | 9 + plugins/auth/dev/index.tsx | 28 + plugins/auth/package.json | 84 ++ plugins/auth/report.api.md | 52 ++ .../components/ConsentPage/ConsentPage.tsx | 246 +++++ .../auth/src/components/ConsentPage/index.ts | 16 + .../ConsentPage/useConsentSession.ts | 144 +++ plugins/auth/src/components/Router.tsx | 29 + plugins/auth/src/index.ts | 16 + plugins/auth/src/plugin.test.ts | 22 + plugins/auth/src/plugin.tsx | 36 + plugins/auth/src/routes.ts | 18 + plugins/auth/src/setupTests.ts | 16 + .../catalog-backend-module-aws/CHANGELOG.md | 10 + .../catalog-backend-module-aws/package.json | 2 +- .../catalog-backend-module-azure/CHANGELOG.md | 8 + .../catalog-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 7 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../catalog-backend-module-gcp/CHANGELOG.md | 7 + .../catalog-backend-module-gcp/package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../catalog-backend-module-gitea/CHANGELOG.md | 8 + .../catalog-backend-module-gitea/package.json | 34 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../CHANGELOG.md | 9 + .../package.json | 2 +- .../catalog-backend-module-ldap/CHANGELOG.md | 7 + .../catalog-backend-module-ldap/package.json | 2 +- .../CHANGELOG.md | 7 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 6 +- .../report-alpha.api.md | 13 - .../report.api.md | 5 + .../src/index.ts | 1 + .../catalogModulePuppetDbEntityProvider.ts | 2 +- .../CHANGELOG.md | 7 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- plugins/catalog-backend/CHANGELOG.md | 10 + plugins/catalog-backend/package.json | 2 +- .../stitcher/markForStitching.test.ts | 135 +++ .../operations/stitcher/markForStitching.ts | 118 ++- plugins/catalog-graph/CHANGELOG.md | 10 + plugins/catalog-graph/package.json | 2 +- plugins/catalog-import/CHANGELOG.md | 11 + plugins/catalog-import/package.json | 2 +- plugins/catalog-node/CHANGELOG.md | 28 + plugins/catalog-node/package.json | 2 +- plugins/catalog-react/CHANGELOG.md | 30 + plugins/catalog-react/package.json | 2 +- plugins/catalog/CHANGELOG.md | 11 + plugins/catalog/package.json | 2 +- plugins/catalog/src/routes.ts | 2 +- plugins/devtools-backend/CHANGELOG.md | 8 + plugins/devtools-backend/package.json | 2 +- plugins/home/CHANGELOG.md | 12 + plugins/home/package.json | 2 +- .../CustomHomepage/CustomHomepageGrid.tsx | 19 +- plugins/kubernetes-backend/CHANGELOG.md | 11 + plugins/kubernetes-backend/package.json | 2 +- .../src/service/KubernetesInitializer.ts | 5 +- plugins/kubernetes-cluster/CHANGELOG.md | 8 + plugins/kubernetes-cluster/package.json | 2 +- plugins/kubernetes/CHANGELOG.md | 9 + plugins/kubernetes/package.json | 2 +- plugins/mcp-actions-backend/CHANGELOG.md | 10 + plugins/mcp-actions-backend/package.json | 2 +- plugins/mcp-actions-backend/src/plugin.ts | 36 +- .../CHANGELOG.md | 10 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- plugins/notifications-backend/CHANGELOG.md | 9 + plugins/notifications-backend/package.json | 2 +- plugins/notifications-node/CHANGELOG.md | 7 + plugins/notifications-node/package.json | 2 +- plugins/notifications/src/alpha.tsx | 7 +- plugins/org-react/CHANGELOG.md | 9 + plugins/org-react/package.json | 2 +- plugins/org/CHANGELOG.md | 9 + plugins/org/package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- plugins/scaffolder-backend/CHANGELOG.md | 12 + plugins/scaffolder-backend/package.json | 2 +- .../notifications-demo/template.yaml | 4 +- .../src/service/router.test.ts | 42 +- .../scaffolder-backend/src/service/router.ts | 9 +- plugins/scaffolder-react/CHANGELOG.md | 10 + plugins/scaffolder-react/package.json | 2 +- .../TaskLogStream/TaskLogStream.tsx | 1 + plugins/scaffolder/CHANGELOG.md | 13 + plugins/scaffolder/package.json | 5 +- .../TemplateListPage.test.tsx | 129 ++- .../TemplateListPage/TemplateListPage.tsx | 24 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- plugins/search/CHANGELOG.md | 9 + plugins/search/package.json | 2 +- .../techdocs-addons-test-utils/CHANGELOG.md | 9 + .../techdocs-addons-test-utils/package.json | 2 +- .../src/test-utils.tsx | 13 + plugins/techdocs-backend/CHANGELOG.md | 11 + .../documented-component/catalog-info.yaml | 14 + .../docs/inner-component-docs/index.md | 5 + .../examples/documented-component/mkdocs.yml | 1 + plugins/techdocs-backend/package.json | 2 +- plugins/techdocs-react/src/helpers.ts | 4 +- plugins/techdocs/CHANGELOG.md | 12 + plugins/techdocs/package.json | 4 +- .../TechDocsReaderPage.test.tsx | 155 +++- .../TechDocsReaderPage/TechDocsReaderPage.tsx | 104 ++- .../TechDocsReaderPageHeader.test.tsx | 33 +- .../TechDocsReaderPageHeader.tsx | 5 +- .../transformers/html/hooks/attributes.ts | 32 + .../reader/transformers/html/hooks/iframes.ts | 7 +- .../reader/transformers/html/hooks/index.ts | 2 + .../reader/transformers/html/hooks/links.ts | 8 +- .../transformers/html/hooks/metatags.ts | 41 + .../reader/transformers/html/transformer.ts | 30 +- .../src/reader/transformers/html/utils.ts | 19 + plugins/user-settings/CHANGELOG.md | 10 + plugins/user-settings/package.json | 2 +- plugins/user-settings/report-alpha.api.md | 2 +- .../AuthProviders/DefaultProviderSettings.tsx | 9 + plugins/user-settings/src/translation.ts | 2 +- yarn.lock | 213 +++-- 301 files changed, 8375 insertions(+), 583 deletions(-) create mode 100644 .changeset/angry-heads-design.md create mode 100644 .changeset/better-eagles-tickle.md create mode 100644 .changeset/big-cameras-turn.md create mode 100644 .changeset/brave-jars-speak.md create mode 100644 .changeset/chilly-llamas-attend.md create mode 100644 .changeset/clear-houses-wonder.md create mode 100644 .changeset/cold-garlics-care.md create mode 100644 .changeset/create-app-1757429965.md create mode 100644 .changeset/dirty-spies-drop.md create mode 100644 .changeset/eighty-numbers-act.md create mode 100644 .changeset/eleven-doors-down.md create mode 100644 .changeset/eleven-doors-own.md create mode 100644 .changeset/funny-eagles-try.md create mode 100644 .changeset/giant-buttons-flash.md create mode 100644 .changeset/gold-words-smoke.md create mode 100644 .changeset/heavy-cats-unite.md create mode 100644 .changeset/heavy-lies-listen.md create mode 100644 .changeset/hot-friends-act.md create mode 100644 .changeset/hungry-carrots-grow.md create mode 100644 .changeset/itchy-moons-start.md create mode 100644 .changeset/kind-eyes-worry.md create mode 100644 .changeset/late-swans-press.md create mode 100644 .changeset/lemon-jobs-create.md create mode 100644 .changeset/lovely-actors-love.md create mode 100644 .changeset/quiet-papayas-mate.md create mode 100644 .changeset/red-shrimps-fall.md create mode 100644 .changeset/silent-results-stick.md create mode 100644 .changeset/stupid-areas-share.md create mode 100644 .changeset/tangy-squids-film.md create mode 100644 .changeset/ten-boxes-lie.md create mode 100644 .changeset/thin-phones-press.md create mode 100644 .changeset/tiny-spoons-mix.md create mode 100644 .changeset/tired-cobras-fly.md create mode 100644 .changeset/warm-emus-itch.md create mode 100644 .changeset/wet-onions-sneeze.md create mode 100644 .changeset/young-doodles-enter.md create mode 100644 docs/auth/openshift/provider.md create mode 100644 docs/releases/v1.43.0-next.2-changelog.md delete mode 100644 lerna.json create mode 100644 microsite/data/plugins/datacontract.yaml create mode 100644 microsite/src/components/pluginsSearch/pluginsSearch.tsx create mode 100644 packages/core-app-api/src/apis/implementations/auth/openshift/OpenShiftAuth.ts rename plugins/catalog-backend-module-puppetdb/src/alpha.ts => packages/core-app-api/src/apis/implementations/auth/openshift/index.ts (84%) create mode 100644 plugins/auth-backend-module-openshift-provider/.eslintrc.js create mode 100644 plugins/auth-backend-module-openshift-provider/README.md create mode 100644 plugins/auth-backend-module-openshift-provider/catalog-info.yaml create mode 100644 plugins/auth-backend-module-openshift-provider/config.d.ts create mode 100644 plugins/auth-backend-module-openshift-provider/dev/index.ts create mode 100644 plugins/auth-backend-module-openshift-provider/package.json create mode 100644 plugins/auth-backend-module-openshift-provider/report.api.md create mode 100644 plugins/auth-backend-module-openshift-provider/src/authenticator.test.ts create mode 100644 plugins/auth-backend-module-openshift-provider/src/authenticator.ts create mode 100644 plugins/auth-backend-module-openshift-provider/src/index.ts create mode 100644 plugins/auth-backend-module-openshift-provider/src/module.ts create mode 100644 plugins/auth-backend-module-openshift-provider/src/resolvers.ts create mode 100644 plugins/auth-backend/migrations/20250909120000_oidc_client_registration.js create mode 100644 plugins/auth-backend/src/database/OidcDatabase.test.ts create mode 100644 plugins/auth-backend/src/database/OidcDatabase.ts create mode 100644 plugins/auth-backend/src/service/OidcService.test.ts create mode 100644 plugins/auth/.eslintrc.js create mode 100644 plugins/auth/CHANGELOG.md create mode 100644 plugins/auth/README.md create mode 100644 plugins/auth/catalog-info.yaml create mode 100644 plugins/auth/dev/index.tsx create mode 100644 plugins/auth/package.json create mode 100644 plugins/auth/report.api.md create mode 100644 plugins/auth/src/components/ConsentPage/ConsentPage.tsx create mode 100644 plugins/auth/src/components/ConsentPage/index.ts create mode 100644 plugins/auth/src/components/ConsentPage/useConsentSession.ts create mode 100644 plugins/auth/src/components/Router.tsx create mode 100644 plugins/auth/src/index.ts create mode 100644 plugins/auth/src/plugin.test.ts create mode 100644 plugins/auth/src/plugin.tsx create mode 100644 plugins/auth/src/routes.ts create mode 100644 plugins/auth/src/setupTests.ts delete mode 100644 plugins/catalog-backend-module-puppetdb/report-alpha.api.md create mode 100644 plugins/techdocs-backend/examples/documented-component/docs/inner-component-docs/index.md create mode 100644 plugins/techdocs/src/reader/transformers/html/hooks/attributes.ts create mode 100644 plugins/techdocs/src/reader/transformers/html/hooks/metatags.ts create mode 100644 plugins/techdocs/src/reader/transformers/html/utils.ts diff --git a/.changeset/angry-heads-design.md b/.changeset/angry-heads-design.md new file mode 100644 index 0000000000..0b4a866fb1 --- /dev/null +++ b/.changeset/angry-heads-design.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Disallow import fallback of critical shared dependencies in module federation. diff --git a/.changeset/better-eagles-tickle.md b/.changeset/better-eagles-tickle.md new file mode 100644 index 0000000000..418f0bcae0 --- /dev/null +++ b/.changeset/better-eagles-tickle.md @@ -0,0 +1,5 @@ +--- +'@backstage/config-loader': patch +--- + +Allow using `BACKSTAGE_ENV` for loading environment specific config files diff --git a/.changeset/big-cameras-turn.md b/.changeset/big-cameras-turn.md new file mode 100644 index 0000000000..6226b17806 --- /dev/null +++ b/.changeset/big-cameras-turn.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Fixed cache namespace and key prefix separator configuration to properly use configured values instead of hardcoded plugin ID. The cache manager now correctly combines the configured namespace with plugin IDs using the configured separator for Redis and Valkey. Memcache and memory store continue to use plugin ID as namespace. diff --git a/.changeset/brave-jars-speak.md b/.changeset/brave-jars-speak.md new file mode 100644 index 0000000000..2060239326 --- /dev/null +++ b/.changeset/brave-jars-speak.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-puppetdb': patch +--- + +**BREAKING ALPHA**: The module has been moved from the `/alpha` export to the root of the package. diff --git a/.changeset/chilly-llamas-attend.md b/.changeset/chilly-llamas-attend.md new file mode 100644 index 0000000000..0a0876ccac --- /dev/null +++ b/.changeset/chilly-llamas-attend.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Updated dependency `dompurify` to `^3.2.4`. diff --git a/.changeset/clear-houses-wonder.md b/.changeset/clear-houses-wonder.md new file mode 100644 index 0000000000..46ada62fbe --- /dev/null +++ b/.changeset/clear-houses-wonder.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +TechDocs page titles have been improved, especially for deeply nested pages. diff --git a/.changeset/cold-garlics-care.md b/.changeset/cold-garlics-care.md new file mode 100644 index 0000000000..960ebe6bd4 --- /dev/null +++ b/.changeset/cold-garlics-care.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-notifications': patch +--- + +Fixed missing app context when rendering the notifications view diff --git a/.changeset/create-app-1757429965.md b/.changeset/create-app-1757429965.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1757429965.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/dirty-spies-drop.md b/.changeset/dirty-spies-drop.md new file mode 100644 index 0000000000..88bff91892 --- /dev/null +++ b/.changeset/dirty-spies-drop.md @@ -0,0 +1,5 @@ +--- +'@backstage/app-defaults': minor +--- + +Add and configure the OpenShift authentication provider to the default APIs. diff --git a/.changeset/eighty-numbers-act.md b/.changeset/eighty-numbers-act.md new file mode 100644 index 0000000000..dc7d504adc --- /dev/null +++ b/.changeset/eighty-numbers-act.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-react': patch +--- + +Update to documentation regarding TechDocs redirects. diff --git a/.changeset/eleven-doors-down.md b/.changeset/eleven-doors-down.md new file mode 100644 index 0000000000..0d380c8ddf --- /dev/null +++ b/.changeset/eleven-doors-down.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-mcp-actions-backend': patch +--- + +Proxy `/.well-known/oauth-authorization-server` to `/.well-known/openid-configuration` on `auth-backend` when `auth.experimentalDynamicClientRegistration.enabled` is enabled. diff --git a/.changeset/eleven-doors-own.md b/.changeset/eleven-doors-own.md new file mode 100644 index 0000000000..1da0297e5c --- /dev/null +++ b/.changeset/eleven-doors-own.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend': patch +--- + +Implementing Dynamic Client Registration with the OIDC server. You can enable this by setting `auth.experimentalDynamicClientRegistration.enabled` in `app-config.yaml`. This is highly experimental, but feedback welcome. diff --git a/.changeset/funny-eagles-try.md b/.changeset/funny-eagles-try.md new file mode 100644 index 0000000000..c5550756e0 --- /dev/null +++ b/.changeset/funny-eagles-try.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-auth-backend': patch +'@backstage/plugin-auth-react': patch +'@backstage/plugin-auth-node': patch +--- + +Updating plugin metadata diff --git a/.changeset/giant-buttons-flash.md b/.changeset/giant-buttons-flash.md new file mode 100644 index 0000000000..97564d37ac --- /dev/null +++ b/.changeset/giant-buttons-flash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth': minor +--- + +Initial publish of the `auth` frontend package diff --git a/.changeset/gold-words-smoke.md b/.changeset/gold-words-smoke.md new file mode 100644 index 0000000000..85141e402c --- /dev/null +++ b/.changeset/gold-words-smoke.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-app-backend': patch +--- + +Internal update to not expose the old `createRouter`. diff --git a/.changeset/heavy-cats-unite.md b/.changeset/heavy-cats-unite.md new file mode 100644 index 0000000000..4875093b0a --- /dev/null +++ b/.changeset/heavy-cats-unite.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-home': patch +--- + +Fixed race condition in CustomHomepageGrid by waiting for storage to load before rendering custom layout to prevent +rendering of the default content. diff --git a/.changeset/heavy-lies-listen.md b/.changeset/heavy-lies-listen.md new file mode 100644 index 0000000000..9f408b1ea8 --- /dev/null +++ b/.changeset/heavy-lies-listen.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes-backend': patch +--- + +Fix a bug where `getDefault` in the `kubernetesFetcherExtensionPoint` had the wrong `this` value diff --git a/.changeset/hot-friends-act.md b/.changeset/hot-friends-act.md new file mode 100644 index 0000000000..37b2e3f112 --- /dev/null +++ b/.changeset/hot-friends-act.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-plugin-api': minor +--- + +Make `openshiftAuthApiRef` available in `@backstage/core-plugin-api`. diff --git a/.changeset/hungry-carrots-grow.md b/.changeset/hungry-carrots-grow.md new file mode 100644 index 0000000000..748ace8d94 --- /dev/null +++ b/.changeset/hungry-carrots-grow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': minor +--- + +Adding redirect handling for TechDocs URLs that reference entities that now reference an external entity for TechDocs. Including tests and documentation. diff --git a/.changeset/itchy-moons-start.md b/.changeset/itchy-moons-start.md new file mode 100644 index 0000000000..e5768b58b2 --- /dev/null +++ b/.changeset/itchy-moons-start.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Render a TechDocs link on the Scaffolder Template List page when templates include either `backstage.io/techdocs-ref` or `backstage.io/techdocs-entity` annotations, using the shared `buildTechDocsURL` helper. Also adds tests to verify both annotations and optional `backstage.io/techdocs-entity-path` are respected. diff --git a/.changeset/kind-eyes-worry.md b/.changeset/kind-eyes-worry.md new file mode 100644 index 0000000000..5568a00e28 --- /dev/null +++ b/.changeset/kind-eyes-worry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-app': minor +--- + +Add implementation of OpenShift authentication provider. diff --git a/.changeset/late-swans-press.md b/.changeset/late-swans-press.md new file mode 100644 index 0000000000..987672bd77 --- /dev/null +++ b/.changeset/late-swans-press.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Prevent deadlock in catalog deferred stitching diff --git a/.changeset/lemon-jobs-create.md b/.changeset/lemon-jobs-create.md new file mode 100644 index 0000000000..d0e28b9c5c --- /dev/null +++ b/.changeset/lemon-jobs-create.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +Add the OpenShift authenticator provider to the default `user-settings` providers page. diff --git a/.changeset/lovely-actors-love.md b/.changeset/lovely-actors-love.md new file mode 100644 index 0000000000..b428a11619 --- /dev/null +++ b/.changeset/lovely-actors-love.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-backend': minor +--- + +Adding new entity that specifies an external entity in the techdocs-entity annotation and updates to documentation regarding TechDocs redirects. diff --git a/.changeset/pre.json b/.changeset/pre.json index dcb0a48960..b1a840849d 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -201,23 +201,42 @@ "@backstage/plugin-techdocs-react": "1.3.2", "@backstage/plugin-user-settings": "0.8.25", "@backstage/plugin-user-settings-backend": "0.3.5", - "@backstage/plugin-user-settings-common": "0.0.1" + "@backstage/plugin-user-settings-common": "0.0.1", + "@backstage/plugin-auth": "0.0.0" }, "changesets": [ + "better-eagles-tickle", + "big-cameras-turn", "brave-bugs-know", + "brave-jars-speak", + "busy-chairs-itch", "cold-donuts-train", "cool-games-rescue", + "create-app-1757429965", "curvy-sites-rhyme", "easy-wings-turn", + "eleven-doors-down", + "eleven-doors-own", "fine-hands-think", + "fix-select-aria-props", "flat-colts-know", + "funny-eagles-try", + "giant-buttons-flash", "giant-zebras-peel", + "gold-words-smoke", + "heavy-cats-unite", + "heavy-lies-listen", "icy-camels-throw", + "itchy-moons-start", + "late-swans-press", "legal-lemons-attend", "lemon-terms-cheer", "lucky-glasses-slide", "mean-sites-cheer", + "olive-moons-burn", "puny-books-fetch", + "quiet-papayas-mate", + "red-shrimps-fall", "ripe-plants-pump", "sharp-carrots-spend", "sixty-pans-prove", @@ -226,9 +245,12 @@ "slick-worms-drum", "social-beers-unite", "sweet-lemons-wonder", + "tangy-squids-film", "tricky-buses-lead", + "warm-emus-itch", "wet-kiwis-strive", "whole-dingos-lay", - "yellow-dragons-float" + "yellow-dragons-float", + "young-doodles-enter" ] } diff --git a/.changeset/quiet-papayas-mate.md b/.changeset/quiet-papayas-mate.md new file mode 100644 index 0000000000..1d2089f4e8 --- /dev/null +++ b/.changeset/quiet-papayas-mate.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Dependency graph can now be opened in full screen mode diff --git a/.changeset/red-shrimps-fall.md b/.changeset/red-shrimps-fall.md new file mode 100644 index 0000000000..1ee3aca7ed --- /dev/null +++ b/.changeset/red-shrimps-fall.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-user-settings': patch +--- + +Tool-tip text correction for the Theme selection in settings page diff --git a/.changeset/silent-results-stick.md b/.changeset/silent-results-stick.md new file mode 100644 index 0000000000..6cb501027c --- /dev/null +++ b/.changeset/silent-results-stick.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fixed a regression that prevented uploads greater than 100KB. Uploads up to 10MB are supported again. diff --git a/.changeset/stupid-areas-share.md b/.changeset/stupid-areas-share.md new file mode 100644 index 0000000000..2238f9d942 --- /dev/null +++ b/.changeset/stupid-areas-share.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Support Techdocs redirect with dompurify 3.2.6+ diff --git a/.changeset/tangy-squids-film.md b/.changeset/tangy-squids-film.md new file mode 100644 index 0000000000..acb5546031 --- /dev/null +++ b/.changeset/tangy-squids-film.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-react': patch +--- + +Fix scaffolder task log stream not having a minimum height diff --git a/.changeset/ten-boxes-lie.md b/.changeset/ten-boxes-lie.md new file mode 100644 index 0000000000..751b01e7d9 --- /dev/null +++ b/.changeset/ten-boxes-lie.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-auth-backend-module-openshift-provider': minor +--- + +Add new `auth-backend-module-openshift-provider`. This authentication provider enables Backstage to sign in with OpenShift. diff --git a/.changeset/thin-phones-press.md b/.changeset/thin-phones-press.md new file mode 100644 index 0000000000..8b3f985772 --- /dev/null +++ b/.changeset/thin-phones-press.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': patch +--- + +Fixes issue with Github credentials provider which fails to match organization name if using allowedInstallationOwners diff --git a/.changeset/tiny-spoons-mix.md b/.changeset/tiny-spoons-mix.md new file mode 100644 index 0000000000..bb607aca3f --- /dev/null +++ b/.changeset/tiny-spoons-mix.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs-addons-test-utils': minor +--- + +Adding catalogApiRef to test-utils to support catalog API usage by TechDocs reader page. diff --git a/.changeset/tired-cobras-fly.md b/.changeset/tired-cobras-fly.md new file mode 100644 index 0000000000..e2e19803f8 --- /dev/null +++ b/.changeset/tired-cobras-fly.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': minor +--- + +Make `openshiftApiRef` available to the new frontend system. diff --git a/.changeset/warm-emus-itch.md b/.changeset/warm-emus-itch.md new file mode 100644 index 0000000000..a7bd51abdb --- /dev/null +++ b/.changeset/warm-emus-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Fix incorrect `defaultTarget` on `createComponentRouteRef`. diff --git a/.changeset/wet-onions-sneeze.md b/.changeset/wet-onions-sneeze.md new file mode 100644 index 0000000000..0fd61d764a --- /dev/null +++ b/.changeset/wet-onions-sneeze.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-app-api': minor +--- + +Add `OpenShiftAuth` helper to create default OAuth flow for OpenShift. diff --git a/.changeset/young-doodles-enter.md b/.changeset/young-doodles-enter.md new file mode 100644 index 0000000000..63e1f33eda --- /dev/null +++ b/.changeset/young-doodles-enter.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +update about card links style for pretty display with other language diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index 56167d6f9f..516eec516f 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -146,6 +146,7 @@ Expedia facto failover Fargate +faqs featureful Figma firehydrant @@ -460,6 +461,7 @@ subfolders subheader subheaders subkey +subpage subpath subroutes substring diff --git a/app-config.yaml b/app-config.yaml index 60842ee61a..eacf9a96aa 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -209,6 +209,11 @@ scaffolder: defaultCommitMessage: 'Initial commit' auth: + experimentalDynamicClientRegistration: + enabled: true + allowedRedirectUriPatterns: + - cursor://* + ### Add auth.keyStore.provider to more granularly control how to store JWK data when running # the auth-backend. # diff --git a/docs/auth/index.md b/docs/auth/index.md index 9f4c229e7f..bff1f3df26 100644 --- a/docs/auth/index.md +++ b/docs/auth/index.md @@ -34,6 +34,7 @@ Backstage comes with many common authentication providers in the core library: - [Okta](okta/provider.md) - [OAuth 2 Custom Proxy](oauth2-proxy/provider.md) - [OneLogin](onelogin/provider.md) +- [OpenShift](openshift/provider.md) - [VMware Cloud](vmware-cloud/provider.md) These built-in providers handle the authentication flow for a particular service, including required scopes, callbacks, etc. These providers are each added to a diff --git a/docs/auth/openshift/provider.md b/docs/auth/openshift/provider.md new file mode 100644 index 0000000000..37c5064580 --- /dev/null +++ b/docs/auth/openshift/provider.md @@ -0,0 +1,130 @@ +--- +id: provider +title: OpenShift Authentication Provider +sidebar_label: OpenShift +description: Adding OpenShift OAuth as an authentication provider in Backstage +--- + +The Backstage `core-plugin-api` package comes with a OpenShift authentication +provider that can authenticate users using OpenShift OAuth. + +## Use Case + +This setup enables the [Kubernetes plugin](../../features/kubernetes/index.md) to access OpenShift clusters using the user's permissions, +leveraging OAuth 2.0 _On-Behalf-Of_ flow via the [Kubernetes Client Side Provider](../../features/kubernetes/authentication.md). + +To make this work, the corresponding `User` entities must exist in the Backstage catalog, +and their names must match the OpenShift users. + +Although the OpenShift authentication provider does not support OIDC natively, +you can still configure it for use with the Kubernetes integration by treating it as an OIDC provider +in the `KubernetesAuthProviders` configuration. + +```ts title="packages/app/src/apis.ts" +import { + KubernetesAuthProviders, + kubernetesAuthProvidersApiRef, +} from '@backstage/plugin-kubernetes'; +import { + googleAuthApiRef, + microsoftAuthApiRef, + openshiftAuthApiRef, +} from '@backstage/core-plugin-api'; + +export const apis: AnyApiFactory[] = [ + // ... + createApiFactory({ + api: kubernetesAuthProvidersApiRef, + deps: { + microsoftAuthApi: microsoftAuthApiRef, + googleAuthApi: googleAuthApiRef, + openshiftAuthApi: openshiftAuthApiRef, + }, + factory({ microsoftAuthApi, googleAuthApi, openshiftAuthApi }) { + return new KubernetesAuthProviders({ + microsoftAuthApi, + googleAuthApi, + oidcProviders: { + openshift: { + async getIdToken(_) { + return await openshiftAuthApi.getAccessToken('user:full'); + }, + }, + }, + }); + }, + }), + //... +]; +``` + +:::note Note + +The OpenShift auth API does **not** implement the `OpenIdConnectApi` interface. In other words, it does **not** return an ID token. +Instead, it returns an **access token**, which is used by the Kubernetes integration in place of an ID token. +This is the only functional difference from the standard OIDC-based authentication flow. + +::: + +## Create an OAuth client in OpenShift + +Make sure that an OAuth client exists in the OpenShift cluster. + +To configure the OpenShift integration, create an [`OAuthClient`](https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/authentication_and_authorization/configuring-oauth-clients). + +The redirect URI must be in the following format: `https:///api/auth/openshift/handler/frame`. + +## Configuration + +The provider configuration can then be added to your `app-config.yaml` under the +root `auth` configuration: + +```yaml +auth: + environment: development + providers: + openshift: + development: + clientId: ${AUTH_OPENSHIFT_CLIENT_ID} + clientSecret: ${AUTH_OPENSHIFT_CLIENT_SECRET} + authorizationUrl: ${AUTH_OPENSHIFT_AUTHORIZATION_URL} + tokenUrl: ${AUTH_OPENSHIFT_TOKEN_URL} + openshiftApiServerUrl: ${OPENSHIFT_API_SERVER_URL} + ## uncomment to set lifespan of user session + # sessionDuration: { hours: 24 } # supports `ms` library format (e.g. '24h', '2 days'), ISO duration, "human duration" as used in code + # sessionDuration: 1d + signIn: + resolvers: + - resolver: displayNameMatchingUserEntityName +``` + +The OpenShift provider is a structure with these configuration keys: + +- `clientId`: The client ID of your OpenShift OAuth client, e.g., `my-backstage` +- `clientSecret`: The client secret tied to the OpenShift OAuth client. +- `authorizationUrl`: The OpenShift OAuth client auth endpoint, format: `https:///oauth/authorize`. +- `tokenUrl`: The OpenShift OAuth client token endpoint, format: `https:///oauth/token`. +- `openshiftApiServerUrl`: The OpenShift API server endpoint, format: `https://`. +- `sessionDuration`: (optional): Lifespan of the user session. +- `signIn`: The configuration for the sign-in process, including the **resolvers** + that should be used to match the user from the auth provider with the user + entity in the Backstage catalog (typically a single resolver is sufficient). + +The provider needs to use the scope **user:full**. + +## Backend Installation + +To add the provider to the backend we will first need to install the package by running this command: + +```bash title="from your Backstage root directory" +yarn --cwd packages/backend add @backstage/plugin-auth-backend-module-openshift-provider +``` + +Then we will need to add this line: + +```ts title="in packages/backend/src/index.ts" +backend.add(import('@backstage/plugin-auth-backend')); +/* highlight-add-start */ +backend.add(import('@backstage/plugin-auth-backend-module-openshift-provider')); +/* highlight-add-end */ +``` diff --git a/docs/backend-system/core-services/actions-registry.md b/docs/backend-system/core-services/actions-registry.md index b1e8fe5f3d..9e493e6bb2 100644 --- a/docs/backend-system/core-services/actions-registry.md +++ b/docs/backend-system/core-services/actions-registry.md @@ -45,7 +45,7 @@ When an action is executed, it receives a context object (`ActionsRegistryAction Here's an example of how to register an action with the Actions Registry Service: ```typescript -import { ActionsRegistryService } from '@backstage/backend-plugin-api'; +import { ActionsRegistryService } from '@backstage/backend-plugin-api/alpha'; export function registerMyActions(actionsRegistry: ActionsRegistryService) { // Register a simple read-only action diff --git a/docs/backend-system/core-services/cache.md b/docs/backend-system/core-services/cache.md index 0e26e8e1f5..ad4d04b50a 100644 --- a/docs/backend-system/core-services/cache.md +++ b/docs/backend-system/core-services/cache.md @@ -7,6 +7,39 @@ description: Documentation for the Cache service This service lets your plugin interact with a cache. It is bound to your plugin too, so that you will only set and get values in your plugin's private namespace. +## Configuration + +The cache service can be configured using the `backend.cache` section in your `app-config.yaml`: + +```yaml +backend: + cache: + store: redis # or 'valkey', 'memcache', 'memory' + connection: redis://localhost:6379 + + # Store-specific configuration (Redis/Valkey only) + redis: + client: + # Optional: Global namespace prefix for all cache keys + namespace: 'my-app' + # Optional: Separator used between namespace and plugin ID (default: ':') + keyPrefixSeparator: ':' + # Other Redis-specific options... + clearBatchSize: 1000 + useUnlink: false +``` + +### Namespace Configuration + +For Redis and Valkey stores, you can configure a global namespace that will be prefixed to all cache keys: + +- **Without namespace**: Cache keys use only the plugin ID (e.g., `catalog:some-key`) +- **With namespace**: Cache keys use the format `namespace:pluginId:key` (e.g., `my-app:catalog:some-key`) + +The `keyPrefixSeparator` controls what character is used between the namespace and plugin ID (defaults to `:`). + +**Note**: Memory and Memcache stores do not support namespace configuration and will always use the plugin ID directly. + ## Using the service The following example shows how to get a cache client in your `example` backend plugin and setting and getting values from the cache. diff --git a/docs/conf/index.md b/docs/conf/index.md index 659ffccfe3..029c5b88fd 100644 --- a/docs/conf/index.md +++ b/docs/conf/index.md @@ -16,10 +16,24 @@ allowing for customization. ## Supplying Configuration Configuration is stored in YAML files where the defaults are `app-config.yaml` -and `app-config.local.yaml` for local overrides. Other sets of files can by -loaded by passing `--config ` flags. The configuration files themselves -contain plain YAML, but with support for loading in data and secrets from -various sources using for example `$env` and `$file` keys. +and `app-config.local.yaml` for local overrides. Additionally, it is possible +to define environment based configuration files with `BACKSTAGE_ENV` +environment variable, which will load `app-config..yaml`. + +Loading order of these files is as follows: + +1. `app-config.yaml` +2. `app-config..yaml` +3. `app-config.local.yaml` +4. `app-config..local.yaml` + +Other sets of files can by loaded by passing `--config ` flags. +Read more about the configuration loading order in the +[Configuration Files](./writing.md#configuration-files) section. + +The configuration files themselves contain plain YAML, but with support for +loading in data and secrets from various sources using for example +`$env` and `$file` keys. It is also possible to supply configuration through environment variables, for example `APP_CONFIG_app_baseUrl=https://staging.example.com`. However these diff --git a/docs/contribute/project-structure.md b/docs/contribute/project-structure.md index 5b86b655b2..f58afedee8 100644 --- a/docs/contribute/project-structure.md +++ b/docs/contribute/project-structure.md @@ -221,7 +221,3 @@ future. - [`catalog-info.yaml`](https://github.com/backstage/backstage/tree/master/catalog-info.yaml) - Description of Backstage in the Backstage Entity format. - -- [`lerna.json`](https://github.com/backstage/backstage/tree/master/lerna.json) - - [Lerna](https://github.com/lerna/lerna) monorepo config. We are using - `yarn workspaces`, so this will only be used for executing scripts. diff --git a/docs/features/software-catalog/well-known-annotations.md b/docs/features/software-catalog/well-known-annotations.md index cdd93b50ac..d8a2e1d232 100644 --- a/docs/features/software-catalog/well-known-annotations.md +++ b/docs/features/software-catalog/well-known-annotations.md @@ -126,7 +126,7 @@ metadata: 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. +another entity, not just linking to the root of another entity's TechDocs. ### backstage.io/view-url, backstage.io/edit-url diff --git a/docs/features/techdocs/FAQ.md b/docs/features/techdocs/FAQ.md index 117471f749..9c78e3e123 100644 --- a/docs/features/techdocs/FAQ.md +++ b/docs/features/techdocs/FAQ.md @@ -12,6 +12,8 @@ This page answers frequently asked questions about [TechDocs](README.md). - [What static site generator is TechDocs using?](#what-static-site-generator-is-techdocs-using) - [What is the mkdocs-techdocs-core plugin?](#what-is-the-mkdocs-techdocs-core-plugin) - [Does TechDocs support file formats other than Markdown (e.g. RST, AsciiDoc)?](#does-techdocs-support-file-formats-other-than-markdown-eg-rst-asciidoc-) +- [What should be the value of `backstage.io/techdocs-ref` when using external build and storage?](#what-should-be-the-value-of-backstageiotechdocs-ref-when-using-external-build-and-storage) +- [Is it possible for users to suggest changes or provide feedback on a TechDocs page?](#is-it-possible-for-users-to-suggest-changes-or-provide-feedback-on-a-techdocs-page) #### What static site generator is TechDocs using? @@ -46,6 +48,10 @@ annotation should still be present in entity descriptor file (e.g. `catalog-info.yaml`) for Backstage to know that TechDocs is enabled for the entity. +#### What happens when you navigate to a TechDocs URL for an entity uses the `backstage.io/techdocs-entity` annotation? + +If you navigate to a TechDocs URL in the format `docs/{namespace}/{kind}/{name}` for an entity that has the `backstage.io/techdocs-entity` annotation (instead of the `backstage.io/techdocs-ref` annotation), then Backstage will redirect to the TechDocs page of the entity referenced in the value of that annotation. + #### Is it possible for users to suggest changes or provide feedback on a TechDocs page? This is supported for TechDocs sites whose source code is hosted in either diff --git a/docs/frontend-system/building-plugins/01-index.md b/docs/frontend-system/building-plugins/01-index.md index 283c162fa7..03da20ea73 100644 --- a/docs/frontend-system/building-plugins/01-index.md +++ b/docs/frontend-system/building-plugins/01-index.md @@ -185,7 +185,7 @@ export const examplePlugin = createFrontendPlugin({ ## Plugin specific extensions -There are many different plugins that you can extend with additional functionality through extensions. One such plugin is [the catalog plugin](../../features/software-catalog/), one of the core features of Backstage. It lets you catalog the software in your organization, where each item in the catalog has its own page that can be populated with tools and information relating to that catalog entity. In this example we will explore how our plugin can provide such a tool to display on an entity page. +There are many different plugins that you can extend with additional functionality through extensions. One such plugin is [the catalog plugin](https://backstage.io/docs/features/software-catalog/), one of the core features of Backstage. It lets you catalog the software in your organization, where each item in the catalog has its own page that can be populated with tools and information relating to that catalog entity. In this example we will explore how our plugin can provide such a tool to display on an entity page. ```tsx title="in src/plugin.ts - An example entity content extension" import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha'; diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index cd86aa3343..252884dc54 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -31,7 +31,7 @@ This guide also assumes a basic understanding of working on a Linux based operat [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/) - A GNU-like build environment available at the command line. For example, on Debian/Ubuntu you will want to have the `make` and `build-essential` packages installed. - On macOS, you will want to have run `xcode-select --install` to get the XCode command line build tooling in place. + On macOS, you will want to run `xcode-select --install` to get the XCode command line build tooling in place. - An account with elevated rights to install the dependencies - `curl` or `wget` installed - Node.js [Active LTS Release](../overview/versioning-policy.md#nodejs-releases) installed using one of these @@ -58,9 +58,9 @@ The Backstage app we'll be creating will only have demo data until we set up int ::: -To install the Backstage Standalone app, we will make use of `npx`. `npx` is a tool that comes preinstalled with Node.js and lets you run commands straight from `npm` or other registries. Before we jump in to running the command, let's chat about what it does. +To install the Backstage Standalone app, we will make use of `npx`. `npx` is a tool that comes preinstalled with Node.js and lets you run commands straight from `npm` or other registries. Before we run the command, let's discuss what it does. -This command will create a new directory with a Backstage app inside. The wizard will ask you for the name of the app. This name will be created as sub directory in your current working directory. +This command will create a new directory with a Backstage app inside. The wizard will ask you for the name of the app. This name will be created as subdirectory in your current working directory. ![create app](../assets/getting-started/create-app-output.png) @@ -89,8 +89,8 @@ app - **package.json**: Root package.json for the project. _Note: Be sure that you don't add any npm dependencies here as they probably should be installed in the intended workspace rather than in the root._ -- **packages/**: Lerna leaf packages or "workspaces". Everything here is going - to be a separate package, managed by lerna. +- **packages/**: Yarn workspaces, everything here is going + to be a separate package, managed by Yarn. - **packages/app/**: A fully functioning Backstage frontend app that acts as a good starting point for you to get to know Backstage. - **packages/backend/**: We include a backend that helps power features such as diff --git a/docs/references/glossary.md b/docs/references/glossary.md index c955d9a5ae..ad9e2bbee5 100644 --- a/docs/references/glossary.md +++ b/docs/references/glossary.md @@ -208,7 +208,7 @@ One of the [packages](#package) within a [monorepo](#monorepo). A package may or 1. A single repository for a collection of related software projects, such as all projects belonging to an organization. -2. A project layout that consists of multiple [packages](#package) within a single project, where packages are able to have local dependencies on each other. Often enabled through tooling such as [lerna](https://lerna.js.org/) and [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/) +2. A project layout that consists of multiple [packages](#package) within a single project, where packages are able to have local dependencies on each other. Often enabled through tooling such as [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces/) ## Name diff --git a/docs/releases/v1.43.0-next.2-changelog.md b/docs/releases/v1.43.0-next.2-changelog.md new file mode 100644 index 0000000000..ef7ddb1c1f --- /dev/null +++ b/docs/releases/v1.43.0-next.2-changelog.md @@ -0,0 +1,695 @@ +# Release v1.43.0-next.2 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.43.0-next.2](https://backstage.github.io/upgrade-helper/?to=1.43.0-next.2) + +## @backstage/catalog-client@1.12.0-next.0 + +### Minor Changes + +- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog. + + Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog. + This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them + all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination + or fetch all entities at once. + + Example usage: + + ```ts + const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token }); + for await (const page of pageStream) { + // Handle page of entities + for (const entity of page) { + console.log(entity); + } + } + ``` + +## @backstage/plugin-auth@0.1.0-next.0 + +### Minor Changes + +- 54ddfef: Initial publish of the `auth` frontend package + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.6-next.1 + +## @backstage/plugin-catalog-node@1.19.0-next.1 + +### Minor Changes + +- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog. + + Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog. + This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them + all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination + or fetch all entities at once. + + Example usage: + + ```ts + const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token }); + for await (const page of pageStream) { + // Handle page of entities + for (const entity of page) { + console.log(entity); + } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + +## @backstage/plugin-catalog-react@1.21.0-next.2 + +### Minor Changes + +- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog. + + Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog. + This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them + all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination + or fetch all entities at once. + + Example usage: + + ```ts + const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token }); + for await (const page of pageStream) { + // Handle page of entities + for (const entity of page) { + console.log(entity); + } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/backend-defaults@0.12.1-next.1 + +### Patch Changes + +- 4eda590: Fixed cache namespace and key prefix separator configuration to properly use configured values instead of hardcoded plugin ID. The cache manager now correctly combines the configured namespace with plugin IDs using the configured separator for Redis and Valkey. Memcache and memory store continue to use plugin ID as namespace. +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/integration-aws-node@0.1.17 + +## @backstage/backend-dynamic-feature-service@0.7.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-backend@3.0.2-next.1 + - @backstage/plugin-app-node@0.1.37-next.1 + +## @backstage/cli@0.34.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/integration@1.18.0-next.0 + +## @backstage/config-loader@1.10.3-next.0 + +### Patch Changes + +- a73f495: Allow using `BACKSTAGE_ENV` for loading environment specific config files + +## @backstage/core-compat-api@0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + +## @backstage/core-components@0.17.6-next.1 + +### Patch Changes + +- 1ad3d94: Dependency graph can now be opened in full screen mode +- ae7d426: update about card links style for pretty display with other language + +## @backstage/create-app@0.7.4-next.2 + +### Patch Changes + +- Bumped create-app version. + +## @backstage/dev-utils@1.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + +## @backstage/repo-tools@0.15.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + +## @backstage/ui@0.7.1-next.0 + +### Patch Changes + +- 7307930: Add missing class for flex: baseline +- 89da341: Fix Select component to properly attach aria-label and aria-labelledby props to the rendered element for improved accessibility. + +## @backstage/plugin-api-docs@0.12.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/plugin-catalog@1.31.3-next.2 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-app-backend@0.5.6-next.1 + +### Patch Changes + +- afd368e: Internal update to not expose the old `createRouter`. +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-app-node@0.1.37-next.1 + +## @backstage/plugin-app-node@0.1.37-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + +## @backstage/plugin-auth-backend@0.25.4-next.1 + +### Patch Changes + +- 1d47bf3: Implementing Dynamic Client Registration with the OIDC server. You can enable this by setting `auth.experimentalDynamicClientRegistration.enabled` in `app-config.yaml`. This is highly experimental, but feedback welcome. +- 54ddfef: Updating plugin metadata +- Updated dependencies + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-auth-node@0.6.7-next.1 + +### Patch Changes + +- 54ddfef: Updating plugin metadata +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + +## @backstage/plugin-auth-react@0.1.19-next.1 + +### Patch Changes + +- 54ddfef: Updating plugin metadata +- Updated dependencies + - @backstage/core-components@0.17.6-next.1 + +## @backstage/plugin-catalog@1.31.3-next.2 + +### Patch Changes + +- 85c5e04: Fix incorrect `defaultTarget` on `createComponentRouteRef`. +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-catalog-backend@3.0.2-next.1 + +### Patch Changes + +- 2204f5b: Prevent deadlock in catalog deferred stitching +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-aws@0.4.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/integration-aws-node@0.1.17 + +## @backstage/plugin-catalog-backend-module-azure@0.3.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-backstage-openapi@0.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-gcp@0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-gitea@0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-github@0.11.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.2-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-github-org@0.3.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/plugin-catalog-backend-module-github@0.11.0-next.1 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.3-next.1 + +## @backstage/plugin-catalog-backend-module-incremental-ingestion@0.7.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-catalog-backend@3.0.2-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-catalog-backend-module-ldap@0.11.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-catalog-backend-module-msgraph@0.8.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-catalog-backend-module-openapi@0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.14-next.1 + +### Patch Changes + +- afd368e: **BREAKING ALPHA**: The module has been moved from the `/alpha` export to the root of the package. +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-catalog-backend-module-unprocessed@0.6.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-catalog-graph@0.4.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-catalog-import@0.13.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-devtools-backend@0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/backend-defaults@0.12.1-next.1 + +## @backstage/plugin-home@0.8.12-next.2 + +### Patch Changes + +- 929c55a: Fixed race condition in CustomHomepageGrid by waiting for storage to load before rendering custom layout to prevent + rendering of the default content. +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-kubernetes@0.12.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-kubernetes-backend@0.20.2-next.2 + +### Patch Changes + +- dd7b6d2: Fix a bug where `getDefault` in the `kubernetesFetcherExtensionPoint` had the wrong `this` value +- Updated dependencies + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration-aws-node@0.1.17 + +## @backstage/plugin-kubernetes-cluster@0.0.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + +## @backstage/plugin-mcp-actions-backend@0.1.3-next.1 + +### Patch Changes + +- 1d47bf3: Proxy `/.well-known/oauth-authorization-server` to `/.well-known/openid-configuration` on `auth-backend` when `auth.experimentalDynamicClientRegistration.enabled` is enabled. +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-notifications-backend@0.5.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/plugin-notifications-node@0.2.19-next.1 + +## @backstage/plugin-notifications-backend-module-email@0.3.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration-aws-node@0.1.17 + - @backstage/plugin-notifications-node@0.2.19-next.1 + +## @backstage/plugin-notifications-backend-module-slack@0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/plugin-notifications-node@0.2.19-next.1 + +## @backstage/plugin-notifications-node@0.2.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + +## @backstage/plugin-org@0.6.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-org-react@0.1.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + +## @backstage/plugin-scaffolder@1.34.1-next.2 + +### Patch Changes + +- 0d415ae: Render a TechDocs link on the Scaffolder Template List page when templates include either `backstage.io/techdocs-ref` or `backstage.io/techdocs-entity` annotations, using the shared `buildTechDocsURL` helper. Also adds tests to verify both annotations and optional `backstage.io/techdocs-entity-path` are respected. +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/plugin-scaffolder-react@1.19.1-next.2 + - @backstage/integration@1.18.0-next.0 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-scaffolder-backend@2.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.12-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.8.3-next.1 + +## @backstage/plugin-scaffolder-backend-module-github@0.8.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + +## @backstage/plugin-scaffolder-react@1.19.1-next.2 + +### Patch Changes + +- 58fc108: Fix scaffolder task log stream not having a minimum height +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + +## @backstage/plugin-search@1.4.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-search-backend-module-catalog@0.3.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-search-backend-module-techdocs@0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + +## @backstage/plugin-techdocs@1.14.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-react@0.1.19-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/core-compat-api@0.5.2-next.2 + +## @backstage/plugin-techdocs-addons-test-utils@1.0.53-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/plugin-catalog@1.31.3-next.2 + - @backstage/plugin-techdocs@1.14.2-next.2 + +## @backstage/plugin-techdocs-backend@2.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.6-next.1 + +## @backstage/plugin-user-settings@0.8.26-next.2 + +### Patch Changes + +- b713b54: Tool-tip text correction for the Theme selection in settings page +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + +## example-app@0.2.113-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.7.1-next.0 + - @backstage/plugin-auth-react@0.1.19-next.1 + - @backstage/plugin-home@0.8.12-next.2 + - @backstage/plugin-scaffolder@1.34.1-next.2 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/plugin-user-settings@0.8.26-next.2 + - @backstage/plugin-scaffolder-react@1.19.1-next.2 + - @backstage/plugin-catalog@1.31.3-next.2 + - @backstage/cli@0.34.2-next.2 + - @backstage/plugin-catalog-graph@0.4.23-next.2 + - @backstage/plugin-catalog-import@0.13.5-next.2 + - @backstage/plugin-org@0.6.44-next.2 + - @backstage/plugin-techdocs@1.14.2-next.2 + - @backstage/plugin-api-docs@0.12.11-next.2 + - @backstage/plugin-kubernetes@0.12.11-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.29-next.2 + - @backstage/plugin-search@1.4.30-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.28-next.0 + +## example-app-next@0.0.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.7.1-next.0 + - @backstage/plugin-auth-react@0.1.19-next.1 + - @backstage/plugin-auth@0.1.0-next.0 + - @backstage/plugin-home@0.8.12-next.2 + - @backstage/plugin-scaffolder@1.34.1-next.2 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/plugin-user-settings@0.8.26-next.2 + - @backstage/plugin-scaffolder-react@1.19.1-next.2 + - @backstage/plugin-catalog@1.31.3-next.2 + - @backstage/cli@0.34.2-next.2 + - @backstage/plugin-catalog-graph@0.4.23-next.2 + - @backstage/plugin-catalog-import@0.13.5-next.2 + - @backstage/plugin-org@0.6.44-next.2 + - @backstage/plugin-techdocs@1.14.2-next.2 + - @backstage/core-compat-api@0.5.2-next.2 + - @backstage/plugin-api-docs@0.12.11-next.2 + - @backstage/plugin-kubernetes@0.12.11-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.29-next.2 + - @backstage/plugin-search@1.4.30-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.28-next.0 diff --git a/lerna.json b/lerna.json deleted file mode 100644 index 4621689664..0000000000 --- a/lerna.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "packages": ["packages/*", "plugins/*"], - "npmClient": "yarn", - "useWorkspaces": true, - "version": "0.0.0" -} diff --git a/microsite/data/plugins/datacontract.yaml b/microsite/data/plugins/datacontract.yaml new file mode 100644 index 0000000000..a267730496 --- /dev/null +++ b/microsite/data/plugins/datacontract.yaml @@ -0,0 +1,10 @@ +--- +title: Data Contract +author: Jan Remunda +authorUrl: https://www.remunda.cz/#backstage +category: Discovery +description: Ingest and visualize Data Contracts to your catalog via API Entities. +documentation: https://www.npmjs.com/package/@remunda/backstage-plugin-datacontract +iconUrl: https://www.remunda.cz/logos/datacontract.png +npmPackageName: '@remunda/backstage-plugin-datacontract' +addedDate: '2025-08-19' diff --git a/microsite/src/components/pluginsSearch/pluginsSearch.tsx b/microsite/src/components/pluginsSearch/pluginsSearch.tsx new file mode 100644 index 0000000000..68f9a2831a --- /dev/null +++ b/microsite/src/components/pluginsSearch/pluginsSearch.tsx @@ -0,0 +1,19 @@ +import React from 'react'; + +type Props = { + searchTerm: string; + onSearchTermChange: (newTerm: string) => void; +}; + +export const PluginsSearch = (props: Props) => { + const { searchTerm, onSearchTermChange } = props; + return ( + onSearchTermChange((e.target as HTMLInputElement).value)} + value={searchTerm} + placeholder="Search plugins..." + className="DocSearch-Input search" + /> + ); +}; diff --git a/microsite/src/pages/plugins/index.tsx b/microsite/src/pages/plugins/index.tsx index 2abdbabf4b..1a87f9c0af 100644 --- a/microsite/src/pages/plugins/index.tsx +++ b/microsite/src/pages/plugins/index.tsx @@ -5,10 +5,11 @@ import { truncateDescription } from '@site/src/util/truncateDescription'; import { ChipCategory } from '@site/src/util/types'; import Layout from '@theme/Layout'; import clsx from 'clsx'; -import React, { useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { IPluginData, PluginCard } from './_pluginCard'; import pluginsStyles from './plugins.module.scss'; +import { PluginsSearch } from '@site/src/components/pluginsSearch/pluginsSearch'; interface IPluginsList { corePlugins: IPluginData[]; @@ -55,6 +56,7 @@ const Plugins = () => { const [selectedCategories, setSelectedCategories] = useState([]); const [showCoreFeatures, setShowCoreFeatures] = useState(true); const [showOtherPlugins, setShowOtherPlugins] = useState(true); + const [searchTerm, setSearchTerm] = useState(''); const handleChipClick = (categoryName: string) => { const isSelected = @@ -97,6 +99,34 @@ const Plugins = () => { } }; + const matchesSearch = (pluginData: IPluginData, term: string) => { + if (!term) return true; + const lowerTerm = term.toLowerCase(); + return ( + pluginData.title.toLowerCase().includes(lowerTerm) || + pluginData.description.toLowerCase().includes(lowerTerm) || + pluginData.category.toLowerCase().includes(lowerTerm) || + (pluginData.author && pluginData.author.toLowerCase().includes(lowerTerm)) + ); + }; + + const matchesCategory = (pluginData: IPluginData, categories: string[]) => { + if (categories.length === 0) return true; + return categories.includes(pluginData.category); + }; + + const corePlugins = useMemo(() => { + return plugins.corePlugins + .filter(pluginData => matchesCategory(pluginData, selectedCategories)) + .filter(pluginData => matchesSearch(pluginData, searchTerm)); + }, [selectedCategories, searchTerm]); + + const otherPlugins = useMemo(() => { + return plugins.otherPlugins + .filter(pluginData => matchesCategory(pluginData, selectedCategories)) + .filter(pluginData => matchesSearch(pluginData, searchTerm)); + }, [selectedCategories, searchTerm]); + return (
{ categories={categories} handleChipClick={handleChipClick} /> +
- {showCoreFeatures && ( + {corePlugins.length === 0 && otherPlugins.length === 0 && ( +
+

No plugins found

+

+ We couldn't find any plugins matching your criteria. Please try + adjusting your search or filter settings. +

+
+ )} + + {showCoreFeatures && corePlugins.length > 0 && (
-

Core Features

+

Core Features ({corePlugins.length})

- {plugins.corePlugins - .filter( - pluginData => - !selectedCategories.length || - selectedCategories.includes(pluginData.category), - ) - .map(pluginData => ( - - ))} + {corePlugins.map(pluginData => ( + + ))}
)} - {showOtherPlugins && ( + {showOtherPlugins && otherPlugins.length > 0 && (
-

All Plugins

+

All Plugins ({otherPlugins.length})

Friendly reminder: While we love the variety and contributions of our open source plugins, they haven't been fully vetted by the @@ -158,18 +193,9 @@ const Plugins = () => { your due diligence before installing. Happy exploring!

- {plugins.otherPlugins - .filter( - pluginData => - !selectedCategories.length || - selectedCategories.includes(pluginData.category), - ) - .map(pluginData => ( - - ))} + {otherPlugins.map(pluginData => ( + + ))}
)} diff --git a/microsite/src/pages/plugins/plugins.module.scss b/microsite/src/pages/plugins/plugins.module.scss index fb17e90625..a17e4bc5c0 100644 --- a/microsite/src/pages/plugins/plugins.module.scss +++ b/microsite/src/pages/plugins/plugins.module.scss @@ -76,6 +76,20 @@ height: 1rem; } + :global(.search) { + float: right; + margin-bottom: 1rem; + margin-right: 1rem; + font-size: calc(0.875rem * var(--ifm-button-size-multiplier)); + font-weight: var(--ifm-button-font-weight); + background-color: transparent; + border: var(--ifm-button-border-width) solid var(--ifm-color-primary); + border-radius: var(--ifm-button-border-radius); + color: var(--ifm-color-primary); + width: 220px; + height: 2.2rem; + } + :global(.dropdown) { float: right; margin-bottom: 1rem; diff --git a/package.json b/package.json index d4ebc22bc1..7aed18ab74 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "root", - "version": "1.43.0-next.1", + "version": "1.43.0-next.2", "backstage": { "cli": { "new": { diff --git a/packages/app-defaults/src/defaults/apis.ts b/packages/app-defaults/src/defaults/apis.ts index 63ace7b4d5..97989dff91 100644 --- a/packages/app-defaults/src/defaults/apis.ts +++ b/packages/app-defaults/src/defaults/apis.ts @@ -35,6 +35,7 @@ import { FetchMiddlewares, VMwareCloudAuth, FrontendHostDiscovery, + OpenShiftAuth, } from '@backstage/core-app-api'; import { @@ -58,6 +59,7 @@ import { bitbucketServerAuthApiRef, atlassianAuthApiRef, vmwareCloudAuthApiRef, + openshiftAuthApiRef, } from '@backstage/core-plugin-api'; import { permissionApiRef, @@ -275,6 +277,22 @@ export const apis = [ }); }, }), + createApiFactory({ + api: openshiftAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + configApi: configApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi, configApi }) => { + return OpenShiftAuth.create({ + configApi, + discoveryApi, + oauthRequestApi, + environment: configApi.getOptionalString('auth.environment'), + }); + }, + }), createApiFactory({ api: permissionApiRef, deps: { diff --git a/packages/app-next/CHANGELOG.md b/packages/app-next/CHANGELOG.md index 5fc353c09d..a4e2386525 100644 --- a/packages/app-next/CHANGELOG.md +++ b/packages/app-next/CHANGELOG.md @@ -1,5 +1,32 @@ # example-app-next +## 0.0.27-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.7.1-next.0 + - @backstage/plugin-auth-react@0.1.19-next.1 + - @backstage/plugin-auth@0.1.0-next.0 + - @backstage/plugin-home@0.8.12-next.2 + - @backstage/plugin-scaffolder@1.34.1-next.2 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/plugin-user-settings@0.8.26-next.2 + - @backstage/plugin-scaffolder-react@1.19.1-next.2 + - @backstage/plugin-catalog@1.31.3-next.2 + - @backstage/cli@0.34.2-next.2 + - @backstage/plugin-catalog-graph@0.4.23-next.2 + - @backstage/plugin-catalog-import@0.13.5-next.2 + - @backstage/plugin-org@0.6.44-next.2 + - @backstage/plugin-techdocs@1.14.2-next.2 + - @backstage/core-compat-api@0.5.2-next.2 + - @backstage/plugin-api-docs@0.12.11-next.2 + - @backstage/plugin-kubernetes@0.12.11-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.29-next.2 + - @backstage/plugin-search@1.4.30-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.28-next.0 + ## 0.0.27-next.1 ### Patch Changes diff --git a/packages/app-next/app-config.yaml b/packages/app-next/app-config.yaml index f83e4d4ba0..35380c961f 100644 --- a/packages/app-next/app-config.yaml +++ b/packages/app-next/app-config.yaml @@ -4,7 +4,6 @@ app: routes: bindings: catalog.viewTechDoc: techdocs.docRoot - catalog.createComponent: catalog-import.importPage org.catalogIndex: catalog.catalogIndex pluginOverrides: diff --git a/packages/app-next/package.json b/packages/app-next/package.json index 44602b2438..49ce264f06 100644 --- a/packages/app-next/package.json +++ b/packages/app-next/package.json @@ -1,6 +1,6 @@ { "name": "example-app-next", - "version": "0.0.27-next.1", + "version": "0.0.27-next.2", "backstage": { "role": "frontend" }, @@ -49,6 +49,7 @@ "@backstage/plugin-api-docs": "workspace:^", "@backstage/plugin-app": "workspace:^", "@backstage/plugin-app-visualizer": "workspace:^", + "@backstage/plugin-auth": "workspace:^", "@backstage/plugin-auth-react": "workspace:^", "@backstage/plugin-catalog": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", diff --git a/packages/app/CHANGELOG.md b/packages/app/CHANGELOG.md index 93dd1db16a..f3b911accf 100644 --- a/packages/app/CHANGELOG.md +++ b/packages/app/CHANGELOG.md @@ -1,5 +1,30 @@ # example-app +## 0.2.113-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/ui@0.7.1-next.0 + - @backstage/plugin-auth-react@0.1.19-next.1 + - @backstage/plugin-home@0.8.12-next.2 + - @backstage/plugin-scaffolder@1.34.1-next.2 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/plugin-user-settings@0.8.26-next.2 + - @backstage/plugin-scaffolder-react@1.19.1-next.2 + - @backstage/plugin-catalog@1.31.3-next.2 + - @backstage/cli@0.34.2-next.2 + - @backstage/plugin-catalog-graph@0.4.23-next.2 + - @backstage/plugin-catalog-import@0.13.5-next.2 + - @backstage/plugin-org@0.6.44-next.2 + - @backstage/plugin-techdocs@1.14.2-next.2 + - @backstage/plugin-api-docs@0.12.11-next.2 + - @backstage/plugin-kubernetes@0.12.11-next.2 + - @backstage/plugin-kubernetes-cluster@0.0.29-next.2 + - @backstage/plugin-search@1.4.30-next.2 + - @backstage/plugin-techdocs-module-addons-contrib@1.1.28-next.0 + ## 0.2.113-next.1 ### Patch Changes diff --git a/packages/app/package.json b/packages/app/package.json index 580c401a1b..5e38aa6256 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -1,6 +1,6 @@ { "name": "example-app", - "version": "0.2.113-next.1", + "version": "0.2.113-next.2", "backstage": { "role": "frontend" }, diff --git a/packages/app/src/identityProviders.ts b/packages/app/src/identityProviders.ts index 66f1460210..372477cd63 100644 --- a/packages/app/src/identityProviders.ts +++ b/packages/app/src/identityProviders.ts @@ -23,6 +23,7 @@ import { oneloginAuthApiRef, bitbucketAuthApiRef, bitbucketServerAuthApiRef, + openshiftAuthApiRef, } from '@backstage/core-plugin-api'; export const providers = [ @@ -74,4 +75,10 @@ export const providers = [ message: 'Sign In using Bitbucket Server', apiRef: bitbucketServerAuthApiRef, }, + { + id: 'openshift-auth-provider', + title: 'OpenShift', + message: 'Sign In using OpenShift', + apiRef: openshiftAuthApiRef, + }, ]; diff --git a/packages/backend-defaults/CHANGELOG.md b/packages/backend-defaults/CHANGELOG.md index 0375e54232..b4c7393455 100644 --- a/packages/backend-defaults/CHANGELOG.md +++ b/packages/backend-defaults/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-defaults +## 0.12.1-next.1 + +### Patch Changes + +- 4eda590: Fixed cache namespace and key prefix separator configuration to properly use configured values instead of hardcoded plugin ID. The cache manager now correctly combines the configured namespace with plugin IDs using the configured separator for Redis and Valkey. Memcache and memory store continue to use plugin ID as namespace. +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/integration-aws-node@0.1.17 + ## 0.12.1-next.0 ### Patch Changes diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json index 09bb4dc85d..1b1f0101c7 100644 --- a/packages/backend-defaults/package.json +++ b/packages/backend-defaults/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/backend-defaults", - "version": "0.12.1-next.0", + "version": "0.12.1-next.1", "description": "Backend defaults used by Backstage backend apps", "backstage": { "role": "node-library" diff --git a/packages/backend-defaults/src/entrypoints/cache/CacheManager.test.ts b/packages/backend-defaults/src/entrypoints/cache/CacheManager.test.ts index 4e9475b66e..a308caa222 100644 --- a/packages/backend-defaults/src/entrypoints/cache/CacheManager.test.ts +++ b/packages/backend-defaults/src/entrypoints/cache/CacheManager.test.ts @@ -333,4 +333,147 @@ describe('CacheManager store options', () => { keyPrefixSeparator: '!', }); }); + + it('correctly applies namespace configuration to redis and valkey stores', () => { + const testCases = [ + { store: 'redis', namespace: 'test1', separator: ':' }, + { store: 'valkey', namespace: 'test2', separator: '!' }, + ]; + + testCases.forEach(({ store, namespace, separator }) => { + const manager = CacheManager.fromConfig( + mockServices.rootConfig({ + data: { + backend: { + cache: { + store, + connection: 'redis://localhost:6379', + [store]: { + client: { + namespace, + keyPrefixSeparator: separator, + }, + }, + }, + }, + }, + }), + ); + + manager.forPlugin('testPlugin'); + + if (store === 'redis') { + // eslint-disable-next-line jest/no-conditional-expect + expect(KeyvRedis).toHaveBeenCalledWith('redis://localhost:6379', { + namespace, + keyPrefixSeparator: separator, + }); + } else if (store === 'valkey') { + // eslint-disable-next-line jest/no-conditional-expect + expect(KeyvValkey).toHaveBeenCalledWith('redis://localhost:6379', { + namespace, + keyPrefixSeparator: separator, + }); + } + }); + }); + + it('falls back to pluginId when no namespace is configured', () => { + const manager = CacheManager.fromConfig( + mockServices.rootConfig({ + data: { + backend: { + cache: { + store: 'redis', + connection: 'redis://localhost:6379', + }, + }, + }, + }), + ); + + manager.forPlugin('testPlugin'); + + expect(KeyvRedis).toHaveBeenCalledWith('redis://localhost:6379', { + keyPrefixSeparator: ':', + }); + }); + + describe('Namespace construction', () => { + it('returns pluginId when no store options are provided', () => { + const result = (CacheManager as any).constructNamespace( + 'testPlugin', + undefined, + ); + expect(result).toBe('testPlugin'); + }); + + it('returns pluginId when store options have no namespace', () => { + const storeOptions = { + client: { + keyPrefixSeparator: ':', + }, + }; + const result = (CacheManager as any).constructNamespace( + 'testPlugin', + storeOptions, + ); + expect(result).toBe('testPlugin'); + }); + + it('combines namespace and pluginId with default separator', () => { + const storeOptions = { + client: { + namespace: 'my-app', + keyPrefixSeparator: ':', + }, + }; + const result = (CacheManager as any).constructNamespace( + 'testPlugin', + storeOptions, + ); + expect(result).toBe('my-app:testPlugin'); + }); + + it('combines namespace and pluginId with custom separator', () => { + const storeOptions = { + client: { + namespace: 'my-app', + keyPrefixSeparator: '-', + }, + }; + const result = (CacheManager as any).constructNamespace( + 'testPlugin', + storeOptions, + ); + expect(result).toBe('my-app-testPlugin'); + }); + + it('uses default separator when keyPrefixSeparator is not provided', () => { + const storeOptions = { + client: { + namespace: 'my-app', + }, + }; + const result = (CacheManager as any).constructNamespace( + 'testPlugin', + storeOptions, + ); + expect(result).toBe('my-app:testPlugin'); + }); + + it('handles empty namespace by falling back to pluginId', () => { + const storeOptions = { + client: { + namespace: '', + keyPrefixSeparator: ':', + }, + }; + const result = (CacheManager as any).constructNamespace( + 'testPlugin', + storeOptions, + ); + expect(result).toBe('testPlugin'); + }); + }); }); diff --git a/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts b/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts index 1c26083525..06b2b0c57b 100644 --- a/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts +++ b/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts @@ -213,6 +213,26 @@ export class CacheManager { return redisOptions; } + /** + * Construct the full namespace based on the options and pluginId. + * + * @param pluginId - The plugin ID to namespace + * @param storeOptions - Optional cache store configuration options + * @returns The constructed namespace string combining the configured namespace with pluginId + */ + private static constructNamespace( + pluginId: string, + storeOptions: RedisCacheStoreOptions | undefined, + ): string { + const prefix = storeOptions?.client?.namespace + ? `${storeOptions.client.namespace}${ + storeOptions.client.keyPrefixSeparator ?? ':' + }` + : ''; + + return `${prefix}${pluginId}`; + } + /** @internal */ constructor( store: string, @@ -286,7 +306,7 @@ export class CacheManager { }); } return new Keyv({ - namespace: pluginId, + namespace: CacheManager.constructNamespace(pluginId, this.storeOptions), ttl: defaultTtl, store: stores[pluginId], emitErrors: false, @@ -326,7 +346,7 @@ export class CacheManager { }); } return new Keyv({ - namespace: pluginId, + namespace: CacheManager.constructNamespace(pluginId, this.storeOptions), ttl: defaultTtl, store: stores[pluginId], emitErrors: false, diff --git a/packages/backend-dynamic-feature-service/CHANGELOG.md b/packages/backend-dynamic-feature-service/CHANGELOG.md index 6bd6a7a781..d2e46404ef 100644 --- a/packages/backend-dynamic-feature-service/CHANGELOG.md +++ b/packages/backend-dynamic-feature-service/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/backend-dynamic-feature-service +## 0.7.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-backend@3.0.2-next.1 + - @backstage/plugin-app-node@0.1.37-next.1 + ## 0.7.4-next.0 ### Patch Changes diff --git a/packages/backend-dynamic-feature-service/package.json b/packages/backend-dynamic-feature-service/package.json index ff8fc29639..6a7cc2315f 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.4-next.0", + "version": "0.7.4-next.1", "description": "Backstage dynamic feature service", "backstage": { "role": "node-library" diff --git a/packages/backend/package.json b/packages/backend/package.json index a60b6d3940..64c2f1dd47 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -37,6 +37,7 @@ "@backstage/plugin-auth-backend": "workspace:^", "@backstage/plugin-auth-backend-module-github-provider": "workspace:^", "@backstage/plugin-auth-backend-module-guest-provider": "workspace:^", + "@backstage/plugin-auth-backend-module-openshift-provider": "workspace:^", "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-backend": "workspace:^", "@backstage/plugin-catalog-backend-module-backstage-openapi": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index f46e947b0d..e32d3148b3 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -33,6 +33,7 @@ const searchLoader = createBackendFeatureLoader({ backend.add(import('@backstage/plugin-auth-backend')); backend.add(import('./authModuleGithubProvider')); backend.add(import('@backstage/plugin-auth-backend-module-guest-provider')); +backend.add(import('@backstage/plugin-auth-backend-module-openshift-provider')); backend.add(import('@backstage/plugin-app-backend')); backend.add(import('@backstage/plugin-catalog-backend-module-unprocessed')); backend.add( diff --git a/packages/catalog-client/CHANGELOG.md b/packages/catalog-client/CHANGELOG.md index 52e2ed04a4..254f37bd69 100644 --- a/packages/catalog-client/CHANGELOG.md +++ b/packages/catalog-client/CHANGELOG.md @@ -1,5 +1,28 @@ # @backstage/catalog-client +## 1.12.0-next.0 + +### Minor Changes + +- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog. + + Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog. + This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them + all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination + or fetch all entities at once. + + Example usage: + + ```ts + const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token }); + for await (const page of pageStream) { + // Handle page of entities + for (const entity of page) { + console.log(entity); + } + } + ``` + ## 1.11.0 ### Minor Changes diff --git a/packages/catalog-client/package.json b/packages/catalog-client/package.json index a87ed29302..3b9d1c603a 100644 --- a/packages/catalog-client/package.json +++ b/packages/catalog-client/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/catalog-client", - "version": "1.11.0", + "version": "1.12.0-next.0", "description": "An isomorphic client for the catalog backend", "backstage": { "role": "common-library" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 87be49efce..bdaf3a05f6 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/cli +## 0.34.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/integration@1.18.0-next.0 + ## 0.34.2-next.1 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 51090239d8..8956b50713 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli", - "version": "0.34.2-next.1", + "version": "0.34.2-next.2", "description": "CLI for developing Backstage plugins and apps", "backstage": { "role": "cli" diff --git a/packages/cli/src/modules/build/lib/bundler/config.ts b/packages/cli/src/modules/build/lib/bundler/config.ts index c4011ede48..bf78d04b4a 100644 --- a/packages/cli/src/modules/build/lib/bundler/config.ts +++ b/packages/cli/src/modules/build/lib/bundler/config.ts @@ -264,24 +264,30 @@ export async function createConfig( singleton: true, requiredVersion: '*', eager: !isRemote, + import: false, }, 'react-dom': { singleton: true, requiredVersion: '*', eager: !isRemote, + import: false, }, // React Router 'react-router': { singleton: true, requiredVersion: '*', eager: !isRemote, + import: false, }, 'react-router-dom': { singleton: true, requiredVersion: '*', eager: !isRemote, + import: false, }, // MUI v4 + // not setting import: false for MUI packages as this + // will break once Backstage moves to BUI '@material-ui/core/styles': { singleton: true, requiredVersion: '*', @@ -293,6 +299,8 @@ export async function createConfig( eager: !isRemote, }, // MUI v5 + // not setting import: false for MUI packages as this + // will break once Backstage moves to BUI '@mui/material/styles/': { singleton: true, requiredVersion: '*', diff --git a/packages/config-loader/CHANGELOG.md b/packages/config-loader/CHANGELOG.md index 6fe939f3e6..a7b38c24b9 100644 --- a/packages/config-loader/CHANGELOG.md +++ b/packages/config-loader/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/config-loader +## 1.10.3-next.0 + +### Patch Changes + +- a73f495: Allow using `BACKSTAGE_ENV` for loading environment specific config files + ## 1.10.2 ### Patch Changes diff --git a/packages/config-loader/package.json b/packages/config-loader/package.json index f347af8034..b0e7af3b5e 100644 --- a/packages/config-loader/package.json +++ b/packages/config-loader/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/config-loader", - "version": "1.10.2", + "version": "1.10.3-next.0", "description": "Config loading functionality used by Backstage backend, and CLI", "backstage": { "role": "node-library" diff --git a/packages/config-loader/src/schema/collect.test.ts b/packages/config-loader/src/schema/collect.test.ts index 53db5c6da7..d48c98fbe4 100644 --- a/packages/config-loader/src/schema/collect.test.ts +++ b/packages/config-loader/src/schema/collect.test.ts @@ -41,16 +41,6 @@ describe('collectConfigSchemas', () => { mockDir.clear(); }); - it('should not find any schemas without packages', async () => { - mockDir.setContent({ - 'lerna.json': JSON.stringify({ - packages: ['packages/*'], - }), - }); - - await expect(collectConfigSchemas([], [])).resolves.toEqual([]); - }); - it('should find schema in a local package', async () => { mockDir.setContent({ node_modules: { diff --git a/packages/config-loader/src/sources/ConfigSources.test.ts b/packages/config-loader/src/sources/ConfigSources.test.ts index e19ac1d51f..a6b0648889 100644 --- a/packages/config-loader/src/sources/ConfigSources.test.ts +++ b/packages/config-loader/src/sources/ConfigSources.test.ts @@ -89,6 +89,19 @@ describe('ConfigSources', () => { { name: 'FileConfigSource', path: `${root}app-config.yaml` }, { name: 'FileConfigSource', path: `${root}app-config.local.yaml` }, ]); + + process.env = Object.assign(process.env, { BACKSTAGE_ENV: 'test' }); + expect( + mergeSources( + ConfigSources.defaultForTargets({ rootDir: '/', targets: [] }), + ), + ).toEqual([ + { name: 'FileConfigSource', path: `${root}app-config.yaml` }, + { name: 'FileConfigSource', path: `${root}app-config.test.yaml` }, + { name: 'FileConfigSource', path: `${root}app-config.local.yaml` }, + { name: 'FileConfigSource', path: `${root}app-config.test.local.yaml` }, + ]); + fsSpy.mockRestore(); expect( diff --git a/packages/config-loader/src/sources/ConfigSources.ts b/packages/config-loader/src/sources/ConfigSources.ts index 37c1c6b087..18d0443986 100644 --- a/packages/config-loader/src/sources/ConfigSources.ts +++ b/packages/config-loader/src/sources/ConfigSources.ts @@ -182,6 +182,14 @@ export class ConfigSources { if (argSources.length === 0) { const defaultPath = resolvePath(rootDir, 'app-config.yaml'); const localPath = resolvePath(rootDir, 'app-config.local.yaml'); + const envPath = resolvePath( + rootDir, + `app-config.${process.env.BACKSTAGE_ENV}.yaml`, + ); + const envLocalPath = resolvePath( + rootDir, + `app-config.${process.env.BACKSTAGE_ENV}.local.yaml`, + ); const alwaysIncludeDefaultConfigSource = !options.allowMissingDefaultConfig; @@ -195,6 +203,16 @@ export class ConfigSources { ); } + if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envPath)) { + argSources.push( + FileConfigSource.create({ + watch: options.watch, + path: envPath, + substitutionFunc: options.substitutionFunc, + }), + ); + } + if (fs.pathExistsSync(localPath)) { argSources.push( FileConfigSource.create({ @@ -204,6 +222,16 @@ export class ConfigSources { }), ); } + + if (process.env.BACKSTAGE_ENV && fs.pathExistsSync(envLocalPath)) { + argSources.push( + FileConfigSource.create({ + watch: options.watch, + path: envLocalPath, + substitutionFunc: options.substitutionFunc, + }), + ); + } } return this.merge(argSources); diff --git a/packages/core-app-api/report.api.md b/packages/core-app-api/report.api.md index 445d73392d..0cecc22f4a 100644 --- a/packages/core-app-api/report.api.md +++ b/packages/core-app-api/report.api.md @@ -52,6 +52,7 @@ import { Observable } from '@backstage/types'; import { oktaAuthApiRef } from '@backstage/core-plugin-api'; import { oneloginAuthApiRef } from '@backstage/core-plugin-api'; import { OpenIdConnectApi } from '@backstage/core-plugin-api'; +import { openshiftAuthApiRef } from '@backstage/core-plugin-api'; import { PendingOAuthRequest } from '@backstage/core-plugin-api'; import { ProfileInfo } from '@backstage/core-plugin-api'; import { ProfileInfoApi } from '@backstage/core-plugin-api'; @@ -651,6 +652,12 @@ export type OpenLoginPopupOptions = { height?: number; }; +// @public +export class OpenShiftAuth { + // (undocumented) + static create(options: OAuthApiCreateOptions): typeof openshiftAuthApiRef.T; +} + // @public export type PopupOptions = { size?: diff --git a/packages/core-app-api/src/apis/implementations/auth/index.ts b/packages/core-app-api/src/apis/implementations/auth/index.ts index e02e07961a..00effb9384 100644 --- a/packages/core-app-api/src/apis/implementations/auth/index.ts +++ b/packages/core-app-api/src/apis/implementations/auth/index.ts @@ -26,4 +26,5 @@ export * from './bitbucket'; export * from './bitbucketServer'; export * from './atlassian'; export * from './vmwareCloud'; +export * from './openshift'; export type { OAuthApiCreateOptions, AuthApiCreateOptions } from './types'; diff --git a/packages/core-app-api/src/apis/implementations/auth/openshift/OpenShiftAuth.ts b/packages/core-app-api/src/apis/implementations/auth/openshift/OpenShiftAuth.ts new file mode 100644 index 0000000000..1d820189d2 --- /dev/null +++ b/packages/core-app-api/src/apis/implementations/auth/openshift/OpenShiftAuth.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 { openshiftAuthApiRef } from '@backstage/core-plugin-api'; +import { OAuth2 } from '../oauth2'; +import { OAuthApiCreateOptions } from '../types'; + +const DEFAULT_PROVIDER = { + id: 'openshift', + title: 'OpenShift', + icon: () => null, +}; + +/** + * Implements the OAuth flow to OpenShift + * + * @public + */ +export default class OpenShiftAuth { + static create(options: OAuthApiCreateOptions): typeof openshiftAuthApiRef.T { + const { + configApi, + discoveryApi, + environment = 'development', + provider = DEFAULT_PROVIDER, + oauthRequestApi, + defaultScopes = ['user:info'], + } = options; + + return OAuth2.create({ + configApi, + discoveryApi, + oauthRequestApi, + provider, + environment, + defaultScopes, + }); + } +} diff --git a/plugins/catalog-backend-module-puppetdb/src/alpha.ts b/packages/core-app-api/src/apis/implementations/auth/openshift/index.ts similarity index 84% rename from plugins/catalog-backend-module-puppetdb/src/alpha.ts rename to packages/core-app-api/src/apis/implementations/auth/openshift/index.ts index 01a9b25f7c..65452114ae 100644 --- a/plugins/catalog-backend-module-puppetdb/src/alpha.ts +++ b/packages/core-app-api/src/apis/implementations/auth/openshift/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,5 +14,4 @@ * limitations under the License. */ -export * from './module'; -export { default } from './module'; +export { default as OpenShiftAuth } from './OpenShiftAuth'; diff --git a/packages/core-compat-api/CHANGELOG.md b/packages/core-compat-api/CHANGELOG.md index a966469313..ea40b301bb 100644 --- a/packages/core-compat-api/CHANGELOG.md +++ b/packages/core-compat-api/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/core-compat-api +## 0.5.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + ## 0.5.2-next.1 ### Patch Changes diff --git a/packages/core-compat-api/package.json b/packages/core-compat-api/package.json index 1430973106..db51762180 100644 --- a/packages/core-compat-api/package.json +++ b/packages/core-compat-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-compat-api", - "version": "0.5.2-next.1", + "version": "0.5.2-next.2", "backstage": { "role": "web-library" }, diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 515e6eac5b..10e04ae0c6 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/core-components +## 0.17.6-next.1 + +### Patch Changes + +- 1ad3d94: Dependency graph can now be opened in full screen mode +- ae7d426: update about card links style for pretty display with other language + ## 0.17.6-next.0 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index be91c5dbd5..5cd6b9f270 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-components", - "version": "0.17.6-next.0", + "version": "0.17.6-next.1", "description": "Core components used by Backstage plugins and apps", "backstage": { "role": "web-library" @@ -80,6 +80,7 @@ "pluralize": "^8.0.0", "qs": "^6.9.4", "rc-progress": "3.5.1", + "react-full-screen": "^1.1.1", "react-helmet": "6.1.0", "react-hook-form": "^7.12.2", "react-idle-timer": "5.7.2", @@ -106,6 +107,7 @@ "@types/d3-selection": "^3.0.1", "@types/d3-shape": "^3.0.1", "@types/d3-zoom": "^3.0.1", + "@types/fscreen": "^1", "@types/google-protobuf": "^3.7.2", "@types/react": "^18.0.0", "@types/react-helmet": "^6.1.0", diff --git a/packages/core-components/report-alpha.api.md b/packages/core-components/report-alpha.api.md index 32bd2f4939..96ddebcd3a 100644 --- a/packages/core-components/report-alpha.api.md +++ b/packages/core-components/report-alpha.api.md @@ -61,6 +61,7 @@ export const coreComponentsTranslationRef: TranslationRef< readonly 'alertDisplay.message_other': '({{ count }} newer messages)'; readonly 'autoLogout.stillTherePrompt.title': 'Logging out due to inactivity'; readonly 'autoLogout.stillTherePrompt.buttonText': "Yes! Don't log me out"; + readonly 'dependencyGraph.fullscreenTooltip': 'Toggle fullscreen'; readonly 'proxiedSignInPage.title': 'You do not appear to be signed in. Please try reloading the browser page.'; } >; diff --git a/packages/core-components/report.api.md b/packages/core-components/report.api.md index 4998accf01..c1c9d4ad5b 100644 --- a/packages/core-components/report.api.md +++ b/packages/core-components/report.api.md @@ -258,6 +258,7 @@ export interface DependencyGraphProps extends SVGProps { acyclicer?: 'greedy'; align?: DependencyGraphTypes.Alignment; + allowFullscreen?: boolean; curve?: 'curveStepBefore' | 'curveMonotoneX'; defs?: JSX.Element | JSX.Element[]; direction?: DependencyGraphTypes.Direction; diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.test.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.test.tsx index 6535808059..0dbf3a36b9 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.test.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.test.tsx @@ -14,10 +14,10 @@ * limitations under the License. */ -import { render } from '@testing-library/react'; import { DependencyGraph } from './DependencyGraph'; import { DependencyGraphTypes as Types } from './types'; import { EDGE_TEST_ID, LABEL_TEST_ID, NODE_TEST_ID } from './constants'; +import { renderInTestApp } from '@backstage/test-utils'; describe('', () => { beforeAll(() => { @@ -36,9 +36,8 @@ describe('', () => { const CUSTOM_TEST_ID = 'custom-test-id'; it('renders each node and edge supplied', async () => { - const { getByText, queryAllByTestId, findAllByTestId } = render( - , - ); + const { getByText, queryAllByTestId, findAllByTestId } = + await renderInTestApp(); const renderedNodes = await findAllByTestId(NODE_TEST_ID); expect(renderedNodes).toHaveLength(3); expect(getByText(nodes[0].id)).toBeInTheDocument(); @@ -49,9 +48,10 @@ describe('', () => { }); it('update render if already referenced nodes are added later', async () => { - const { getByText, queryAllByTestId, findAllByTestId, rerender } = render( - , - ); + const { getByText, queryAllByTestId, findAllByTestId, rerender } = + await renderInTestApp( + , + ); let renderedNodes = await findAllByTestId(NODE_TEST_ID); expect(renderedNodes).toHaveLength(2); @@ -75,9 +75,10 @@ describe('', () => { { ...edges[0], label: 'first' }, { ...edges[1], label: 'second' }, ]; - const { getByText, getAllByTestId, findAllByTestId } = render( - , - ); + const { getByText, getAllByTestId, findAllByTestId } = + await renderInTestApp( + , + ); const renderedEdges = await findAllByTestId(EDGE_TEST_ID); expect(renderedEdges).toHaveLength(2); expect(getAllByTestId(LABEL_TEST_ID)).toHaveLength(2); @@ -94,7 +95,7 @@ describe('', () => { ); - const { getByText, findByTestId, container } = render( + const { getByText, findByTestId, container } = await renderInTestApp( , ); const node = await findByTestId(CUSTOM_TEST_ID); @@ -112,7 +113,7 @@ describe('', () => { ); - const { getByText, findByTestId, container } = render( + const { getByText, findByTestId, container } = await renderInTestApp( ({ + root: { + overflow: 'hidden', + minHeight: '100%', + minWidth: '100%', + }, + fullscreen: { + backgroundColor: theme.palette.background.paper, + }, +})); /** * Properties of {@link DependencyGraph} @@ -142,7 +161,6 @@ export interface DependencyGraphProps * Custom edge rendering component */ renderEdge?: Types.RenderEdgeFunction; - /** * Custom node rendering component */ @@ -186,9 +204,18 @@ export interface DependencyGraphProps * Default: 'grow' */ fit?: 'grow' | 'contain'; + /** + * Controls if user can toggle fullscreen mode + * + * @remarks + * + * Default: true + */ + allowFullscreen?: boolean; } const WORKSPACE_ID = 'workspace'; +const DEPENDENCY_GRAPH_SVG = 'dependency-graph'; /** * Graph component used to visualize relations between entities @@ -222,11 +249,15 @@ export function DependencyGraph( curve = 'curveMonotoneX', showArrowHeads = false, fit = 'grow', + allowFullscreen = true, ...svgProps } = props; const theme = useTheme(); const [containerWidth, setContainerWidth] = useState(100); const [containerHeight, setContainerHeight] = useState(100); + const fullScreenHandle = useFullScreenHandle(); + const styles = useStyles(); + const { t } = useTranslationRef(coreComponentsTranslationRef); const graph = useRef>>( new dagre.graphlib.Graph(), @@ -248,11 +279,17 @@ export function DependencyGraph( const containerRef = useMemo( () => - debounce((node: SVGSVGElement) => { - if (!node) { + debounce((root: HTMLDivElement) => { + if (!root) { return; } // Set up zooming + panning + const node: SVGSVGElement = root.querySelector( + `svg#${DEPENDENCY_GRAPH_SVG}`, + ) as SVGSVGElement; + if (!node) { + return; + } const container = d3Selection.select(node); const workspace = d3Selection.select(node.getElementById(WORKSPACE_ID)); @@ -288,7 +325,7 @@ export function DependencyGraph( } const { width: newContainerWidth, height: newContainerHeight } = - node.getBoundingClientRect(); + root.getBoundingClientRect(); if (containerWidth !== newContainerWidth) { setContainerWidth(newContainerWidth); } @@ -412,70 +449,97 @@ export function DependencyGraph( } return ( - - - - - - {defs} - - - - {graphEdges.map(e => { - const edge = graph.current.edge(e) as GraphEdge; - if (!edge) return null; - if (renderEdge) return renderEdge({ edge, id: e }); +
+ + {allowFullscreen && ( + + + {fullScreenHandle.active ? ( + + ) : ( + + )} + + + )} - return ( - + + + - ); - })} - {graphNodes.map((id: string) => { - const node = graph.current.node(id); - if (!node) return null; - return ( - - ); - })} + + {defs} + + + + {graphEdges.map(e => { + const edge = graph.current.edge(e) as GraphEdge; + if (!edge) return null; + if (renderEdge) return renderEdge({ edge, id: e }); + + return ( + + ); + })} + {graphNodes.map((id: string) => { + const node = graph.current.node(id); + + if (!node) return null; + return ( + + ); + })} + + - - + +
); } diff --git a/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx b/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx index 1fcf664bab..0b8fe8cd8c 100644 --- a/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx +++ b/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx @@ -27,6 +27,7 @@ const useStyles = makeStyles( gridAutoFlow: 'column', gridAutoColumns: 'min-content', gridGap: theme.spacing(3), + wordBreak: 'keep-all', }, }), { name: 'BackstageHeaderIconLinkRow' }, diff --git a/packages/core-components/src/translation.ts b/packages/core-components/src/translation.ts index b884f0af92..aa644fa909 100644 --- a/packages/core-components/src/translation.ts +++ b/packages/core-components/src/translation.ts @@ -120,6 +120,9 @@ export const coreComponentsTranslationRef = createTranslationRef({ buttonText: "Yes! Don't log me out", }, }, + dependencyGraph: { + fullscreenTooltip: 'Toggle fullscreen', + }, proxiedSignInPage: { title: 'You do not appear to be signed in. Please try reloading the browser page.', diff --git a/packages/core-plugin-api/report.api.md b/packages/core-plugin-api/report.api.md index 54bbfb94cf..b40088dc78 100644 --- a/packages/core-plugin-api/report.api.md +++ b/packages/core-plugin-api/report.api.md @@ -604,6 +604,11 @@ export type OpenIdConnectApi = { getIdToken(options?: AuthRequestOptions): Promise; }; +// @public +export const openshiftAuthApiRef: ApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +>; + // @public @deprecated export type OptionalParams< Params extends { diff --git a/packages/core-plugin-api/src/apis/definitions/auth.ts b/packages/core-plugin-api/src/apis/definitions/auth.ts index 9339a3e18a..f8686cb128 100644 --- a/packages/core-plugin-api/src/apis/definitions/auth.ts +++ b/packages/core-plugin-api/src/apis/definitions/auth.ts @@ -474,3 +474,20 @@ export const vmwareCloudAuthApiRef: ApiRef< > = createApiRef({ id: 'core.auth.vmware-cloud', }); + +/** + * Provides authentication towards OpenShift APIs and identities. + * + * @public + * @remarks + * + * See {@link https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/authentication_and_authorization/configuring-oauth-clients} + * on how to configure the OAuth clients and + * {@link https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html-single/authentication_and_authorization/index#tokens-scoping-about_configuring-internal-oauth} + * for available scopes. + */ +export const openshiftAuthApiRef: ApiRef< + OAuthApi & ProfileInfoApi & BackstageIdentityApi & SessionApi +> = createApiRef({ + id: 'core.auth.openshift', +}); diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index 261e595b30..0e622c2490 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/create-app +## 0.7.4-next.2 + +### Patch Changes + +- Bumped create-app version. + ## 0.7.4-next.1 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index 7f2f9e4cd5..59f8498c54 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/create-app", - "version": "0.7.4-next.1", + "version": "0.7.4-next.2", "description": "A CLI that helps you create your own Backstage app", "backstage": { "role": "cli" diff --git a/packages/dev-utils/CHANGELOG.md b/packages/dev-utils/CHANGELOG.md index 503ae406ae..45aaf0a814 100644 --- a/packages/dev-utils/CHANGELOG.md +++ b/packages/dev-utils/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/dev-utils +## 1.1.14-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + ## 1.1.14-next.1 ### Patch Changes diff --git a/packages/dev-utils/package.json b/packages/dev-utils/package.json index 55b4c3fdfe..fd5881af44 100644 --- a/packages/dev-utils/package.json +++ b/packages/dev-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/dev-utils", - "version": "1.1.14-next.1", + "version": "1.1.14-next.2", "description": "Utilities for developing Backstage plugins.", "backstage": { "role": "web-library" diff --git a/packages/frontend-defaults/src/createApp.test.tsx b/packages/frontend-defaults/src/createApp.test.tsx index 351bc8f1b5..7b5e345e12 100644 --- a/packages/frontend-defaults/src/createApp.test.tsx +++ b/packages/frontend-defaults/src/createApp.test.tsx @@ -372,6 +372,7 @@ describe('createApp', () => { + diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index e6259c70d7..f9e2336408 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -69,6 +69,7 @@ import { OAuthScope } from '@backstage/core-plugin-api'; import { oktaAuthApiRef } from '@backstage/core-plugin-api'; import { oneloginAuthApiRef } from '@backstage/core-plugin-api'; import { OpenIdConnectApi } from '@backstage/core-plugin-api'; +import { openshiftAuthApiRef } from '@backstage/core-plugin-api'; import { PendingOAuthRequest } from '@backstage/core-plugin-api'; import { ProfileInfo } from '@backstage/core-plugin-api'; import { ProfileInfoApi } from '@backstage/core-plugin-api'; @@ -1518,6 +1519,8 @@ export { oneloginAuthApiRef }; export { OpenIdConnectApi }; +export { openshiftAuthApiRef }; + // @public export interface OverridableFrontendPlugin< TRoutes extends { diff --git a/packages/frontend-plugin-api/src/apis/definitions/auth.ts b/packages/frontend-plugin-api/src/apis/definitions/auth.ts index 89509082f0..5a31c1603d 100644 --- a/packages/frontend-plugin-api/src/apis/definitions/auth.ts +++ b/packages/frontend-plugin-api/src/apis/definitions/auth.ts @@ -37,4 +37,5 @@ export { microsoftAuthApiRef, oneloginAuthApiRef, vmwareCloudAuthApiRef, + openshiftAuthApiRef, } from '@backstage/core-plugin-api'; diff --git a/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.test.ts b/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.test.ts index ec07d1b465..0468e96e14 100644 --- a/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.test.ts +++ b/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.test.ts @@ -231,6 +231,42 @@ describe('SingleInstanceGithubCredentialsProvider tests', () => { expect(token).toEqual(undefined); }); + it('should not fail to issue tokens for an organization when there is a case mismatch in the organization name', async () => { + octokit.apps.listInstallations.mockResolvedValue({ + headers: { + etag: '123', + }, + data: [ + { + id: 1, + repository_selection: 'selected', + account: { + login: 'backstage', + }, + }, + ], + } as RestEndpointMethodTypes['apps']['listInstallations']['response']); + + octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({ + data: { + expires_at: DateTime.local().plus({ hours: 1 }).toString(), + token: 'secret_token', + repository_selection: 'selected', + }, + } as RestEndpointMethodTypes['apps']['createInstallationAccessToken']['response']); + + octokit.apps.listReposAccessibleToInstallation.mockReturnValue({ + data: [{ name: 'some-repo' }], + } as unknown as RestEndpointMethodTypes['apps']['listReposAccessibleToInstallation']['response']); + + const { token, headers } = await github.getCredentials({ + url: 'https://github.com/Backstage', + }); + const expectedToken = 'secret_token'; + expect(headers).toEqual({ Authorization: `Bearer ${expectedToken}` }); + expect(token).toEqual('secret_token'); + }); + it('should not fail to issue tokens for an organization when the app is installed for a single repo', async () => { octokit.apps.listInstallations.mockResolvedValue({ headers: { diff --git a/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.ts b/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.ts index fd3c02486f..eaaabe8b0f 100644 --- a/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.ts +++ b/packages/integration/src/github/SingleInstanceGithubCredentialsProvider.ts @@ -102,7 +102,9 @@ class GithubAppManager { private readonly allowedInstallationOwners: string[] | undefined; // undefined allows all installations constructor(config: GithubAppConfig, baseUrl?: string) { - this.allowedInstallationOwners = config.allowedInstallationOwners; + this.allowedInstallationOwners = config.allowedInstallationOwners?.map( + owner => owner.toLocaleLowerCase('en-US'), + ); this.baseUrl = baseUrl; this.baseAuthConfig = { appId: config.appId, @@ -121,7 +123,11 @@ class GithubAppManager { repo?: string, ): Promise<{ accessToken: string | undefined }> { if (this.allowedInstallationOwners) { - if (!this.allowedInstallationOwners?.includes(owner)) { + if ( + !this.allowedInstallationOwners?.includes( + owner.toLocaleLowerCase('en-US'), + ) + ) { return { accessToken: undefined }; // An empty token allows anonymous access to public repos } } diff --git a/packages/repo-tools/CHANGELOG.md b/packages/repo-tools/CHANGELOG.md index 569444b4b8..a5a9bb0505 100644 --- a/packages/repo-tools/CHANGELOG.md +++ b/packages/repo-tools/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/repo-tools +## 0.15.2-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + ## 0.15.2-next.0 ### Patch Changes diff --git a/packages/repo-tools/package.json b/packages/repo-tools/package.json index 9b7c875279..d93785f25e 100644 --- a/packages/repo-tools/package.json +++ b/packages/repo-tools/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/repo-tools", - "version": "0.15.2-next.0", + "version": "0.15.2-next.1", "description": "CLI for Backstage repo tooling ", "backstage": { "role": "cli" diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index a88c4593e1..d251516dcd 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/ui +## 0.7.1-next.0 + +### Patch Changes + +- 7307930: Add missing class for flex: baseline +- 89da341: Fix Select component to properly attach aria-label and aria-labelledby props to the rendered element for improved accessibility. + ## 0.7.0 ### Minor Changes diff --git a/packages/ui/package.json b/packages/ui/package.json index 2ac399fcee..36b51f0bc8 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/ui", - "version": "0.7.0", + "version": "0.7.1-next.0", "backstage": { "role": "web-library" }, diff --git a/packages/yarn-plugin/package.json b/packages/yarn-plugin/package.json index c534c50c76..4bd43fce40 100644 --- a/packages/yarn-plugin/package.json +++ b/packages/yarn-plugin/package.json @@ -31,6 +31,7 @@ }, "dependencies": { "@backstage/cli-common": "workspace:^", + "@backstage/errors": "workspace:^", "@backstage/release-manifests": "workspace:^", "@yarnpkg/core": "^4.4.1", "@yarnpkg/fslib": "^3.1.2", diff --git a/packages/yarn-plugin/src/util/getCurrentBackstageVersion.test.ts b/packages/yarn-plugin/src/util/getCurrentBackstageVersion.test.ts index 4b1f008fce..a0ce45c18f 100644 --- a/packages/yarn-plugin/src/util/getCurrentBackstageVersion.test.ts +++ b/packages/yarn-plugin/src/util/getCurrentBackstageVersion.test.ts @@ -73,17 +73,15 @@ describe('getCurrentBackstageVersion', () => { }); it.each` - description | content - ${'is missing'} | ${{}} - ${'is invalid'} | ${{ 'backstage.json': '}{' }} - ${'has missing version'} | ${{ 'backstage.json': '{"a":"b"}' }} - ${'has invalid version'} | ${{ 'backstage.json': '{"version":"foobar"}' }} - `('throws if backstage.json $description', ({ content }) => { + description | content | message + ${'is missing'} | ${{}} | ${/valid version string not found.*no such file/i} + ${'is invalid'} | ${{ 'backstage.json': '}{' }} | ${/valid version string not found.*not valid json/i} + ${'has missing version'} | ${{ 'backstage.json': '{"a":"b"}' }} | ${/valid version string not found.*version field is missing/i} + ${'has invalid version'} | ${{ 'backstage.json': '{"version":"foobar"}' }} | ${/valid version string not found.*exists but is not valid semver/i} + `('throws if backstage.json $description', ({ content, message }) => { mockDir.addContent(content); - expect(() => getCurrentBackstageVersion()).toThrow( - /valid version string not found/i, - ); + expect(() => getCurrentBackstageVersion()).toThrow(message); }); it('caches repeated calls', () => { diff --git a/packages/yarn-plugin/src/util/getCurrentBackstageVersion.ts b/packages/yarn-plugin/src/util/getCurrentBackstageVersion.ts index 5280854fb3..be80d29376 100644 --- a/packages/yarn-plugin/src/util/getCurrentBackstageVersion.ts +++ b/packages/yarn-plugin/src/util/getCurrentBackstageVersion.ts @@ -18,6 +18,7 @@ import assert from 'assert'; import { valid as semverValid } from 'semver'; import { ppath, xfs } from '@yarnpkg/fslib'; import { BACKSTAGE_JSON } from '@backstage/cli-common'; +import { ForwardedError } from '@backstage/errors'; import { memoize } from './memoize'; import { getWorkspaceRoot } from './getWorkspaceRoot'; @@ -26,11 +27,16 @@ export const getCurrentBackstageVersion = memoize(() => { let backstageVersion: string | null = null; try { - backstageVersion = semverValid(xfs.readJsonSync(backstageJsonPath).version); + const backstageVersionRaw = xfs.readJsonSync(backstageJsonPath).version; + assert(backstageVersionRaw !== undefined, 'Version field is missing'); + backstageVersion = semverValid(backstageVersionRaw); - assert(backstageVersion !== null); - } catch { - throw new Error('Valid version string not found in backstage.json'); + assert(backstageVersion !== null, 'Version exists but is not valid semver'); + } catch (err) { + throw new ForwardedError( + 'Valid version string not found in backstage.json', + err, + ); } return backstageVersion; diff --git a/plugins/api-docs/CHANGELOG.md b/plugins/api-docs/CHANGELOG.md index 25671d8050..c57a56754c 100644 --- a/plugins/api-docs/CHANGELOG.md +++ b/plugins/api-docs/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-api-docs +## 0.12.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/plugin-catalog@1.31.3-next.2 + - @backstage/core-compat-api@0.5.2-next.2 + ## 0.12.11-next.1 ### Patch Changes diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index 4fcae79fba..17cf78a69a 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-api-docs", - "version": "0.12.11-next.1", + "version": "0.12.11-next.2", "description": "A Backstage plugin that helps represent API entities in the frontend", "backstage": { "role": "frontend-plugin", diff --git a/plugins/app-backend/CHANGELOG.md b/plugins/app-backend/CHANGELOG.md index bd097b0005..ffe2bd1b71 100644 --- a/plugins/app-backend/CHANGELOG.md +++ b/plugins/app-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-app-backend +## 0.5.6-next.1 + +### Patch Changes + +- afd368e: Internal update to not expose the old `createRouter`. +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-app-node@0.1.37-next.1 + ## 0.5.6-next.0 ### Patch Changes diff --git a/plugins/app-backend/package.json b/plugins/app-backend/package.json index b81e709926..4640a6459b 100644 --- a/plugins/app-backend/package.json +++ b/plugins/app-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-backend", - "version": "0.5.6-next.0", + "version": "0.5.6-next.1", "description": "A Backstage backend plugin that serves the Backstage frontend app", "backstage": { "role": "backend-plugin", diff --git a/plugins/app-backend/src/index.ts b/plugins/app-backend/src/index.ts index 9f83f6e30a..3f8a0002a7 100644 --- a/plugins/app-backend/src/index.ts +++ b/plugins/app-backend/src/index.ts @@ -21,4 +21,3 @@ */ export { appPlugin as default } from './service/appPlugin'; -export * from './service/router'; diff --git a/plugins/app-node/CHANGELOG.md b/plugins/app-node/CHANGELOG.md index 2063c2db48..14b3a215ee 100644 --- a/plugins/app-node/CHANGELOG.md +++ b/plugins/app-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-app-node +## 0.1.37-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + ## 0.1.37-next.0 ### Patch Changes diff --git a/plugins/app-node/package.json b/plugins/app-node/package.json index 07340379e9..f28b28f461 100644 --- a/plugins/app-node/package.json +++ b/plugins/app-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-node", - "version": "0.1.37-next.0", + "version": "0.1.37-next.1", "description": "Node.js library for the app plugin", "backstage": { "role": "node-library", diff --git a/plugins/app/report.api.md b/plugins/app/report.api.md index 24885bed4b..d12ada15b4 100644 --- a/plugins/app/report.api.md +++ b/plugins/app/report.api.md @@ -539,6 +539,21 @@ const appPlugin: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; + 'api:app/openshift-auth': ExtensionDefinition<{ + kind: 'api'; + name: 'openshift-auth'; + config: {}; + configInput: {}; + output: ExtensionDataRef; + inputs: {}; + params: < + TApi, + TImpl extends TApi, + TDeps extends { [name in string]: unknown }, + >( + params: ApiFactory, + ) => ExtensionBlueprintParams; + }>; 'api:app/permission': ExtensionDefinition<{ kind: 'api'; name: 'permission'; diff --git a/plugins/app/src/defaultApis.ts b/plugins/app/src/defaultApis.ts index 0337f6c4f4..0b4eb5c825 100644 --- a/plugins/app/src/defaultApis.ts +++ b/plugins/app/src/defaultApis.ts @@ -35,6 +35,7 @@ import { createFetchApi, FetchMiddlewares, VMwareCloudAuth, + OpenShiftAuth, } from '../../../packages/core-app-api/src/apis/implementations'; import { @@ -56,6 +57,7 @@ import { bitbucketServerAuthApiRef, atlassianAuthApiRef, vmwareCloudAuthApiRef, + openshiftAuthApiRef, } from '@backstage/core-plugin-api'; import { ApiBlueprint, dialogApiRef } from '@backstage/frontend-plugin-api'; import { @@ -353,6 +355,26 @@ export const apis = [ }, }), }), + ApiBlueprint.make({ + name: 'openshift-auth', + params: defineParams => + defineParams({ + api: openshiftAuthApiRef, + deps: { + discoveryApi: discoveryApiRef, + oauthRequestApi: oauthRequestApiRef, + configApi: configApiRef, + }, + factory: ({ discoveryApi, oauthRequestApi, configApi }) => { + return OpenShiftAuth.create({ + configApi, + discoveryApi, + oauthRequestApi, + environment: configApi.getOptionalString('auth.environment'), + }); + }, + }), + }), ApiBlueprint.make({ name: 'permission', params: defineParams => diff --git a/plugins/auth-backend-module-openshift-provider/.eslintrc.js b/plugins/auth-backend-module-openshift-provider/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/auth-backend-module-openshift-provider/README.md b/plugins/auth-backend-module-openshift-provider/README.md new file mode 100644 index 0000000000..ae4700d561 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/README.md @@ -0,0 +1,5 @@ +# @backstage/plugin-auth-backend-module-openshift-provider + +The openshift-provider backend module for the auth plugin. + +_This plugin was created through the Backstage CLI_ diff --git a/plugins/auth-backend-module-openshift-provider/catalog-info.yaml b/plugins/auth-backend-module-openshift-provider/catalog-info.yaml new file mode 100644 index 0000000000..3db615244a --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/catalog-info.yaml @@ -0,0 +1,10 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth-backend-module-openshift-provider + title: '@backstage/plugin-auth-backend-module-openshift-provider' + description: The OpenShift backend module for the auth plugin. +spec: + lifecycle: experimental + type: backstage-backend-plugin-module + owner: auth-maintainers diff --git a/plugins/auth-backend-module-openshift-provider/config.d.ts b/plugins/auth-backend-module-openshift-provider/config.d.ts new file mode 100644 index 0000000000..1fdaeb1532 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/config.d.ts @@ -0,0 +1,44 @@ +/* + * 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 { HumanDuration } from '@backstage/types'; + +export interface Config { + auth?: { + providers?: { + /** @visibility frontend */ + openshift?: { + [authEnv: string]: { + clientId: string; + /** + * @visibility secret + */ + clientSecret: string; + authorizationUrl: string; + tokenUrl: string; + callbackUrl?: string; + openshiftApiServerUrl: string; + signIn?: { + resolvers: Array<{ + resolver: 'displayNameMatchingUserEntityName'; + dangerouslyAllowSignInWithoutUserInCatalog?: boolean; + }>; + }; + sessionDuration?: HumanDuration | string; + }; + }; + }; + }; +} diff --git a/plugins/auth-backend-module-openshift-provider/dev/index.ts b/plugins/auth-backend-module-openshift-provider/dev/index.ts new file mode 100644 index 0000000000..99f6828292 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/dev/index.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 { createBackend } from '@backstage/backend-defaults'; +import authPlugin from '@backstage/plugin-auth-backend'; +import authModuleOpenShiftProvider from '../src'; + +const backend = createBackend(); + +backend.add(authPlugin); +backend.add(authModuleOpenShiftProvider); + +backend.start(); diff --git a/plugins/auth-backend-module-openshift-provider/package.json b/plugins/auth-backend-module-openshift-provider/package.json new file mode 100644 index 0000000000..9fad0b542e --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/package.json @@ -0,0 +1,55 @@ +{ + "name": "@backstage/plugin-auth-backend-module-openshift-provider", + "version": "0.0.0", + "description": "The OpenShift backend module for the auth plugin.", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "auth", + "pluginPackage": "@backstage/plugin-auth-backend" + }, + "publishConfig": { + "access": "public", + "main": "dist/index.cjs.js", + "types": "dist/index.d.ts" + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/auth-backend-module-openshift-provider" + }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist", + "config.d.ts" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/backend-plugin-api": "workspace:^", + "@backstage/catalog-model": "workspace:^", + "@backstage/plugin-auth-node": "workspace:^", + "@backstage/types": "workspace:^", + "passport-oauth2": "^1.8.0", + "zod": "^3.24.2" + }, + "devDependencies": { + "@backstage/backend-defaults": "workspace:^", + "@backstage/backend-test-utils": "workspace:^", + "@backstage/cli": "workspace:^", + "@backstage/config": "workspace:^", + "@backstage/plugin-auth-backend": "workspace:^", + "express": "^4.18.2", + "msw": "^2.7.3", + "supertest": "^7.1.0" + }, + "configSchema": "config.d.ts" +} diff --git a/plugins/auth-backend-module-openshift-provider/report.api.md b/plugins/auth-backend-module-openshift-provider/report.api.md new file mode 100644 index 0000000000..aa429e1d47 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/report.api.md @@ -0,0 +1,28 @@ +## API Report File for "@backstage/plugin-auth-backend-module-openshift-provider" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; +import { OAuthAuthenticator } from '@backstage/plugin-auth-node'; +import { PassportOAuthAuthenticatorHelper } from '@backstage/plugin-auth-node'; +import { PassportProfile } from '@backstage/plugin-auth-node'; + +// @public (undocumented) +const authModuleOpenshiftProvider: BackendFeature; +export default authModuleOpenshiftProvider; + +// @public (undocumented) +export const openshiftAuthenticator: OAuthAuthenticator< + OpenShiftAuthenticatorContext, + PassportProfile +>; + +// @public (undocumented) +export interface OpenShiftAuthenticatorContext { + // (undocumented) + helper: PassportOAuthAuthenticatorHelper; + // (undocumented) + openshiftApiServerUrl: string; +} +``` diff --git a/plugins/auth-backend-module-openshift-provider/src/authenticator.test.ts b/plugins/auth-backend-module-openshift-provider/src/authenticator.test.ts new file mode 100644 index 0000000000..28a7738d21 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/src/authenticator.test.ts @@ -0,0 +1,226 @@ +/* + * 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 { setupServer } from 'msw/node'; +import { + decodeOAuthState, + encodeOAuthState, +} from '@backstage/plugin-auth-node'; +import { registerMswTestHooks } from '@backstage/backend-test-utils'; +import { http, HttpResponse } from 'msw'; +import { openshiftAuthenticator } from './authenticator'; +import { ConfigReader } from '@backstage/config'; +import { + OAuthState, + OAuthAuthenticatorStartInput, + OAuthAuthenticatorAuthenticateInput, +} from '@backstage/plugin-auth-node'; +import express from 'express'; + +describe('openshiftAuthenticator', () => { + let implementation: any; + let oauthState: OAuthState; + + const mswServer = setupServer(); + registerMswTestHooks(mswServer); + + beforeEach(() => { + mswServer.use( + http.post('https://openshift.test/oauth/token', () => { + return HttpResponse.json({ + access_token: 'accessToken', + scope: 'user:full', + expires_in: 60 * 60 * 24, + }); + }), + http.get( + 'https://api.openshift.test/apis/user.openshift.io/v1/users/~', + async () => { + return HttpResponse.json({ + kind: 'User', + apiVersion: 'user.openshift.io/v1', + metadata: { + name: 'alice', + uid: 'ca993628-8817-4a3b-9811-be4a34c60bf4', + resourceVersion: '1', + creationTimestamp: '2022-01-11T13:10:45Z', + managedFields: [], + }, + fullName: 'Alice Adams', + identities: ['SSO:id'], + groups: ['system:authenticated', 'system:authenticated:oauth'], + }); + }, + ), + ); + + implementation = openshiftAuthenticator.initialize({ + callbackUrl: 'https://backstage.test/callback', + config: new ConfigReader({ + clientId: 'clientId', + clientSecret: 'clientSecret', + authorizationUrl: 'https://openshift.test/oauth/authorize', + tokenUrl: 'https://openshift.test/oauth/token', + openshiftApiServerUrl: 'https://api.openshift.test', + }), + }); + + oauthState = { + nonce: 'nonce', + env: 'env', + }; + }); + + afterEach(() => { + jest.clearAllMocks(); + }); + + describe('#start', () => { + let fakeSession: Record; + let startRequest: OAuthAuthenticatorStartInput; + + beforeEach(() => { + fakeSession = {}; + startRequest = { + state: encodeOAuthState(oauthState), + req: { + method: 'GET', + url: 'test', + session: fakeSession, + }, + } as unknown as OAuthAuthenticatorStartInput; + }); + + it('initiates authorization code grant', async () => { + const startResponse = await openshiftAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('response_type')).toBe('code'); + }); + + it('passes client ID from config', async () => { + const startResponse = await openshiftAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('client_id')).toBe('clientId'); + }); + + it('passes callback URL from config', async () => { + const startResponse = await openshiftAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + + expect(searchParams.get('redirect_uri')).toBe( + 'https://backstage.test/callback', + ); + }); + + it('encodes OAuth state in query param', async () => { + const startResponse = await openshiftAuthenticator.start( + startRequest, + implementation, + ); + const { searchParams } = new URL(startResponse.url); + const stateParam = searchParams.get('state'); + const decodedState = decodeOAuthState(stateParam!); + + expect(decodedState).toMatchObject(oauthState); + }); + }); + + describe('#authenticate', () => { + let handlerRequest: OAuthAuthenticatorAuthenticateInput; + + beforeEach(() => { + handlerRequest = { + req: { + method: 'GET', + query: { + code: 'authorization_code', + state: encodeOAuthState(oauthState), + }, + session: { + 'oauth2:openshift': { + state: encodeOAuthState(oauthState), + }, + }, + } as unknown as express.Request, + }; + }); + + it('exchanges authorization code for access token', async () => { + const authenticatorResult = await openshiftAuthenticator.authenticate( + handlerRequest, + implementation, + ); + const accessToken = authenticatorResult.session.accessToken; + + expect(accessToken).toEqual('accessToken'); + }); + + it('returns granted scope', async () => { + const authenticatorResult = await openshiftAuthenticator.authenticate( + handlerRequest, + implementation, + ); + const responseScope = authenticatorResult.session.scope; + + expect(responseScope).toEqual('user:full'); + }); + + it('returns a default session.tokentype field', async () => { + const authenticatorResult = await openshiftAuthenticator.authenticate( + handlerRequest, + implementation, + ); + const tokenType = authenticatorResult.session.tokenType; + + expect(tokenType).toEqual('bearer'); + }); + + it('returns displayName', async () => { + const authenticatorResult = await openshiftAuthenticator.authenticate( + handlerRequest, + implementation, + ); + + expect(authenticatorResult).toMatchObject({ + fullProfile: { + displayName: 'alice', + }, + }); + }); + + it('should store access token as refresh token', async () => { + const authenticatorResult = await openshiftAuthenticator.authenticate( + handlerRequest, + implementation, + ); + + expect(authenticatorResult.session.refreshToken).toBe( + authenticatorResult.session.accessToken, + ); + }); + }); +}); diff --git a/plugins/auth-backend-module-openshift-provider/src/authenticator.ts b/plugins/auth-backend-module-openshift-provider/src/authenticator.ts new file mode 100644 index 0000000000..0c9acb6287 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/src/authenticator.ts @@ -0,0 +1,184 @@ +/* + * 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 { + createOAuthAuthenticator, + PassportOAuthAuthenticatorHelper, + PassportOAuthDoneCallback, + PassportProfile, +} from '@backstage/plugin-auth-node'; +import { createHash } from 'node:crypto'; +import OAuth2Strategy from 'passport-oauth2'; +import { z } from 'zod'; + +/** @public */ +export interface OpenShiftAuthenticatorContext { + openshiftApiServerUrl: string; + helper: PassportOAuthAuthenticatorHelper; +} + +/** @private + * Schema for user.openshift.io/v1, + * see https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/user_and_group_apis/user-user-openshift-io-v1#user-user-openshift-io-v1 + */ +const OpenShiftUser = z.object({ + metadata: z.object({ + name: z.string(), + }), +}); + +/** @public */ +export const openshiftAuthenticator = createOAuthAuthenticator< + OpenShiftAuthenticatorContext, + PassportProfile +>({ + defaultProfileTransform: + PassportOAuthAuthenticatorHelper.defaultProfileTransform, + scopes: { + required: ['user:full'], + }, + initialize({ callbackUrl, config }) { + const clientId = config.getString('clientId'); + const clientSecret = config.getString('clientSecret'); + const authorizationUrl = config.getString('authorizationUrl'); + const tokenUrl = config.getString('tokenUrl'); + const openshiftApiServerUrl = config.getString('openshiftApiServerUrl'); + + // userUrl: `${openshiftApiServerUrl}/apis/user.openshift.io/v1/users/~`, + const strategy = new OAuth2Strategy( + { + clientID: clientId, + clientSecret: clientSecret, + callbackURL: callbackUrl, + authorizationURL: authorizationUrl, + tokenURL: tokenUrl, + passReqToCallback: false, + }, + ( + accessToken: any, + refreshToken: string, + params: any, + fullProfile: PassportProfile, + done: PassportOAuthDoneCallback, + ) => { + done(undefined, { fullProfile, params, accessToken }, { refreshToken }); + }, + ); + + strategy.userProfile = function userProfile( + accessToken: string, + done: (err?: unknown, profile?: any) => void, + ): void { + this._oauth2.useAuthorizationHeaderforGET(true); + + this._oauth2.get( + `${openshiftApiServerUrl}/apis/user.openshift.io/v1/users/~`, + accessToken, + (error, data, _) => { + if (error !== null && error.statusCode !== 200) { + done(new Error(`HTTP error! Status: ${error.statusCode}`)); + return; + } + + if (!data) { + done(new Error('No data provided!')); + return; + } + + if (typeof data !== 'string') { + done(new Error('Data of type Buffer is not supported!')); + return; + } + + const user = OpenShiftUser.parse(JSON.parse(data)); + done(null, { displayName: user.metadata.name }); + }, + ); + }; + + return { + openshiftApiServerUrl, + helper: PassportOAuthAuthenticatorHelper.from(strategy), + }; + }, + async start(input, { helper }) { + return helper.start(input, { + accessType: 'offline', + prompt: 'consent', + }); + }, + async authenticate(input, { helper }) { + // Same workaround as the GitHub provider; see https://github.com/backstage/backstage/issues/25383 + const { fullProfile, session } = await helper.authenticate(input); + session.refreshToken = session.accessToken; + session.refreshTokenExpiresInSeconds = session.expiresInSeconds; + return { fullProfile, session }; + }, + async refresh(input, { helper }) { + // Because the session is refreshed on login, this override is crucial, + // see https://github.com/backstage/backstage/issues/25383 + const accessToken = input.refreshToken; + + const fullProfile = await helper.fetchProfile(accessToken).catch(error => { + if (error.oauthError?.statusCode === 401) { + throw new Error('Invalid access token'); + } + throw error; + }); + + return { + fullProfile, + session: { + accessToken, + tokenType: 'bearer', + scope: input.scope, + refreshToken: input.refreshToken, + }, + }; + }, + async logout(input, { openshiftApiServerUrl, helper }) { + // Due to the implementation of createOAuthRouteHandlers, only the refresh token is set. + // In this provider, the refresh token actually IS the access token. + const accessToken = input.refreshToken; + if (!accessToken) { + throw new Error('access token/refresh token needs to be set for logout'); + } + + // Check if access token is still valid. + try { + await helper.fetchProfile(accessToken); + } catch { + // Invalid token, no need to delete OAuthAccessToken. + return; + } + + // Calculate token name, see: + // https://docs.redhat.com/en/documentation/openshift_container_platform/latest/html/oauth_apis/oauthaccesstoken-oauth-openshift-io-v1#apis-oauth-openshift-io-v1-oauthaccesstokens + const tokenName = createHash('sha256') + .update(accessToken.slice('sha256~'.length)) + .digest() + .toString('base64url'); + + const response = await fetch( + `${openshiftApiServerUrl}/apis/oauth.openshift.io/v1/oauthaccesstokens/sha256~${tokenName}`, + { method: 'DELETE', headers: { Authorization: `Bearer ${accessToken}` } }, + ); + + if (response.status === 401) { + throw new Error('unauthorized'); + } + }, +}); diff --git a/plugins/auth-backend-module-openshift-provider/src/index.ts b/plugins/auth-backend-module-openshift-provider/src/index.ts new file mode 100644 index 0000000000..4c8dd6cb22 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/src/index.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ +/** + * The openshift-provider backend module for the auth plugin. + * + * @packageDocumentation + */ +export { + openshiftAuthenticator, + type OpenShiftAuthenticatorContext, +} from './authenticator'; +export { authModuleOpenshiftProvider as default } from './module'; diff --git a/plugins/auth-backend-module-openshift-provider/src/module.ts b/plugins/auth-backend-module-openshift-provider/src/module.ts new file mode 100644 index 0000000000..18d96c4778 --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/src/module.ts @@ -0,0 +1,45 @@ +/* + * 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 { createBackendModule } from '@backstage/backend-plugin-api'; +import { + authProvidersExtensionPoint, + createOAuthProviderFactory, +} from '@backstage/plugin-auth-node'; +import { openshiftAuthenticator } from './authenticator'; +import { openshiftSignInResolvers } from './resolvers'; + +/** @public */ +export const authModuleOpenshiftProvider = createBackendModule({ + pluginId: 'auth', + moduleId: 'openshift-provider', + register(reg) { + reg.registerInit({ + deps: { providers: authProvidersExtensionPoint }, + async init({ providers }) { + providers.registerProvider({ + providerId: 'openshift', + factory: createOAuthProviderFactory({ + authenticator: openshiftAuthenticator, + signInResolverFactories: { + ...openshiftSignInResolvers, + }, + }), + }); + }, + }); + }, +}); diff --git a/plugins/auth-backend-module-openshift-provider/src/resolvers.ts b/plugins/auth-backend-module-openshift-provider/src/resolvers.ts new file mode 100644 index 0000000000..dee55ec4ca --- /dev/null +++ b/plugins/auth-backend-module-openshift-provider/src/resolvers.ts @@ -0,0 +1,68 @@ +/* + * 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 { + createSignInResolverFactory, + OAuthAuthenticatorResult, + PassportProfile, + SignInInfo, +} from '@backstage/plugin-auth-node'; + +import { + DEFAULT_NAMESPACE, + stringifyEntityRef, +} from '@backstage/catalog-model'; +import { z } from 'zod'; + +export namespace openshiftSignInResolvers { + export const displayNameMatchingUserEntityName = createSignInResolverFactory({ + optionsSchema: z + .object({ + dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(), + }) + .optional(), + create(options = {}) { + return async ( + info: SignInInfo>, + ctx, + ) => { + const { displayName } = info.profile; + + if (!displayName) { + throw new Error( + `OpenShift user profile does not contain a displayName`, + ); + } + + const userRef = stringifyEntityRef({ + kind: 'User', + name: displayName, + namespace: DEFAULT_NAMESPACE, + }); + + return await ctx.signInWithCatalogUser( + { entityRef: userRef }, + { + dangerousEntityRefFallback: + options?.dangerouslyAllowSignInWithoutUserInCatalog + ? { entityRef: { name: displayName } } + : undefined, + }, + ); + }; + }, + }); +} diff --git a/plugins/auth-backend/CHANGELOG.md b/plugins/auth-backend/CHANGELOG.md index 54dee8262d..7aa33c315a 100644 --- a/plugins/auth-backend/CHANGELOG.md +++ b/plugins/auth-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-auth-backend +## 0.25.4-next.1 + +### Patch Changes + +- 1d47bf3: Implementing Dynamic Client Registration with the OIDC server. You can enable this by setting `auth.experimentalDynamicClientRegistration.enabled` in `app-config.yaml`. This is highly experimental, but feedback welcome. +- 54ddfef: Updating plugin metadata +- Updated dependencies + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.25.4-next.0 ### Patch Changes diff --git a/plugins/auth-backend/migrations/20250909120000_oidc_client_registration.js b/plugins/auth-backend/migrations/20250909120000_oidc_client_registration.js new file mode 100644 index 0000000000..87391c3467 --- /dev/null +++ b/plugins/auth-backend/migrations/20250909120000_oidc_client_registration.js @@ -0,0 +1,159 @@ +/* + * 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. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + // These tables make up the OIDC client registration flow. + // Clients are the top of the tree, that are created by the client registration flow. + await knex.schema.createTable('oidc_clients', table => { + table.comment( + 'OIDC clients that are registered via dynamic client registration', + ); + + table + .string('client_id') + .primary() + .notNullable() + .comment('The unique client ID of the client'); + + table + .string('client_secret') + .notNullable() + .comment('The client secret of the client'); + + table + .string('client_name') + .notNullable() + .comment('The name of the client, should be human readable'); + + table + .text('response_types', 'longtext') + .notNullable() + .comment('JSON array of supported response types'); + + table + .text('grant_types', 'longtext') + .notNullable() + .comment('JSON array of supported grant types'); + + table + .text('redirect_uris', 'longtext') + .notNullable() + .comment('Allowed redirect URIs as JSON array'); + + table.text('scope').nullable().comment('Default scopes for the client'); + + table + .text('metadata', 'longtext') + .nullable() + .comment('Additional client metadata as JSON'); + }); + + await knex.schema.createTable('oauth_authorization_sessions', table => { + table.comment('Core OAuth authorization sessions with shared context'); + + table + .string('id') + .primary() + .notNullable() + .comment('Unique session identifier'); + + table.string('client_id').notNullable().comment('OIDC client identifier'); + + table + .string('user_entity_ref') + .nullable() + .comment('Backstage user entity reference'); + + table + .text('redirect_uri', 'longtext') + .notNullable() + .comment('Client redirect URI'); + + table.text('scope').nullable().comment('Requested scopes space-separated'); + + table.string('state').nullable().comment('Client state parameter'); + + table.string('response_type').notNullable().comment('OAuth2 response type'); + + table.string('code_challenge').nullable().comment('PKCE code challenge'); + + table + .string('code_challenge_method') + .nullable() + .comment('PKCE code challenge method'); + + table.string('nonce').nullable().comment('OIDC nonce parameter'); + + table + .enum('status', ['pending', 'approved', 'rejected', 'expired']) + .defaultTo('pending') + .comment('Authorization session status'); + + table + .timestamp('expires_at', { useTz: true, precision: 0 }) + .notNullable() + .comment('Session expiration timestamp'); + + table.foreign('client_id').references('client_id').inTable('oidc_clients'); + table.index(['client_id', 'user_entity_ref']); + table.index(['status', 'expires_at']); + }); + + await knex.schema.createTable('oidc_authorization_codes', table => { + table.comment('OAuth authorization codes for code exchange flow'); + + table + .string('code') + .primary() + .notNullable() + .comment('Unique authorization code'); + + table + .string('session_id') + .notNullable() + .comment('Authorization session identifier'); + + table + .timestamp('expires_at', { useTz: true, precision: 0 }) + .notNullable() + .comment('Authorization code expiration timestamp'); + + table + .boolean('used') + .defaultTo(false) + .comment('Whether the authorization code has been used'); + + table + .foreign('session_id') + .references('id') + .inTable('oauth_authorization_sessions') + .onDelete('CASCADE'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.dropTable('oidc_authorization_codes'); + await knex.schema.dropTable('oauth_authorization_sessions'); + await knex.schema.dropTable('oidc_clients'); +}; diff --git a/plugins/auth-backend/package.json b/plugins/auth-backend/package.json index 0dddd935e6..e5f048ccae 100644 --- a/plugins/auth-backend/package.json +++ b/plugins/auth-backend/package.json @@ -1,11 +1,12 @@ { "name": "@backstage/plugin-auth-backend", - "version": "0.25.4-next.0", + "version": "0.25.4-next.1", "description": "A Backstage backend plugin that handles authentication", "backstage": { "role": "backend-plugin", "pluginId": "auth", "pluginPackages": [ + "@backstage/plugin-auth", "@backstage/plugin-auth-backend", "@backstage/plugin-auth-node", "@backstage/plugin-auth-react" @@ -60,6 +61,7 @@ "knex": "^3.0.0", "lodash": "^4.17.21", "luxon": "^3.0.0", + "matcher": "^4.0.0", "minimatch": "^9.0.0", "passport": "^0.7.0", "uuid": "^11.0.0" diff --git a/plugins/auth-backend/report.sql.md b/plugins/auth-backend/report.sql.md index b135414af6..7622a5750e 100644 --- a/plugins/auth-backend/report.sql.md +++ b/plugins/auth-backend/report.sql.md @@ -5,6 +5,59 @@ > [!WARNING] > Failed to migrate down from '20220321100910_timestamptz_again.js' +## Table `oauth_authorization_sessions` + +| Column | Type | Nullable | Max Length | Default | +| ----------------------- | -------------------------- | -------- | ---------- | ----------------- | +| `client_id` | `character varying` | false | 255 | - | +| `code_challenge` | `character varying` | true | 255 | - | +| `code_challenge_method` | `character varying` | true | 255 | - | +| `expires_at` | `timestamp with time zone` | false | - | - | +| `id` | `character varying` | false | 255 | - | +| `nonce` | `character varying` | true | 255 | - | +| `redirect_uri` | `text` | false | - | - | +| `response_type` | `character varying` | false | 255 | - | +| `scope` | `text` | true | - | - | +| `state` | `character varying` | true | 255 | - | +| `status` | `text` | true | - | `'pending'::text` | +| `user_entity_ref` | `character varying` | true | 255 | - | + +### Indices + +- `oauth_authorization_sessions_client_id_user_entity_ref_index` (`client_id`, `user_entity_ref`) +- `oauth_authorization_sessions_pkey` (`id`) unique primary +- `oauth_authorization_sessions_status_expires_at_index` (`status`, `expires_at`) + +## Table `oidc_authorization_codes` + +| Column | Type | Nullable | Max Length | Default | +| ------------ | -------------------------- | -------- | ---------- | ------- | +| `code` | `character varying` | false | 255 | - | +| `expires_at` | `timestamp with time zone` | false | - | - | +| `session_id` | `character varying` | false | 255 | - | +| `used` | `boolean` | true | - | `false` | + +### Indices + +- `oidc_authorization_codes_pkey` (`code`) unique primary + +## Table `oidc_clients` + +| Column | Type | Nullable | Max Length | Default | +| ---------------- | ------------------- | -------- | ---------- | ------- | +| `client_id` | `character varying` | false | 255 | - | +| `client_name` | `character varying` | false | 255 | - | +| `client_secret` | `character varying` | false | 255 | - | +| `grant_types` | `text` | false | - | - | +| `metadata` | `text` | true | - | - | +| `redirect_uris` | `text` | false | - | - | +| `response_types` | `text` | false | - | - | +| `scope` | `text` | true | - | - | + +### Indices + +- `oidc_clients_pkey` (`client_id`) unique primary + ## Table `sessions` | Column | Type | Nullable | Max Length | Default | diff --git a/plugins/auth-backend/src/authPlugin.ts b/plugins/auth-backend/src/authPlugin.ts index f3877d48cd..025d72fcb7 100644 --- a/plugins/auth-backend/src/authPlugin.ts +++ b/plugins/auth-backend/src/authPlugin.ts @@ -66,6 +66,7 @@ export const authPlugin = createBackendPlugin({ database: coreServices.database, discovery: coreServices.discovery, auth: coreServices.auth, + httpAuth: coreServices.httpAuth, catalog: catalogServiceRef, }, async init({ @@ -75,6 +76,7 @@ export const authPlugin = createBackendPlugin({ database, discovery, auth, + httpAuth, catalog, }) { const router = await createRouter({ @@ -86,6 +88,7 @@ export const authPlugin = createBackendPlugin({ catalog, providerFactories: Object.fromEntries(providers), ownershipResolver, + httpAuth, }); httpRouter.addAuthPolicy({ path: '/', diff --git a/plugins/auth-backend/src/database/OidcDatabase.test.ts b/plugins/auth-backend/src/database/OidcDatabase.test.ts new file mode 100644 index 0000000000..19285aec0a --- /dev/null +++ b/plugins/auth-backend/src/database/OidcDatabase.test.ts @@ -0,0 +1,293 @@ +/* + * 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 { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { AuthDatabase } from './AuthDatabase'; +import { OidcDatabase } from './OidcDatabase'; +import { resolvePackagePath } from '@backstage/backend-plugin-api'; + +jest.setTimeout(60_000); + +describe('Oidc Database', () => { + const databases = TestDatabases.create(); + + async function createOidcDatabase(databaseId: TestDatabaseId) { + const knex = await databases.init(databaseId); + + await knex.migrate.latest({ + directory: resolvePackagePath( + '@backstage/plugin-auth-backend', + 'migrations', + ), + }); + + return { + oidc: await OidcDatabase.create({ + database: AuthDatabase.create({ + getClient: async () => knex, + }), + }), + }; + } + + describe.each(databases.eachSupportedId())('%p', databaseId => { + describe('Clients', () => { + it('should create and return a client', async () => { + const { oidc } = await createOidcDatabase(databaseId); + + await expect( + oidc.createClient({ + clientId: 'test-client', + clientName: 'Test Client', + clientSecret: 'test-secret', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + }), + ).resolves.toEqual({ + clientId: 'test-client', + clientName: 'Test Client', + clientSecret: 'test-secret', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: undefined, + expiresAt: undefined, + metadata: undefined, + }); + }); + + it('should return the client thats created in a list', async () => { + const { oidc } = await createOidcDatabase(databaseId); + + const client = await oidc.createClient({ + clientId: 'test-client', + clientName: 'Test Client', + clientSecret: 'test-secret', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + }); + + await expect( + oidc.getClient({ clientId: 'test-client' }), + ).resolves.toEqual(client); + }); + + it('should return null if the client does not exist', async () => { + const { oidc } = await createOidcDatabase(databaseId); + + await expect( + oidc.getClient({ clientId: 'test-client' }), + ).resolves.toBeNull(); + }); + }); + + describe('Authorization Sessions', () => { + it('should create and return an authorization session', async () => { + const { oidc } = await createOidcDatabase(databaseId); + + const client = await oidc.createClient({ + clientId: 'test-client', + clientName: 'Test Client', + clientSecret: 'test-secret', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + }); + + const session = await oidc.createAuthorizationSession({ + id: 'test-session', + clientId: client.clientId, + userEntityRef: 'user:default/blam', + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + codeChallenge: 'test-challenge', + codeChallengeMethod: 'S256', + nonce: 'test-nonce', + expiresAt: new Date('2025-01-01T00:00:00Z'), + }); + + expect(session).toEqual( + expect.objectContaining({ + id: 'test-session', + clientId: client.clientId, + userEntityRef: 'user:default/blam', + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + codeChallenge: 'test-challenge', + codeChallengeMethod: 'S256', + nonce: 'test-nonce', + expiresAt: new Date('2025-01-01T00:00:00Z'), + status: 'pending', + }), + ); + }); + + it('should allow updating the authorization session', async () => { + const { oidc } = await createOidcDatabase(databaseId); + + const client = await oidc.createClient({ + clientId: 'test-client', + clientName: 'Test Client', + clientSecret: 'test-secret', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + }); + + const session = await oidc.createAuthorizationSession({ + id: 'test-session', + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + expiresAt: new Date('2025-01-01T00:00:00Z'), + }); + + await expect( + oidc.updateAuthorizationSession({ + id: 'test-session', + userEntityRef: 'user:default/blam', + status: 'approved', + }), + ).resolves.toEqual({ + ...session, + userEntityRef: 'user:default/blam', + status: 'approved', + }); + }); + }); + + describe('Authorization Codes', () => { + it('should create and return an authorization code', async () => { + const { oidc } = await createOidcDatabase(databaseId); + + const client = await oidc.createClient({ + clientId: 'test-client', + clientName: 'Test Client', + clientSecret: 'test-secret', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + }); + + const session = await oidc.createAuthorizationSession({ + id: 'test-session', + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + expiresAt: new Date('2025-01-01T00:00:00Z'), + }); + + const authCode = await oidc.createAuthorizationCode({ + code: 'test-code', + sessionId: session.id, + expiresAt: new Date('2025-01-01T00:00:00Z'), + }); + + expect(authCode).toEqual( + expect.objectContaining({ + code: 'test-code', + sessionId: session.id, + expiresAt: new Date('2025-01-01T00:00:00Z'), + }), + ); + }); + + it('should return authorization code with session data', async () => { + const { oidc } = await createOidcDatabase(databaseId); + + const client = await oidc.createClient({ + clientId: 'test-client', + clientName: 'Test Client', + clientSecret: 'test-secret', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + }); + + const session = await oidc.createAuthorizationSession({ + id: 'test-session', + clientId: client.clientId, + userEntityRef: 'user:default/blam', + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + codeChallenge: 'test-challenge', + codeChallengeMethod: 'S256', + nonce: 'test-nonce', + expiresAt: new Date('2025-01-01T00:00:00Z'), + }); + + const authCode = await oidc.createAuthorizationCode({ + code: 'test-code', + sessionId: session.id, + expiresAt: new Date('2025-01-01T00:00:00Z'), + }); + + const authCodeFromDb = await oidc.getAuthorizationCode({ + code: 'test-code', + }); + const sessionFromDb = await oidc.getAuthorizationSession({ + id: authCodeFromDb!.sessionId, + }); + + expect(authCodeFromDb).toEqual(authCode); + expect(sessionFromDb).toEqual(session); + }); + + it('should allow updating the authorization code', async () => { + const { oidc } = await createOidcDatabase(databaseId); + + const client = await oidc.createClient({ + clientId: 'test-client', + clientName: 'Test Client', + clientSecret: 'test-secret', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + }); + + const session = await oidc.createAuthorizationSession({ + id: 'test-session', + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + expiresAt: new Date('2025-01-01T00:00:00Z'), + }); + + const authCode = await oidc.createAuthorizationCode({ + code: 'test-code', + sessionId: session.id, + expiresAt: new Date('2025-01-01T00:00:00Z'), + }); + + const updatedAuthCode = await oidc.updateAuthorizationCode({ + code: 'test-code', + used: true, + }); + + expect(updatedAuthCode).toEqual({ + ...authCode, + used: true, + }); + }); + }); + }); +}); diff --git a/plugins/auth-backend/src/database/OidcDatabase.ts b/plugins/auth-backend/src/database/OidcDatabase.ts new file mode 100644 index 0000000000..ebb6619400 --- /dev/null +++ b/plugins/auth-backend/src/database/OidcDatabase.ts @@ -0,0 +1,397 @@ +/* + * 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 { Knex } from 'knex'; +import { AuthDatabase } from './AuthDatabase'; + +function toDate(value?: Date | string | number): Date | undefined { + if (!value) { + return undefined; + } + + return typeof value === 'string' || typeof value === 'number' + ? new Date(value) + : value; +} +type OidcClientRow = { + client_id: string; + client_secret: string; + client_name: string; + response_types: string; + grant_types: string; + redirect_uris: string; + scope: string | null; + metadata: string | null; +}; + +type OAuthAuthorizationSessionRow = { + id: string; + client_id: string; + user_entity_ref: string | null; + redirect_uri: string; + scope: string | null; + state: string | null; + response_type: string; + code_challenge: string | null; + code_challenge_method: string | null; + nonce: string | null; + status: 'pending' | 'approved' | 'rejected' | 'expired'; + expires_at: Date | string; +}; + +type OidcAuthorizationCodeRow = { + code: string; + session_id: string; + expires_at: Date | string; + used: boolean; +}; + +export type Client = { + clientId: string; + clientName: string; + clientSecret: string; + redirectUris: string[]; + responseTypes: string[]; + grantTypes: string[]; + scope?: string; + metadata?: Record; +}; + +export type AuthorizationSession = { + id: string; + clientId: string; + userEntityRef?: string; + redirectUri: string; + scope?: string; + state?: string; + responseType: string; + codeChallenge?: string; + codeChallengeMethod?: string; + nonce?: string; + status: 'pending' | 'approved' | 'rejected' | 'expired'; + expiresAt: Date; +}; + +export type ConsentRequest = { + id: string; + sessionId: string; + expiresAt: Date; +}; + +export type AuthorizationCode = { + code: string; + sessionId: string; + expiresAt: Date; + used: boolean; +}; + +export type AccessToken = { + tokenId: string; + sessionId: string; + expiresAt: Date; +}; + +/** + * This class provides database operations for OpenID Connect (OIDC) authentication flows. + * It manages OIDC clients, authorization codes, and access tokens in the database. + */ +export class OidcDatabase { + private constructor(private readonly db: Knex) {} + + static async create(options: { database: AuthDatabase }) { + const client = await options.database.get(); + return new OidcDatabase(client); + } + + async createClient(client: Client) { + await this.db('oidc_clients').insert({ + client_id: client.clientId, + client_secret: client.clientSecret, + client_name: client.clientName, + response_types: JSON.stringify(client.responseTypes), + grant_types: JSON.stringify(client.grantTypes), + redirect_uris: JSON.stringify(client.redirectUris), + scope: client.scope, + metadata: JSON.stringify(client.metadata), + }); + + return client; + } + + async getClient({ clientId }: { clientId: string }) { + const client = await this.db('oidc_clients') + .where('client_id', clientId) + .first(); + + if (!client) { + return null; + } + + return this.rowToClient(client) as Client; + } + + async createAuthorizationSession( + session: Omit, + ) { + await this.db( + 'oauth_authorization_sessions', + ).insert({ + id: session.id, + client_id: session.clientId, + user_entity_ref: session.userEntityRef, + redirect_uri: session.redirectUri, + scope: session.scope, + state: session.state, + response_type: session.responseType, + code_challenge: session.codeChallenge, + code_challenge_method: session.codeChallengeMethod, + nonce: session.nonce, + status: 'pending', + expires_at: session.expiresAt, + }); + + return { + ...session, + status: 'pending', + }; + } + + async updateAuthorizationSession( + session: Partial & { id: string }, + ) { + const row = this.authorizationSessionToRow(session); + const updatedFields = Object.fromEntries( + Object.entries(row).filter(([_, value]) => value !== undefined), + ); + + // MySQL and SQLite3 don't support RETURNING + if ( + this.db.client.config.client.includes('sqlite3') || + this.db.client.config.client.includes('mysql') + ) { + return await this.db.transaction(async trx => { + await trx('oauth_authorization_sessions') + .where('id', session.id) + .update(updatedFields); + + const updated = await trx( + 'oauth_authorization_sessions', + ) + .where('id', session.id) + .first(); + + if (!updated) { + throw new Error( + `Failed to retrieve updated authorization session with id ${session.id}`, + ); + } + + return this.rowToAuthorizationSession(updated) as AuthorizationSession; + }); + } + + const returnedRows = await this.db( + 'oauth_authorization_sessions', + ) + .where('id', session.id) + .update(updatedFields) + .returning('*'); + + if (returnedRows.length !== 1) { + throw new Error( + `Failed to retrieve updated authorization session with id ${session.id}`, + ); + } + + const [returnedSession] = returnedRows; + + return this.rowToAuthorizationSession( + returnedSession, + ) as AuthorizationSession; + } + + async getAuthorizationSession({ id }: { id: string }) { + const session = await this.db( + 'oauth_authorization_sessions', + ) + .where('id', id) + .first(); + + if (!session) { + return null; + } + + return this.rowToAuthorizationSession(session) as AuthorizationSession; + } + + async createAuthorizationCode( + authorizationCode: Omit, + ) { + await this.db('oidc_authorization_codes').insert({ + code: authorizationCode.code, + session_id: authorizationCode.sessionId, + expires_at: authorizationCode.expiresAt, + used: false, + }); + + return { + ...authorizationCode, + used: false, + }; + } + + async getAuthorizationCode({ code }: { code: string }) { + const authCode = await this.db( + 'oidc_authorization_codes', + ) + .where('code', code) + .first(); + + if (!authCode) { + return null; + } + + return this.rowToAuthorizationCode(authCode) as AuthorizationCode; + } + + async updateAuthorizationCode( + authorizationCode: Partial & { code: string }, + ) { + const row = this.authorizationCodeToRow(authorizationCode); + const updatedFields = Object.fromEntries( + Object.entries(row).filter(([_, value]) => value !== undefined), + ); + + // MySQL and SQLite3 don't support RETURNING + if ( + this.db.client.config.client.includes('sqlite3') || + this.db.client.config.client.includes('mysql') + ) { + return await this.db.transaction(async trx => { + await trx('oidc_authorization_codes') + .where('code', authorizationCode.code) + .update(updatedFields); + + const updated = await trx( + 'oidc_authorization_codes', + ) + .where('code', authorizationCode.code) + .first(); + + if (!updated) { + throw new Error( + `Failed to retrieve updated authorization code with code ${authorizationCode.code}`, + ); + } + + return this.rowToAuthorizationCode(updated) as AuthorizationCode; + }); + } + + const returnedRows = await this.db( + 'oidc_authorization_codes', + ) + .where('code', authorizationCode.code) + .update(updatedFields) + .returning('*'); + + if (returnedRows.length !== 1) { + throw new Error( + `Failed to retrieve updated authorization code with code ${authorizationCode.code}`, + ); + } + + const [returnedCode] = returnedRows; + + return this.rowToAuthorizationCode(returnedCode) as AuthorizationCode; + } + + private rowToClient(row: OidcClientRow): Client { + return { + clientId: row.client_id, + clientName: row.client_name, + clientSecret: row.client_secret, + redirectUris: row.redirect_uris + ? JSON.parse(row.redirect_uris) + : undefined, + responseTypes: row.response_types + ? JSON.parse(row.response_types) + : undefined, + grantTypes: row.grant_types ? JSON.parse(row.grant_types) : undefined, + scope: row.scope ?? undefined, + metadata: row.metadata ? JSON.parse(row.metadata) : undefined, + }; + } + + private authorizationSessionToRow( + session: Partial, + ): Partial { + return { + id: session.id, + client_id: session.clientId, + user_entity_ref: session.userEntityRef, + redirect_uri: session.redirectUri, + scope: session.scope, + state: session.state, + response_type: session.responseType, + code_challenge: session.codeChallenge, + code_challenge_method: session.codeChallengeMethod, + nonce: session.nonce, + status: session.status, + expires_at: toDate(session.expiresAt), + }; + } + + private rowToAuthorizationSession( + row: OAuthAuthorizationSessionRow, + ): Partial { + return { + id: row.id, + clientId: row.client_id, + userEntityRef: row.user_entity_ref ?? undefined, + redirectUri: row.redirect_uri, + scope: row.scope ?? undefined, + state: row.state ?? undefined, + responseType: row.response_type, + codeChallenge: row.code_challenge ?? undefined, + codeChallengeMethod: row.code_challenge_method ?? undefined, + nonce: row.nonce ?? undefined, + status: row.status, + expiresAt: toDate(row.expires_at), + }; + } + + private authorizationCodeToRow( + authorizationCode: Partial, + ): Partial { + return { + code: authorizationCode.code, + session_id: authorizationCode.sessionId, + expires_at: toDate(authorizationCode.expiresAt), + used: authorizationCode.used, + }; + } + + private rowToAuthorizationCode( + row: OidcAuthorizationCodeRow, + ): Partial { + return { + code: row.code, + sessionId: row.session_id, + expiresAt: toDate(row.expires_at), + used: Boolean(row.used), + }; + } +} diff --git a/plugins/auth-backend/src/migrations.test.ts b/plugins/auth-backend/src/migrations.test.ts index f9575c70fd..df7063351a 100644 --- a/plugins/auth-backend/src/migrations.test.ts +++ b/plugins/auth-backend/src/migrations.test.ts @@ -186,4 +186,122 @@ describe('migrations', () => { await knex.destroy(); }, ); + + it.each(databases.eachSupportedId())( + '20250909120000_oidc_client_registration.js, %p', + async databaseId => { + const knex = await databases.init(databaseId); + + await migrateUntilBefore( + knex, + '20250909120000_oidc_client_registration.js', + ); + await migrateUpOnce(knex); + + await knex + .insert({ + client_id: 'test-client-id', + client_secret: 'test-client-secret', + client_name: 'Test Client', + response_types: JSON.stringify(['code']), + grant_types: JSON.stringify(['authorization_code']), + redirect_uris: JSON.stringify(['https://example.com/callback']), + scope: 'openid profile', + metadata: JSON.stringify({ description: 'Test client' }), + }) + .into('oidc_clients'); + + await expect( + knex('oidc_clients').where('client_id', 'test-client-id').first(), + ).resolves.toEqual({ + client_id: 'test-client-id', + client_secret: 'test-client-secret', + client_name: 'Test Client', + response_types: JSON.stringify(['code']), + grant_types: JSON.stringify(['authorization_code']), + redirect_uris: JSON.stringify(['https://example.com/callback']), + scope: 'openid profile', + metadata: JSON.stringify({ description: 'Test client' }), + }); + + await knex + .insert({ + id: 'test-session-id', + client_id: 'test-client-id', + user_entity_ref: 'user:default/test-user', + redirect_uri: 'https://example.com/callback', + scope: 'openid', + state: 'test-state', + response_type: 'code', + code_challenge: 'test-challenge', + code_challenge_method: 'S256', + nonce: 'test-nonce', + status: 'pending', + expires_at: new Date(Date.now() + 3600000), + }) + .into('oauth_authorization_sessions'); + + await expect( + knex('oauth_authorization_sessions') + .where('id', 'test-session-id') + .first(), + ).resolves.toEqual( + expect.objectContaining({ + id: 'test-session-id', + client_id: 'test-client-id', + user_entity_ref: 'user:default/test-user', + redirect_uri: 'https://example.com/callback', + scope: 'openid', + state: 'test-state', + response_type: 'code', + code_challenge: 'test-challenge', + code_challenge_method: 'S256', + nonce: 'test-nonce', + status: 'pending', + }), + ); + + await knex + .insert({ + code: 'test-auth-code', + session_id: 'test-session-id', + expires_at: new Date(Date.now() + 600000), + used: false, + }) + .into('oidc_authorization_codes'); + + await expect( + knex('oidc_authorization_codes') + .where('code', 'test-auth-code') + .first(), + ).resolves.toEqual( + expect.objectContaining({ + code: 'test-auth-code', + session_id: 'test-session-id', + }), + ); + + await knex('oauth_authorization_sessions') + .where('id', 'test-session-id') + .del(); + + await expect( + knex('oidc_authorization_codes').where('session_id', 'test-session-id'), + ).resolves.toHaveLength(0); + + await migrateDownOnce(knex); + + const tables = [ + 'oidc_clients', + 'oauth_authorization_sessions', + 'oidc_authorization_codes', + ]; + + for (const table of tables) { + await expect(knex.schema.hasTable(table)).resolves.toBe(false); + } + + await knex.destroy(); + }, + ); }); diff --git a/plugins/auth-backend/src/service/OidcRouter.test.ts b/plugins/auth-backend/src/service/OidcRouter.test.ts index dbc6c88f93..de865a9c43 100644 --- a/plugins/auth-backend/src/service/OidcRouter.test.ts +++ b/plugins/auth-backend/src/service/OidcRouter.test.ts @@ -17,135 +17,794 @@ import { coreServices, createBackendPlugin, + resolvePackagePath, } from '@backstage/backend-plugin-api'; -import { mockServices, startTestBackend } from '@backstage/backend-test-utils'; -import Router from 'express-promise-router'; +import { + mockServices, + startTestBackend, + TestDatabases, + TestDatabaseId, + mockCredentials, +} from '@backstage/backend-test-utils'; import request from 'supertest'; +import crypto from 'crypto'; import { OidcRouter } from './OidcRouter'; import { UserInfoDatabase } from '../database/UserInfoDatabase'; +import { OidcDatabase } from '../database/OidcDatabase'; +import { AuthDatabase } from '../database/AuthDatabase'; +import { OidcService } from '../service/OidcService'; +import { TokenIssuer } from '../identity/types'; + +jest.setTimeout(60_000); describe('OidcRouter', () => { - describe('/v1/userinfo', () => { - it('should return user info for full tokens', async () => { - const auth = mockServices.auth.mock(); - const mockUserInfo = { - getUserInfo: jest.fn().mockResolvedValue({ - claims: { - sub: 'k/ns:n', - ent: ['k/ns:a', 'k/ns:b'], - }, - }), - } as unknown as UserInfoDatabase; + const MOCK_USER_TOKEN = 'mock-user-token'; + const MOCK_USER_ENTITY_REF = 'user:default/test-user'; + const databases = TestDatabases.create(); - const { server } = await startTestBackend({ - features: [ - createBackendPlugin({ - pluginId: 'auth', - register(reg) { - reg.registerInit({ - deps: { httpRouter: coreServices.httpRouter }, - async init({ httpRouter }) { - const router = Router(); + async function createRouter(databaseId: TestDatabaseId) { + const knex = await databases.init(databaseId); - router.use( - OidcRouter.create({ - auth, - tokenIssuer: {} as any, - baseUrl: 'http://localhost:7000', - userInfo: mockUserInfo, - }).getRouter(), - ); - httpRouter.use(router); - httpRouter.addAuthPolicy({ - path: '/', - allow: 'unauthenticated', - }); - }, - }); - }, - }), - ], - }); - - auth.authenticate.mockResolvedValueOnce({} as any); - auth.isPrincipal.mockReturnValueOnce(true); - - await request(server) - .get('/api/auth/v1/userinfo') - .set( - 'Authorization', - `Bearer h.${btoa( - JSON.stringify({ sub: 'k/ns:n', ent: ['k/ns:a', 'k/ns:b'] }), - )}.s`, - ) - .expect(200, { - claims: { - sub: 'k/ns:n', - ent: ['k/ns:a', 'k/ns:b'], - }, - }); - - expect(mockUserInfo.getUserInfo).toHaveBeenCalledWith('k/ns:n'); + await knex.migrate.latest({ + directory: resolvePackagePath( + '@backstage/plugin-auth-backend', + 'migrations', + ), }); - it('should return user info for limited tokens', async () => { - const auth = mockServices.auth.mock(); - const mockUserInfo = { - getUserInfo: jest.fn().mockResolvedValue({ - claims: { - sub: 'k/ns:n', - ent: ['k/ns:a', 'k/ns:b'], + const authDatabase = AuthDatabase.create({ + getClient: async () => knex, + }); + + const oidcDatabase = await OidcDatabase.create({ + database: authDatabase, + }); + + const userInfoDatabase = await UserInfoDatabase.create({ + database: authDatabase, + }); + + const mockTokenIssuer = { + issueToken: jest.fn(), + listPublicKeys: jest.fn(), + } as unknown as jest.Mocked; + + const mockAuth = mockServices.auth.mock(); + const mockHttpAuth = mockServices.httpAuth.mock(); + const mockConfig = mockServices.rootConfig({ + data: { + auth: { + experimentalDynamicClientRegistration: { + enabled: true, }, - }), - } as unknown as UserInfoDatabase; + }, + }, + }); - const { server } = await startTestBackend({ - features: [ - createBackendPlugin({ - pluginId: 'auth', - register(reg) { - reg.registerInit({ - deps: { httpRouter: coreServices.httpRouter }, - async init({ httpRouter }) { - const router = Router(); + const oidcService = OidcService.create({ + auth: mockAuth, + tokenIssuer: mockTokenIssuer, + baseUrl: 'http://localhost:7000', + userInfo: userInfoDatabase, + oidc: oidcDatabase, + config: mockConfig, + }); - router.use( - OidcRouter.create({ - auth, - tokenIssuer: {} as any, - baseUrl: 'http://localhost:7000', - userInfo: mockUserInfo, - }).getRouter(), - ); - httpRouter.use(router); - httpRouter.addAuthPolicy({ - path: '/', - allow: 'unauthenticated', - }); - }, - }); - }, - }), - ], - }); + const oidcRouter = OidcRouter.create({ + auth: mockAuth, + tokenIssuer: mockTokenIssuer, + baseUrl: 'http://localhost:7000', + appUrl: 'http://localhost:3000', + logger: mockServices.logger.mock(), + userInfo: userInfoDatabase, + oidc: oidcDatabase, + httpAuth: mockHttpAuth, + config: mockConfig, + }); - auth.authenticate.mockResolvedValueOnce({} as any); - auth.isPrincipal.mockReturnValueOnce(true); + return { + router: oidcRouter, + mocks: { + httpAuth: mockHttpAuth, + auth: mockAuth, + oidc: oidcDatabase, + userInfo: userInfoDatabase, + service: oidcService, + tokenIssuer: mockTokenIssuer, + }, + }; + } - await request(server) - .get('/api/auth/v1/userinfo') - .set( - 'Authorization', - `Bearer h.${btoa(JSON.stringify({ sub: 'k/ns:n' }))}.s`, - ) - .expect(200, { + describe.each(databases.eachSupportedId())('%p', databaseId => { + describe('/v1/userinfo', () => { + it('should return user info for full tokens', async () => { + const { + mocks: { auth, userInfo }, + router, + } = await createRouter(databaseId); + + await userInfo.addUserInfo({ claims: { sub: 'k/ns:n', ent: ['k/ns:a', 'k/ns:b'], + exp: Math.floor(Date.now() / 1000) + 3600, }, }); - expect(mockUserInfo.getUserInfo).toHaveBeenCalledWith('k/ns:n'); + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + auth.isPrincipal.mockReturnValueOnce(true); + + const response = await request(server) + .get('/api/auth/v1/userinfo') + .set( + 'Authorization', + `Bearer h.${btoa( + JSON.stringify({ sub: 'k/ns:n', ent: ['k/ns:a', 'k/ns:b'] }), + )}.s`, + ) + .expect(200); + + expect(response.body).toEqual({ + claims: { + sub: 'k/ns:n', + ent: ['k/ns:a', 'k/ns:b'], + exp: expect.any(Number), + }, + }); + }); + + it('should return user info for limited tokens', async () => { + const { + mocks: { auth, userInfo }, + router, + } = await createRouter(databaseId); + + await userInfo.addUserInfo({ + claims: { + sub: 'k/ns:n', + ent: ['k/ns:a', 'k/ns:b'], + exp: Math.floor(Date.now() / 1000) + 3600, + }, + }); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + auth.isPrincipal.mockReturnValueOnce(true); + + const response = await request(server) + .get('/api/auth/v1/userinfo') + .set( + 'Authorization', + `Bearer h.${btoa(JSON.stringify({ sub: 'k/ns:n' }))}.s`, + ) + .expect(200); + + expect(response.body).toEqual({ + claims: { + sub: 'k/ns:n', + ent: ['k/ns:a', 'k/ns:b'], + exp: expect.any(Number), + }, + }); + }); + }); + + describe('auth flow', () => { + it('should register a client', async () => { + const { router } = await createRouter(databaseId); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + const response = await request(server) + .post('/api/auth/v1/register') + .send({ + client_name: 'Test Client', + redirect_uris: ['https://example.com/callback'], + response_types: ['code'], + grant_types: ['authorization_code'], + scope: 'openid', + }) + .expect(201); + + expect(response.body).toEqual({ + client_id: expect.any(String), + client_secret: expect.any(String), + redirect_uris: ['https://example.com/callback'], + }); + }); + + it('should create an authorization session via authorization endpoint', async () => { + const { + mocks: { service }, + router, + } = await createRouter(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + const response = await request(server) + .get('/api/auth/v1/authorize') + .query({ + client_id: client.clientId, + redirect_uri: 'https://example.com/callback', + response_type: 'code', + scope: 'openid', + state: 'test-state', + }) + .expect(302); + + expect(response.header.location).toMatch( + /^http:\/\/localhost:3000\/oauth2\/authorize\/[a-f0-9-]+$/, + ); + }); + + it('should get auth session details', async () => { + const { + mocks: { service }, + router, + } = await createRouter(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + }); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + const response = await request(server) + .get(`/api/auth/v1/sessions/${authSession.id}`) + .expect(200); + + expect(response.body).toEqual({ + id: authSession.id, + clientName: 'Test Client', + scope: 'openid', + redirectUri: 'https://example.com/callback', + }); + }); + + it('should approve authorization session', async () => { + const { + mocks: { auth, service, httpAuth }, + router, + } = await createRouter(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + }); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + httpAuth.credentials.mockResolvedValueOnce( + mockCredentials.user('user:default/test-user'), + ); + + auth.isPrincipal.mockReturnValueOnce(true); + + const response = await request(server) + .post(`/api/auth/v1/sessions/${authSession.id}/approve`) + .set('Authorization', `Bearer ${MOCK_USER_TOKEN}`) + .expect(200); + + expect(response.body).toEqual({ + redirectUrl: expect.stringMatching( + /^https:\/\/example\.com\/callback\?code=[\w-]+&state=test-state$/, + ), + }); + }); + + it('should reject auth session', async () => { + const { + mocks: { service, httpAuth, auth }, + router, + } = await createRouter(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + }); + + httpAuth.credentials.mockResolvedValueOnce( + mockCredentials.user('user:default/test-user'), + ); + + auth.isPrincipal.mockReturnValueOnce(true); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + const response = await request(server) + .post(`/api/auth/v1/sessions/${authSession.id}/reject`) + .expect(200); + + expect(response.body).toEqual({ + redirectUrl: expect.stringMatching( + /^https:\/\/example\.com\/callback\?error=access_denied&error_description=User\+denied\+the\+request&state=test-state$/, + ), + }); + }); + }); + + describe('token exchange', () => { + it('should exchange authorization code for tokens', async () => { + const { + mocks: { auth, service, tokenIssuer, httpAuth }, + router, + } = await createRouter(databaseId); + + httpAuth.credentials.mockResolvedValueOnce( + mockCredentials.user('user:default/test-user'), + ); + + auth.isPrincipal.mockReturnValueOnce(true); + + tokenIssuer.issueToken.mockResolvedValue({ + token: 'mock-access-token', + }); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + }); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + const approvalResponse = await request(server) + .post(`/api/auth/v1/sessions/${authSession.id}/approve`) + .set('Authorization', `Bearer ${MOCK_USER_TOKEN}`) + .expect(200); + + const redirectUrl = new URL(approvalResponse.body.redirectUrl); + const authorizationCode = redirectUrl.searchParams.get('code'); + + expect(authorizationCode).toBeDefined(); + + const tokenResponse = await request(server) + .post('/api/auth/v1/token') + .send({ + grant_type: 'authorization_code', + code: authorizationCode, + redirect_uri: 'https://example.com/callback', + }) + .expect(200); + + expect(tokenResponse.body).toEqual({ + access_token: 'mock-access-token', + token_type: 'Bearer', + expires_in: 3600, + id_token: 'mock-access-token', + scope: 'openid', + }); + + expect(tokenIssuer.issueToken).toHaveBeenCalledWith({ + claims: { + sub: MOCK_USER_ENTITY_REF, + }, + }); + }); + + it('should exchange authorization code for tokens with PKCE', async () => { + const { + mocks: { auth, service, tokenIssuer, httpAuth }, + router, + } = await createRouter(databaseId); + + tokenIssuer.issueToken.mockResolvedValue({ + token: 'mock-access-token-pkce', + }); + + httpAuth.credentials.mockResolvedValueOnce( + mockCredentials.user('user:default/test-user-pkce'), + ); + + auth.isPrincipal.mockReturnValueOnce(true); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }); + + const codeVerifier = + 'test-code-verifier-123456789012345678901234567890123456789012345'; + const codeChallenge = codeVerifier; + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + codeChallenge, + codeChallengeMethod: 'plain', + }); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + const approvalResponse = await request(server) + .post(`/api/auth/v1/sessions/${authSession.id}/approve`) + .set('Authorization', `Bearer ${MOCK_USER_TOKEN}`) + .expect(200); + + const redirectUrl = new URL(approvalResponse.body.redirectUrl); + const authorizationCode = redirectUrl.searchParams.get('code'); + + expect(authorizationCode).toBeDefined(); + + const tokenResponse = await request(server) + .post('/api/auth/v1/token') + .send({ + grant_type: 'authorization_code', + code: authorizationCode, + redirect_uri: 'https://example.com/callback', + code_verifier: codeVerifier, + }) + .expect(200); + + expect(tokenResponse.body).toEqual({ + access_token: 'mock-access-token-pkce', + token_type: 'Bearer', + expires_in: 3600, + id_token: 'mock-access-token-pkce', + scope: 'openid', + }); + + expect(tokenIssuer.issueToken).toHaveBeenCalledWith({ + claims: { + sub: 'user:default/test-user-pkce', + }, + }); + }); + + it('should reject token exchange with invalid authorization code', async () => { + const { router } = await createRouter(databaseId); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + const tokenResponse = await request(server) + .post('/api/auth/v1/token') + .send({ + grant_type: 'authorization_code', + code: 'invalid-code', + redirect_uri: 'https://example.com/callback', + }) + .expect(401); + + expect(tokenResponse.body).toEqual({ + error: 'invalid_client', + error_description: 'Invalid authorization code', + }); + }); + + it('should exchange authorization code for tokens with PKCE S256', async () => { + const { + mocks: { auth, service, tokenIssuer, httpAuth }, + router, + } = await createRouter(databaseId); + + tokenIssuer.issueToken.mockResolvedValue({ + token: 'mock-access-token-s256', + }); + + httpAuth.credentials.mockResolvedValueOnce( + mockCredentials.user('user:default/test-user-s256'), + ); + + auth.isPrincipal.mockReturnValueOnce(true); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }); + + const codeVerifier = + 'test-code-verifier-s256-123456789012345678901234567890123456789'; + const codeChallenge = crypto + .createHash('sha256') + .update(codeVerifier) + .digest('base64url'); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + codeChallenge, + codeChallengeMethod: 'S256', + }); + + const { server } = await startTestBackend({ + features: [ + createBackendPlugin({ + pluginId: 'auth', + register(reg) { + reg.registerInit({ + deps: { httpRouter: coreServices.httpRouter }, + async init({ httpRouter }) { + httpRouter.use(router.getRouter()); + httpRouter.addAuthPolicy({ + path: '/', + allow: 'unauthenticated', + }); + }, + }); + }, + }), + ], + }); + + const approvalResponse = await request(server) + .post(`/api/auth/v1/sessions/${authSession.id}/approve`) + .set('Authorization', `Bearer ${MOCK_USER_TOKEN}`) + .expect(200); + + const redirectUrl = new URL(approvalResponse.body.redirectUrl); + const authorizationCode = redirectUrl.searchParams.get('code'); + + expect(authorizationCode).toBeDefined(); + + const tokenResponse = await request(server) + .post('/api/auth/v1/token') + .send({ + grant_type: 'authorization_code', + code: authorizationCode, + redirect_uri: 'https://example.com/callback', + code_verifier: codeVerifier, + }) + .expect(200); + + expect(tokenResponse.body).toEqual({ + access_token: 'mock-access-token-s256', + token_type: 'Bearer', + expires_in: 3600, + id_token: 'mock-access-token-s256', + scope: 'openid', + }); + + expect(tokenIssuer.issueToken).toHaveBeenCalledWith({ + claims: { + sub: 'user:default/test-user-s256', + }, + }); + }); }); }); }); diff --git a/plugins/auth-backend/src/service/OidcRouter.ts b/plugins/auth-backend/src/service/OidcRouter.ts index 6ada071c44..9a3308b4eb 100644 --- a/plugins/auth-backend/src/service/OidcRouter.ts +++ b/plugins/auth-backend/src/service/OidcRouter.ts @@ -15,42 +15,72 @@ */ import Router from 'express-promise-router'; import { OidcService } from './OidcService'; -import { AuthenticationError } from '@backstage/errors'; -import { AuthService } from '@backstage/backend-plugin-api'; +import { AuthenticationError, isError } from '@backstage/errors'; +import { + AuthService, + HttpAuthService, + LoggerService, + RootConfigService, +} from '@backstage/backend-plugin-api'; import { TokenIssuer } from '../identity/types'; import { UserInfoDatabase } from '../database/UserInfoDatabase'; +import { OidcDatabase } from '../database/OidcDatabase'; +import { json } from 'express'; export class OidcRouter { - private constructor(private readonly oidc: OidcService) {} + private constructor( + private readonly oidc: OidcService, + private readonly logger: LoggerService, + private readonly auth: AuthService, + private readonly appUrl: string, + private readonly httpAuth: HttpAuthService, + private readonly config: RootConfigService, + ) {} static create(options: { auth: AuthService; tokenIssuer: TokenIssuer; baseUrl: string; + appUrl: string; + logger: LoggerService; userInfo: UserInfoDatabase; + oidc: OidcDatabase; + httpAuth: HttpAuthService; + config: RootConfigService; }) { - return new OidcRouter(OidcService.create(options)); + return new OidcRouter( + OidcService.create(options), + options.logger, + options.auth, + options.appUrl, + options.httpAuth, + options.config, + ); } public getRouter() { const router = Router(); + router.use(json()); + + // OpenID Provider Configuration endpoint + // https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig + // Returns the OpenID Provider Configuration document containing metadata about the provider router.get('/.well-known/openid-configuration', (_req, res) => { res.json(this.oidc.getConfiguration()); }); + // JSON Web Key Set endpoint + // https://openid.net/specs/openid-connect-core-1_0.html#rfc.section.10.1.1 + // Returns the public keys used to verify JWTs issued by this provider router.get('/.well-known/jwks.json', async (_req, res) => { const { keys } = await this.oidc.listPublicKeys(); res.json({ keys }); }); - router.get('/v1/token', (_req, res) => { - res.status(501).send('Not Implemented'); - }); - - // This endpoint doesn't use the regular HttpAuthoidc, since the contract - // is specifically for the header to be communicated in the Authorization - // header, regardless of token type + // UserInfo endpoint + // https://openid.net/specs/openid-connect-core-1_0.html#UserInfo + // Returns claims about the authenticated user using an access token router.get('/v1/userinfo', async (req, res) => { const matches = req.headers.authorization?.match(/^Bearer[ ]+(\S+)$/i); const token = matches?.[1]; @@ -68,6 +98,337 @@ export class OidcRouter { res.json(userInfo); }); + if ( + this.config.getOptionalBoolean( + 'auth.experimentalDynamicClientRegistration.enabled', + ) + ) { + // Authorization endpoint + // https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest + // Handles the initial authorization request from the client, validates parameters, + // and redirects to the Authorization Session page for user approval + router.get('/v1/authorize', async (req, res) => { + // todo(blam): maybe add zod types for validating input + const { + client_id: clientId, + redirect_uri: redirectUri, + response_type: responseType, + scope, + state, + nonce, + code_challenge: codeChallenge, + code_challenge_method: codeChallengeMethod, + } = req.query; + + if (!clientId || !redirectUri || !responseType) { + this.logger.error(`Failed to authorize: Missing required parameters`); + return res.status(400).json({ + error: 'invalid_request', + error_description: + 'Missing required parameters: client_id, redirect_uri, response_type', + }); + } + + try { + const result = await this.oidc.createAuthorizationSession({ + clientId: clientId as string, + redirectUri: redirectUri as string, + responseType: responseType as string, + scope: scope as string | undefined, + state: state as string | undefined, + nonce: nonce as string | undefined, + codeChallenge: codeChallenge as string | undefined, + codeChallengeMethod: codeChallengeMethod as string | undefined, + }); + + // todo(blam): maybe this URL could be overridable by config if + // the plugin is mounted somewhere else? + // support slashes in baseUrl? + const authSessionRedirectUrl = new URL( + `./oauth2/authorize/${result.id}`, + ensureTrailingSlash(this.appUrl), + ); + + return res.redirect(authSessionRedirectUrl.toString()); + } catch (error) { + const errorParams = new URLSearchParams(); + errorParams.append( + 'error', + isError(error) ? error.name : 'server_error', + ); + errorParams.append( + 'error_description', + isError(error) ? error.message : 'Unknown error', + ); + if (state) { + errorParams.append('state', state as string); + } + + const redirectUrl = new URL(redirectUri as string); + redirectUrl.search = errorParams.toString(); + return res.redirect(redirectUrl.toString()); + } + }); + + // Authorization Session request details endpoint + // Returns Authorization Session request details for the frontend + router.get('/v1/sessions/:sessionId', async (req, res) => { + const { sessionId } = req.params; + + if (!sessionId) { + return res.status(400).json({ + error: 'invalid_request', + error_description: 'Missing Authorization Session ID', + }); + } + + try { + const session = await this.oidc.getAuthorizationSession({ + sessionId, + }); + + return res.json({ + id: session.id, + clientName: session.clientName, + scope: session.scope, + redirectUri: session.redirectUri, + }); + } catch (error) { + const description = isError(error) ? error.message : 'Unknown error'; + this.logger.error( + `Failed to get authorization session: ${description}`, + error, + ); + return res.status(404).json({ + error: 'not_found', + error_description: description, + }); + } + }); + + // Authorization Session approval endpoint + // Handles user approval of Authorization Session requests and generates authorization codes + router.post('/v1/sessions/:sessionId/approve', async (req, res) => { + const { sessionId } = req.params; + + if (!sessionId) { + return res.status(400).json({ + error: 'invalid_request', + error_description: 'Missing authorization session ID', + }); + } + + try { + const httpCredentials = await this.httpAuth.credentials(req); + + if (!this.auth.isPrincipal(httpCredentials, 'user')) { + return res.status(401).json({ + error: 'unauthorized', + error_description: 'Authentication required', + }); + } + + const { userEntityRef } = httpCredentials.principal; + + const result = await this.oidc.approveAuthorizationSession({ + sessionId, + userEntityRef, + }); + + return res.json({ + redirectUrl: result.redirectUrl, + }); + } catch (error) { + const description = isError(error) ? error.message : 'Unknown error'; + this.logger.error( + `Failed to approve authorization session: ${description}`, + error, + ); + return res.status(400).json({ + error: 'invalid_request', + error_description: description, + }); + } + }); + + // Authorization Session rejection endpoint + // Handles user rejection of Authorization Session requests and redirects with error + router.post('/v1/sessions/:sessionId/reject', async (req, res) => { + const { sessionId } = req.params; + + if (!sessionId) { + return res.status(400).json({ + error: 'invalid_request', + error_description: 'Missing authorization session ID', + }); + } + + const httpCredentials = await this.httpAuth.credentials(req); + + if (!this.auth.isPrincipal(httpCredentials, 'user')) { + return res.status(401).json({ + error: 'unauthorized', + error_description: 'Authentication required', + }); + } + + const { userEntityRef } = httpCredentials.principal; + try { + const session = await this.oidc.getAuthorizationSession({ + sessionId, + }); + + await this.oidc.rejectAuthorizationSession({ + sessionId, + userEntityRef, + }); + + const errorParams = new URLSearchParams(); + errorParams.append('error', 'access_denied'); + errorParams.append('error_description', 'User denied the request'); + if (session.state) { + errorParams.append('state', session.state); + } + + const redirectUrl = new URL(session.redirectUri); + redirectUrl.search = errorParams.toString(); + + return res.json({ + redirectUrl: redirectUrl.toString(), + }); + } catch (error) { + const description = isError(error) ? error.message : 'Unknown error'; + this.logger.error( + `Failed to reject authorization session: ${description}`, + error, + ); + + return res.status(400).json({ + error: 'invalid_request', + error_description: description, + }); + } + }); + + // Token endpoint + // https://openid.net/specs/openid-connect-core-1_0.html#TokenRequest + // Exchanges authorization codes for access tokens and ID tokens + router.post('/v1/token', async (req, res) => { + // todo(blam): maybe add zod types for validating input + const { + grant_type: grantType, + code, + redirect_uri: redirectUri, + code_verifier: codeVerifier, + } = req.body; + + if (!grantType || !code || !redirectUri) { + this.logger.error( + `Failed to exchange code for token: Missing required parameters`, + ); + return res.status(400).json({ + error: 'invalid_request', + error_description: 'Missing required parameters', + }); + } + + try { + const result = await this.oidc.exchangeCodeForToken({ + code, + redirectUri, + codeVerifier, + grantType, + }); + + return res.json({ + access_token: result.accessToken, + token_type: result.tokenType, + expires_in: result.expiresIn, + id_token: result.idToken, + scope: result.scope, + }); + } catch (error) { + const description = isError(error) ? error.message : 'Unknown error'; + this.logger.error( + `Failed to exchange code for token: ${description}`, + error, + ); + + if (isError(error)) { + if (error.name === 'AuthenticationError') { + return res.status(401).json({ + error: 'invalid_client', + error_description: error.message, + }); + } + if (error.name === 'InputError') { + return res.status(400).json({ + error: 'invalid_request', + error_description: error.message, + }); + } + } + + return res.status(500).json({ + error: 'server_error', + error_description: description, + }); + } + }); + + // Dynamic Client Registration endpoint + // https://openid.net/specs/openid-connect-registration-1_0.html#ClientRegistration + // Allows clients to register themselves dynamically with the provider + router.post('/v1/register', async (req, res) => { + // todo(blam): maybe add zod types for validating input + const { + client_name: clientName, + redirect_uris: redirectUris, + response_types: responseTypes, + grant_types: grantTypes, + scope, + } = req.body; + + if (!redirectUris?.length) { + res.status(400).json({ + error: 'invalid_request', + error_description: 'redirect_uris is required', + }); + return; + } + + try { + const client = await this.oidc.registerClient({ + clientName, + redirectUris, + responseTypes, + grantTypes, + scope, + }); + + res.status(201).json({ + client_id: client.clientId, + redirect_uris: client.redirectUris, + client_secret: client.clientSecret, + }); + } catch (e) { + const description = isError(e) ? e.message : 'Unknown error'; + this.logger.error(`Failed to register client: ${description}`, e); + + res.status(500).json({ + error: 'server_error', + error_description: `Failed to register client: ${description}`, + }); + } + }); + } + return router; } } +function ensureTrailingSlash(appUrl: string): string | URL | undefined { + if (appUrl.endsWith('/')) { + return appUrl; + } + return `${appUrl}/`; +} diff --git a/plugins/auth-backend/src/service/OidcService.test.ts b/plugins/auth-backend/src/service/OidcService.test.ts new file mode 100644 index 0000000000..e4e1673397 --- /dev/null +++ b/plugins/auth-backend/src/service/OidcService.test.ts @@ -0,0 +1,789 @@ +/* + * 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, + TestDatabaseId, + TestDatabases, +} from '@backstage/backend-test-utils'; +import { OidcService } from './OidcService'; +import { + BackstageCredentials, + BackstageServicePrincipal, + BackstageUserPrincipal, + resolvePackagePath, +} from '@backstage/backend-plugin-api'; +import { AuthDatabase } from '../database/AuthDatabase'; +import { OidcDatabase } from '../database/OidcDatabase'; +import { UserInfoDatabase } from '../database/UserInfoDatabase'; +import crypto from 'crypto'; +import { AnyJWK, TokenIssuer } from '../identity/types'; + +jest.setTimeout(60_000); + +describe('OidcService', () => { + const databases = TestDatabases.create(); + + async function createOidcService(databaseId: TestDatabaseId) { + const knex = await databases.init(databaseId); + + await knex.migrate.latest({ + directory: resolvePackagePath( + '@backstage/plugin-auth-backend', + 'migrations', + ), + }); + + const oidcDatabase = await OidcDatabase.create({ + database: AuthDatabase.create({ + getClient: async () => knex, + }), + }); + + const mockAuth = mockServices.auth.mock(); + const mockTokenIssuer = { + issueToken: jest.fn(), + listPublicKeys: jest.fn(), + } as jest.Mocked; + + const mockUserInfo = { + addUserInfo: jest.fn(), + getUserInfo: jest.fn(), + } as unknown as jest.Mocked; + + const mockConfig = mockServices.rootConfig.mock(); + + return { + service: OidcService.create({ + auth: mockAuth, + tokenIssuer: mockTokenIssuer, + baseUrl: 'http://mock-base-url', + userInfo: mockUserInfo, + oidc: oidcDatabase, + config: mockConfig, + }), + mocks: { + auth: mockAuth, + tokenIssuer: mockTokenIssuer, + userInfo: mockUserInfo, + config: mockConfig, + }, + }; + } + + describe.each(databases.eachSupportedId())('%p', databaseId => { + describe('getConfiguration', () => { + it('should return OIDC configuration', async () => { + const { service } = await createOidcService(databaseId); + + const config = service.getConfiguration(); + + expect(config).toEqual({ + issuer: 'http://mock-base-url', + token_endpoint: 'http://mock-base-url/v1/token', + userinfo_endpoint: 'http://mock-base-url/v1/userinfo', + jwks_uri: 'http://mock-base-url/.well-known/jwks.json', + response_types_supported: ['code', 'id_token'], + subject_types_supported: ['public'], + id_token_signing_alg_values_supported: [ + 'RS256', + 'RS384', + 'RS512', + 'ES256', + 'ES384', + 'ES512', + 'PS256', + 'PS384', + 'PS512', + 'EdDSA', + ], + scopes_supported: ['openid'], + token_endpoint_auth_methods_supported: [ + 'client_secret_basic', + 'client_secret_post', + ], + claims_supported: ['sub', 'ent'], + grant_types_supported: ['authorization_code'], + authorization_endpoint: 'http://mock-base-url/v1/authorize', + registration_endpoint: 'http://mock-base-url/v1/register', + code_challenge_methods_supported: ['S256', 'plain'], + }); + }); + }); + + describe('listPublicKeys', () => { + it('should return public keys from token issuer', async () => { + const { service, mocks } = await createOidcService(databaseId); + const mockKeys = [{ kid: 'key-1', use: 'sig' }] as AnyJWK[]; + mocks.tokenIssuer.listPublicKeys.mockResolvedValue({ keys: mockKeys }); + + const { keys } = await service.listPublicKeys(); + + expect(keys).toEqual(mockKeys); + expect(mocks.tokenIssuer.listPublicKeys).toHaveBeenCalledTimes(1); + }); + }); + + describe('getUserInfo', () => { + it('should return user info for valid token', async () => { + const { service, mocks } = await createOidcService(databaseId); + const mockCredentials: BackstageCredentials = { + principal: { + type: 'user', + userEntityRef: 'user:default/test', + }, + $$type: '@backstage/BackstageCredentials', + }; + const mockUserInfo = { sub: 'user:default/test', name: 'Test User' }; + + mocks.auth.authenticate.mockResolvedValue(mockCredentials); + mocks.auth.isPrincipal.mockReturnValue(true); + mocks.userInfo.getUserInfo.mockResolvedValue({ + claims: mockUserInfo, + }); + + const mockToken = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyOmRlZmF1bHQvdGVzdCJ9.signature'; + + const userInfo = await service.getUserInfo({ token: mockToken }); + + expect(userInfo).toEqual({ + claims: mockUserInfo, + }); + + expect(mocks.auth.authenticate).toHaveBeenCalledWith(mockToken, { + allowLimitedAccess: true, + }); + + expect(mocks.userInfo.getUserInfo).toHaveBeenCalledWith( + 'user:default/test', + ); + }); + + it('should throw error for non-user principal', async () => { + const { service, mocks } = await createOidcService(databaseId); + const mockCredentials: BackstageCredentials = + { + principal: { + type: 'service', + subject: 'test-service', + }, + $$type: '@backstage/BackstageCredentials', + }; + + mocks.auth.authenticate.mockResolvedValue(mockCredentials); + mocks.auth.isPrincipal.mockReturnValue(false); + + const mockToken = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyOmRlZmF1bHQvdGVzdCJ9.signature'; + + await expect(service.getUserInfo({ token: mockToken })).rejects.toThrow( + 'Userinfo endpoint must be called with a token that represents a user principal', + ); + }); + }); + + describe('registerClient', () => { + it('should create a new client with generated credentials', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }); + + expect(client).toEqual( + expect.objectContaining({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + scope: 'openid', + }), + ); + expect(client.clientId).toBeDefined(); + expect(client.clientSecret).toBeDefined(); + }); + + it('should throw an error for invalid redirect URI', async () => { + const { + service, + mocks: { config }, + } = await createOidcService(databaseId); + + config.getOptionalStringArray.mockReturnValue([ + 'https://example.com/*', + ]); + + await expect( + service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://invalid.com/callback'], + }), + ).rejects.toThrow('Invalid redirect_uri'); + }); + + it('should create a new client with valid redirect URI', async () => { + const { + service, + mocks: { config }, + } = await createOidcService(databaseId); + + config.getOptionalStringArray.mockReturnValue(['cursor:*']); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['cursor://callback/asd?asd=asd'], + }); + + expect(client).toEqual( + expect.objectContaining({ + redirectUris: ['cursor://callback/asd?asd=asd'], + }), + ); + }); + + it('should create a client with default values', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + }); + + expect(client).toEqual( + expect.objectContaining({ + clientName: 'Test Client', + redirectUris: [], + responseTypes: ['code'], + grantTypes: ['authorization_code'], + }), + ); + }); + }); + + describe('createAuthorizationSession', () => { + it('should create a authorization session for valid client', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + }); + + expect(authSession).toEqual({ + id: expect.any(String), + clientName: 'Test Client', + scope: 'openid', + redirectUri: 'https://example.com/callback', + }); + }); + + it('should throw error for invalid client', async () => { + const { service } = await createOidcService(databaseId); + + await expect( + service.createAuthorizationSession({ + clientId: 'invalid-client', + redirectUri: 'https://example.com/callback', + responseType: 'code', + }), + ).rejects.toThrow('Invalid client_id'); + }); + + it('should throw error for invalid redirect URI', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + await expect( + service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://invalid.com/callback', + responseType: 'code', + }), + ).rejects.toThrow('Invalid redirect_uri'); + }); + + it('should throw error for unsupported response type', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + await expect( + service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'token', + }), + ).rejects.toThrow('Only authorization code flow is supported'); + }); + + it('should handle PKCE parameters', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + codeChallenge: 'test-challenge', + codeChallengeMethod: 'S256', + }); + + expect(authSession.id).toBeDefined(); + }); + + it('should throw error for invalid PKCE method', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + await expect( + service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + codeChallenge: 'test-challenge', + codeChallengeMethod: 'invalid', + }), + ).rejects.toThrow('Invalid code_challenge_method'); + }); + }); + + describe('approveAuthorizationSession', () => { + it('should approve a valid authorization session', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + state: 'test-state', + }); + + const result = await service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + expect(result.redirectUrl).toMatch( + /^https:\/\/example\.com\/callback\?code=.+&state=test-state$/, + ); + }); + + it('should throw error for invalid authorization session', async () => { + const { service } = await createOidcService(databaseId); + + await expect( + service.approveAuthorizationSession({ + sessionId: 'invalid-session', + userEntityRef: 'user:default/test', + }), + ).rejects.toThrow('Invalid authorization session'); + }); + + it('should throw error when trying to approve an already approved session', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + }); + + await service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + await expect( + service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }), + ).rejects.toThrow('Authorization session not found or expired'); + }); + + it('should throw error when trying to approve an already rejected session', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + }); + + await service.rejectAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + await expect( + service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }), + ).rejects.toThrow('Authorization session not found or expired'); + }); + }); + + describe('getAuthorizationSession', () => { + it('should return authorization session details', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + state: 'test-state', + }); + + const details = await service.getAuthorizationSession({ + sessionId: authSession.id, + }); + + expect(details).toEqual( + expect.objectContaining({ + id: authSession.id, + clientId: client.clientId, + clientName: 'Test Client', + redirectUri: 'https://example.com/callback', + scope: 'openid', + state: 'test-state', + responseType: 'code', + }), + ); + }); + + it('should throw error when trying to get an already approved session', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + }); + + await service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + await expect( + service.getAuthorizationSession({ + sessionId: authSession.id, + }), + ).rejects.toThrow('Authorization session not found or expired'); + }); + + it('should throw error when trying to get an already rejected session', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + }); + + await service.rejectAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + await expect( + service.getAuthorizationSession({ + sessionId: authSession.id, + }), + ).rejects.toThrow('Authorization session not found or expired'); + }); + }); + + describe('rejectAuthorizationSession', () => { + it('should reject a authorization session', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + }); + + await service.rejectAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + await expect( + service.getAuthorizationSession({ + sessionId: authSession.id, + }), + ).rejects.toThrow('Authorization session not found or expired'); + }); + + it('should throw error for invalid authorization session', async () => { + const { service } = await createOidcService(databaseId); + + await expect( + service.rejectAuthorizationSession({ + sessionId: 'invalid-session', + userEntityRef: 'user:default/test', + }), + ).rejects.toThrow('Invalid authorization session'); + }); + + it('should throw error when trying to reject an already approved session', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + }); + + await service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + await expect( + service.rejectAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }), + ).rejects.toThrow('Authorization session not found or expired'); + }); + + it('should throw error when trying to reject an already rejected session', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + }); + + await service.rejectAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + await expect( + service.rejectAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }), + ).rejects.toThrow('Authorization session not found or expired'); + }); + }); + + describe('exchangeCodeForToken', () => { + it('should exchange valid code for tokens', async () => { + const { service, mocks } = await createOidcService(databaseId); + const mockToken = 'mock-jwt-token'; + mocks.tokenIssuer.issueToken.mockResolvedValue({ token: mockToken }); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + scope: 'openid', + }); + + const authResult = await service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + const code = new URL(authResult.redirectUrl).searchParams.get('code')!; + + const tokenResult = await service.exchangeCodeForToken({ + code, + redirectUri: 'https://example.com/callback', + grantType: 'authorization_code', + }); + + expect(tokenResult).toEqual({ + accessToken: mockToken, + tokenType: 'Bearer', + expiresIn: 3600, + idToken: mockToken, + scope: 'openid', + }); + }); + + it('should throw error for invalid grant type', async () => { + const { service } = await createOidcService(databaseId); + + await expect( + service.exchangeCodeForToken({ + code: 'test-code', + redirectUri: 'https://example.com/callback', + grantType: 'client_credentials', + }), + ).rejects.toThrow('Unsupported grant type'); + }); + + it('should handle PKCE verification', async () => { + const { service, mocks } = await createOidcService(databaseId); + const mockToken = 'mock-jwt-token'; + mocks.tokenIssuer.issueToken.mockResolvedValue({ token: mockToken }); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const codeVerifier = 'test-code-verifier'; + const codeChallenge = crypto + .createHash('sha256') + .update(codeVerifier) + .digest('base64url'); + + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + codeChallenge, + codeChallengeMethod: 'S256', + }); + + const authResult = await service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + const code = new URL(authResult.redirectUrl).searchParams.get('code')!; + + const tokenResult = await service.exchangeCodeForToken({ + code, + redirectUri: 'https://example.com/callback', + grantType: 'authorization_code', + codeVerifier, + }); + + expect(tokenResult.accessToken).toBe(mockToken); + }); + + it('should throw error for invalid PKCE verifier', async () => { + const { service } = await createOidcService(databaseId); + + const client = await service.registerClient({ + clientName: 'Test Client', + redirectUris: ['https://example.com/callback'], + }); + + const codeChallenge = 'test-challenge'; + const authSession = await service.createAuthorizationSession({ + clientId: client.clientId, + redirectUri: 'https://example.com/callback', + responseType: 'code', + codeChallenge, + codeChallengeMethod: 'S256', + }); + + const authResult = await service.approveAuthorizationSession({ + sessionId: authSession.id, + userEntityRef: 'user:default/test', + }); + + const code = new URL(authResult.redirectUrl).searchParams.get('code')!; + + await expect( + service.exchangeCodeForToken({ + code, + redirectUri: 'https://example.com/callback', + grantType: 'authorization_code', + codeVerifier: 'invalid-verifier', + }), + ).rejects.toThrow('Invalid code verifier'); + }); + }); + }); +}); diff --git a/plugins/auth-backend/src/service/OidcService.ts b/plugins/auth-backend/src/service/OidcService.ts index 5024b2cc8c..b4c6bb122b 100644 --- a/plugins/auth-backend/src/service/OidcService.ts +++ b/plugins/auth-backend/src/service/OidcService.ts @@ -13,11 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { AuthService } from '@backstage/backend-plugin-api'; +import { AuthService, RootConfigService } from '@backstage/backend-plugin-api'; import { TokenIssuer } from '../identity/types'; import { UserInfoDatabase } from '../database/UserInfoDatabase'; -import { InputError } from '@backstage/errors'; +import { + InputError, + AuthenticationError, + NotFoundError, +} from '@backstage/errors'; import { decodeJwt } from 'jose'; +import crypto from 'crypto'; +import { OidcDatabase } from '../database/OidcDatabase'; +import { DateTime } from 'luxon'; +import matcher from 'matcher'; export class OidcService { private constructor( @@ -25,6 +33,8 @@ export class OidcService { private readonly tokenIssuer: TokenIssuer, private readonly baseUrl: string, private readonly userInfo: UserInfoDatabase, + private readonly oidc: OidcDatabase, + private readonly config: RootConfigService, ) {} static create(options: { @@ -32,12 +42,16 @@ export class OidcService { tokenIssuer: TokenIssuer; baseUrl: string; userInfo: UserInfoDatabase; + oidc: OidcDatabase; + config: RootConfigService; }) { return new OidcService( options.auth, options.tokenIssuer, options.baseUrl, options.userInfo, + options.oidc, + options.config, ); } @@ -47,7 +61,7 @@ export class OidcService { token_endpoint: `${this.baseUrl}/v1/token`, userinfo_endpoint: `${this.baseUrl}/v1/userinfo`, jwks_uri: `${this.baseUrl}/.well-known/jwks.json`, - response_types_supported: ['id_token'], + response_types_supported: ['code', 'id_token'], subject_types_supported: ['public'], id_token_signing_alg_values_supported: [ 'RS256', @@ -62,9 +76,15 @@ export class OidcService { 'EdDSA', ], scopes_supported: ['openid'], - token_endpoint_auth_methods_supported: [], + token_endpoint_auth_methods_supported: [ + 'client_secret_basic', + 'client_secret_post', + ], claims_supported: ['sub', 'ent'], - grant_types_supported: [], + grant_types_supported: ['authorization_code'], + authorization_endpoint: `${this.baseUrl}/v1/authorize`, + registration_endpoint: `${this.baseUrl}/v1/register`, + code_challenge_methods_supported: ['S256', 'plain'], }; } @@ -89,4 +109,321 @@ export class OidcService { } return await this.userInfo.getUserInfo(userEntityRef); } + + public async registerClient(opts: { + responseTypes?: string[]; + grantTypes?: string[]; + clientName: string; + redirectUris?: string[]; + scope?: string; + }) { + const generatedClientId = crypto.randomUUID(); + const generatedClientSecret = crypto.randomUUID(); + + const allowedRedirectUriPatterns = this.config.getOptionalStringArray( + 'auth.experimentalDynamicClientRegistration.allowedRedirectUriPatterns', + ) ?? ['*']; + + for (const redirectUri of opts.redirectUris ?? []) { + if ( + !allowedRedirectUriPatterns.some(pattern => + matcher.isMatch(redirectUri, pattern), + ) + ) { + throw new InputError('Invalid redirect_uri'); + } + } + + return await this.oidc.createClient({ + clientId: generatedClientId, + clientName: opts.clientName, + clientSecret: generatedClientSecret, + redirectUris: opts.redirectUris ?? [], + responseTypes: opts.responseTypes ?? ['code'], + grantTypes: opts.grantTypes ?? ['authorization_code'], + scope: opts.scope, + }); + } + + public async createAuthorizationSession(opts: { + clientId: string; + redirectUri: string; + responseType: string; + scope?: string; + state?: string; + nonce?: string; + codeChallenge?: string; + codeChallengeMethod?: string; + }) { + const { + clientId, + redirectUri, + responseType, + scope, + state, + nonce, + codeChallenge, + codeChallengeMethod, + } = opts; + + if (responseType !== 'code') { + throw new InputError('Only authorization code flow is supported'); + } + + const client = await this.oidc.getClient({ clientId }); + if (!client) { + throw new InputError('Invalid client_id'); + } + + if (!client.redirectUris.includes(redirectUri)) { + throw new InputError('Invalid redirect_uri'); + } + + if (codeChallenge) { + if ( + !codeChallengeMethod || + !['S256', 'plain'].includes(codeChallengeMethod) + ) { + throw new InputError('Invalid code_challenge_method'); + } + } + + const sessionId = crypto.randomUUID(); + const sessionExpiresAt = DateTime.now().plus({ hours: 1 }).toJSDate(); + + await this.oidc.createAuthorizationSession({ + id: sessionId, + clientId, + redirectUri, + responseType, + scope, + state, + codeChallenge, + codeChallengeMethod, + nonce, + expiresAt: sessionExpiresAt, + }); + + return { + id: sessionId, + clientName: client.clientName, + scope, + redirectUri, + }; + } + + public async approveAuthorizationSession(opts: { + sessionId: string; + userEntityRef: string; + }) { + const { sessionId, userEntityRef } = opts; + + const session = await this.oidc.getAuthorizationSession({ + id: sessionId, + }); + + if (!session) { + throw new NotFoundError('Invalid authorization session'); + } + + if (DateTime.fromJSDate(session.expiresAt) < DateTime.now()) { + throw new InputError('Authorization session expired'); + } + + if (session.status !== 'pending') { + throw new NotFoundError('Authorization session not found or expired'); + } + + await this.oidc.updateAuthorizationSession({ + id: session.id, + userEntityRef, + status: 'approved', + }); + + const authorizationCode = crypto.randomBytes(32).toString('base64url'); + const codeExpiresAt = DateTime.now().plus({ minutes: 10 }).toJSDate(); + + await this.oidc.createAuthorizationCode({ + code: authorizationCode, + sessionId: session.id, + expiresAt: codeExpiresAt, + }); + + const redirectUrl = new URL(session.redirectUri); + + redirectUrl.searchParams.append('code', authorizationCode); + if (session.state) { + redirectUrl.searchParams.append('state', session.state); + } + + return { + redirectUrl: redirectUrl.toString(), + }; + } + + public async getAuthorizationSession(opts: { sessionId: string }) { + const session = await this.oidc.getAuthorizationSession({ + id: opts.sessionId, + }); + + if (!session) { + throw new NotFoundError('Invalid authorization session'); + } + + if (DateTime.fromJSDate(session.expiresAt) < DateTime.now()) { + throw new InputError('Authorization session expired'); + } + + if (session.status !== 'pending') { + throw new NotFoundError('Authorization session not found or expired'); + } + + const client = await this.oidc.getClient({ clientId: session.clientId }); + if (!client) { + throw new InputError('Invalid client_id'); + } + + return { + id: session.id, + clientId: session.clientId, + clientName: client.clientName, + redirectUri: session.redirectUri, + scope: session.scope, + state: session.state, + responseType: session.responseType, + codeChallenge: session.codeChallenge, + codeChallengeMethod: session.codeChallengeMethod, + nonce: session.nonce, + expiresAt: session.expiresAt, + status: session.status, + }; + } + + public async rejectAuthorizationSession(opts: { + sessionId: string; + userEntityRef: string; + }) { + const { sessionId, userEntityRef } = opts; + + const session = await this.oidc.getAuthorizationSession({ + id: sessionId, + }); + + if (!session) { + throw new NotFoundError('Invalid authorization session'); + } + + if (DateTime.fromJSDate(session.expiresAt) < DateTime.now()) { + throw new InputError('Authorization session expired'); + } + + if (session.status !== 'pending') { + throw new NotFoundError('Authorization session not found or expired'); + } + + await this.oidc.updateAuthorizationSession({ + id: session.id, + status: 'rejected', + userEntityRef, + }); + } + + public async exchangeCodeForToken(params: { + code: string; + redirectUri: string; + codeVerifier?: string; + grantType: string; + }) { + const { code, redirectUri, codeVerifier, grantType } = params; + + if (grantType !== 'authorization_code') { + throw new InputError('Unsupported grant type'); + } + + const authCode = await this.oidc.getAuthorizationCode({ code }); + if (!authCode) { + throw new AuthenticationError('Invalid authorization code'); + } + + if (DateTime.fromJSDate(authCode.expiresAt) < DateTime.now()) { + throw new AuthenticationError('Authorization code expired'); + } + + if (authCode.used) { + throw new AuthenticationError('Authorization code already used'); + } + + const session = await this.oidc.getAuthorizationSession({ + id: authCode.sessionId, + }); + + if (!session) { + throw new NotFoundError('Invalid authorization session'); + } + + if (session.redirectUri !== redirectUri) { + throw new AuthenticationError('Redirect URI mismatch'); + } + + if (session.status !== 'approved') { + throw new AuthenticationError('Authorization not approved'); + } + + if (!session.userEntityRef) { + throw new AuthenticationError('No user associated with authorization'); + } + + if (session.codeChallenge) { + if (!codeVerifier) { + throw new AuthenticationError('Code verifier required for PKCE'); + } + + if ( + !this.verifyPkce( + session.codeChallenge, + codeVerifier, + session.codeChallengeMethod, + ) + ) { + throw new AuthenticationError('Invalid code verifier'); + } + } + + await this.oidc.updateAuthorizationCode({ + code, + used: true, + }); + + const { token } = await this.tokenIssuer.issueToken({ + claims: { + sub: session.userEntityRef, + }, + }); + + return { + accessToken: token, + tokenType: 'Bearer', + expiresIn: 3600, + idToken: token, + scope: session.scope || 'openid', + }; + } + + private verifyPkce( + codeChallenge: string, + codeVerifier: string, + method?: string, + ): boolean { + if (!method || method === 'plain') { + return codeChallenge === codeVerifier; + } + + if (method === 'S256') { + const hash = crypto.createHash('sha256').update(codeVerifier).digest(); + const base64urlHash = hash.toString('base64url'); + return codeChallenge === base64urlHash; + } + + return false; + } } diff --git a/plugins/auth-backend/src/service/router.ts b/plugins/auth-backend/src/service/router.ts index 5012c90106..0f0d5b2830 100644 --- a/plugins/auth-backend/src/service/router.ts +++ b/plugins/auth-backend/src/service/router.ts @@ -21,6 +21,7 @@ import { AuthService, DatabaseService, DiscoveryService, + HttpAuthService, LoggerService, RootConfigService, } from '@backstage/backend-plugin-api'; @@ -40,6 +41,7 @@ import { StaticTokenIssuer } from '../identity/StaticTokenIssuer'; import { StaticKeyStore } from '../identity/StaticKeyStore'; import { bindProviderRouters, ProviderFactories } from '../providers/router'; import { OidcRouter } from './OidcRouter'; +import { OidcDatabase } from '../database/OidcDatabase'; interface RouterOptions { logger: LoggerService; @@ -51,6 +53,7 @@ interface RouterOptions { providerFactories?: ProviderFactories; catalog: CatalogService; ownershipResolver?: AuthOwnershipResolver; + httpAuth: HttpAuthService; } export async function createRouter( @@ -63,6 +66,7 @@ export async function createRouter( database: db, tokenFactoryAlgorithm, providerFactories = {}, + httpAuth, } = options; const router = Router(); @@ -147,11 +151,18 @@ export async function createRouter( userInfo, }); + const oidc = await OidcDatabase.create({ database }); + const oidcRouter = OidcRouter.create({ auth: options.auth, tokenIssuer, baseUrl: authUrl, + appUrl, userInfo, + oidc, + logger, + httpAuth, + config, }); router.use(oidcRouter.getRouter()); diff --git a/plugins/auth-node/CHANGELOG.md b/plugins/auth-node/CHANGELOG.md index 48554f6932..3c2ceea7c0 100644 --- a/plugins/auth-node/CHANGELOG.md +++ b/plugins/auth-node/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-node +## 0.6.7-next.1 + +### Patch Changes + +- 54ddfef: Updating plugin metadata +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + ## 0.6.7-next.0 ### Patch Changes diff --git a/plugins/auth-node/package.json b/plugins/auth-node/package.json index 23cff9720c..64c12ae977 100644 --- a/plugins/auth-node/package.json +++ b/plugins/auth-node/package.json @@ -1,10 +1,11 @@ { "name": "@backstage/plugin-auth-node", - "version": "0.6.7-next.0", + "version": "0.6.7-next.1", "backstage": { "role": "node-library", "pluginId": "auth", "pluginPackages": [ + "@backstage/plugin-auth", "@backstage/plugin-auth-backend", "@backstage/plugin-auth-node", "@backstage/plugin-auth-react" diff --git a/plugins/auth-react/CHANGELOG.md b/plugins/auth-react/CHANGELOG.md index 1dc720ab67..9b314d3e4f 100644 --- a/plugins/auth-react/CHANGELOG.md +++ b/plugins/auth-react/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-auth-react +## 0.1.19-next.1 + +### Patch Changes + +- 54ddfef: Updating plugin metadata +- Updated dependencies + - @backstage/core-components@0.17.6-next.1 + ## 0.1.19-next.0 ### Patch Changes diff --git a/plugins/auth-react/package.json b/plugins/auth-react/package.json index 4335bbc03a..2bfee0dd44 100644 --- a/plugins/auth-react/package.json +++ b/plugins/auth-react/package.json @@ -1,11 +1,12 @@ { "name": "@backstage/plugin-auth-react", - "version": "0.1.19-next.0", + "version": "0.1.19-next.1", "description": "Web library for the auth plugin", "backstage": { "role": "web-library", "pluginId": "auth", "pluginPackages": [ + "@backstage/plugin-auth", "@backstage/plugin-auth-backend", "@backstage/plugin-auth-node", "@backstage/plugin-auth-react" diff --git a/plugins/auth/.eslintrc.js b/plugins/auth/.eslintrc.js new file mode 100644 index 0000000000..e2a53a6ad2 --- /dev/null +++ b/plugins/auth/.eslintrc.js @@ -0,0 +1 @@ +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); diff --git a/plugins/auth/CHANGELOG.md b/plugins/auth/CHANGELOG.md new file mode 100644 index 0000000000..d28fef1c9e --- /dev/null +++ b/plugins/auth/CHANGELOG.md @@ -0,0 +1,12 @@ +# @backstage/plugin-auth + +## 0.1.0-next.0 + +### Minor Changes + +- 54ddfef: Initial publish of the `auth` frontend package + +### Patch Changes + +- Updated dependencies + - @backstage/core-components@0.17.6-next.1 diff --git a/plugins/auth/README.md b/plugins/auth/README.md new file mode 100644 index 0000000000..440d7d294a --- /dev/null +++ b/plugins/auth/README.md @@ -0,0 +1,16 @@ +# @backstage/plugin-auth + +A Backstage frontend plugin that provides user interface components for authentication flows, specifically for OpenID Connect (OIDC) consent management. + +## Installation + +This plugin is designed to work with the `@backstage/plugin-auth-backend` package that provides OIDC provider functionality. + +```bash +# From your Backstage app directory +yarn --cwd packages/app add @backstage/plugin-auth +``` + +## Usage + +The plugin provides the route `/oauth2/authorize/:sessionId` for approving of oauth2 sessions for clients. You should see an approval flow for any sessions created through the `auth-backend`. diff --git a/plugins/auth/catalog-info.yaml b/plugins/auth/catalog-info.yaml new file mode 100644 index 0000000000..66d835a198 --- /dev/null +++ b/plugins/auth/catalog-info.yaml @@ -0,0 +1,9 @@ +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-plugin-auth + title: '@backstage/plugin-auth' +spec: + lifecycle: experimental + type: backstage-frontend-plugin + owner: auth-maintainers diff --git a/plugins/auth/dev/index.tsx b/plugins/auth/dev/index.tsx new file mode 100644 index 0000000000..b0762416c6 --- /dev/null +++ b/plugins/auth/dev/index.tsx @@ -0,0 +1,28 @@ +/* + * 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 { createApp } from '@backstage/frontend-defaults'; +import { createRoot } from 'react-dom/client'; + +import plugin from '../src'; + +const app = createApp({ + features: [plugin], +}); + +const container = document.getElementById('root'); +const root = createRoot(container!); +root.render(app.createRoot()); diff --git a/plugins/auth/package.json b/plugins/auth/package.json new file mode 100644 index 0000000000..6c8184db35 --- /dev/null +++ b/plugins/auth/package.json @@ -0,0 +1,84 @@ +{ + "name": "@backstage/plugin-auth", + "version": "0.1.0-next.0", + "backstage": { + "role": "frontend-plugin", + "pluginId": "auth", + "pluginPackages": [ + "@backstage/plugin-auth", + "@backstage/plugin-auth-backend", + "@backstage/plugin-auth-node", + "@backstage/plugin-auth-react" + ] + }, + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/auth" + }, + "license": "Apache-2.0", + "sideEffects": false, + "exports": { + ".": "./src/index.ts", + "./package.json": "./package.json" + }, + "main": "src/index.ts", + "types": "src/index.ts", + "typesVersions": { + "*": { + "package.json": [ + "package.json" + ] + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "backstage-cli package build", + "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", + "prepack": "backstage-cli package prepack", + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" + }, + "dependencies": { + "@backstage/core-components": "workspace:^", + "@backstage/errors": "workspace:^", + "@backstage/frontend-plugin-api": "workspace:^", + "@backstage/theme": "workspace:^", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.61", + "react-use": "^17.2.4" + }, + "devDependencies": { + "@backstage/cli": "workspace:^", + "@backstage/dev-utils": "workspace:^", + "@backstage/frontend-defaults": "workspace:^", + "@backstage/test-utils": "workspace:^", + "@testing-library/jest-dom": "^6.0.0", + "@testing-library/react": "^16.0.0", + "@testing-library/user-event": "^14.0.0", + "@types/react": "^18.0.0", + "msw": "^1.0.0", + "react": "^18.0.2", + "react-dom": "^18.0.2", + "react-router-dom": "^6.3.0" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0", + "react": "^17.0.0 || ^18.0.0", + "react-dom": "^17.0.0 || ^18.0.0", + "react-router-dom": "^6.3.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } +} diff --git a/plugins/auth/report.api.md b/plugins/auth/report.api.md new file mode 100644 index 0000000000..4c7d2d4a11 --- /dev/null +++ b/plugins/auth/report.api.md @@ -0,0 +1,52 @@ +## API Report File for "@backstage/plugin-auth" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts +import { AnyRouteRefParams } from '@backstage/frontend-plugin-api'; +import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; +import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; +import { JSX as JSX_2 } from 'react'; +import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; +import { RouteRef } from '@backstage/frontend-plugin-api'; + +// @public (undocumented) +const _default: OverridableFrontendPlugin< + { + root: RouteRef; + }, + {}, + { + 'page:auth': ExtensionDefinition<{ + kind: 'page'; + name: undefined; + config: { + path: string | undefined; + }; + configInput: { + path?: string | undefined; + }; + output: + | ExtensionDataRef + | ExtensionDataRef + | ExtensionDataRef< + RouteRef, + 'core.routing.ref', + { + optional: true; + } + >; + inputs: {}; + params: { + defaultPath?: [Error: `Use the 'path' param instead`]; + path: string; + loader: () => Promise; + routeRef?: RouteRef; + }; + }>; + } +>; +export default _default; + +// (No @packageDocumentation comment for this package) +``` diff --git a/plugins/auth/src/components/ConsentPage/ConsentPage.tsx b/plugins/auth/src/components/ConsentPage/ConsentPage.tsx new file mode 100644 index 0000000000..0f071025a2 --- /dev/null +++ b/plugins/auth/src/components/ConsentPage/ConsentPage.tsx @@ -0,0 +1,246 @@ +/* + * 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 { useParams } from 'react-router-dom'; + +import { + Box, + Button, + Card, + CardContent, + CardActions, + Typography, + makeStyles, + Divider, +} from '@material-ui/core'; +import { Alert } from '@material-ui/lab'; +import CheckCircleIcon from '@material-ui/icons/CheckCircle'; +import CancelIcon from '@material-ui/icons/Cancel'; +import AppsIcon from '@material-ui/icons/Apps'; +import WarningIcon from '@material-ui/icons/Warning'; +import { + Header, + Page, + Content, + Progress, + EmptyState, + ResponseErrorPanel, +} from '@backstage/core-components'; +import { useConsentSession } from './useConsentSession'; + +const useStyles = makeStyles(theme => ({ + authCard: { + maxWidth: 600, + margin: '0 auto', + marginTop: theme.spacing(4), + }, + appHeader: { + display: 'flex', + alignItems: 'center', + marginBottom: theme.spacing(2), + }, + appIcon: { + marginRight: theme.spacing(2), + fontSize: 40, + }, + appName: { + fontSize: '1.5rem', + fontWeight: 'bold', + }, + securityWarning: { + margin: theme.spacing(2, 0), + }, + buttonContainer: { + display: 'flex', + justifyContent: 'space-between', + gap: theme.spacing(2), + padding: theme.spacing(2), + }, + callbackUrl: { + fontFamily: 'monospace', + backgroundColor: theme.palette.background.default, + padding: theme.spacing(1), + borderRadius: theme.shape.borderRadius, + wordBreak: 'break-all', + fontSize: '0.875rem', + }, + scopeList: { + backgroundColor: theme.palette.background.default, + borderRadius: theme.shape.borderRadius, + padding: theme.spacing(1), + }, +})); + +const ConsentPageLayout = ({ + title, + children, +}: { + title: string; + children: React.ReactNode; +}) => ( + +
+ {children} + +); + +export const ConsentPage = () => { + const classes = useStyles(); + const { sessionId } = useParams<{ sessionId: string }>(); + const { state, handleAction } = useConsentSession({ sessionId }); + + if (!sessionId) { + return ( + + + + ); + } + + if (state.status === 'loading') { + return ( + + + + + + ); + } + + if (state.status === 'error') { + return ( + + + + ); + } + + if (state.status === 'completed') { + return ( + + + + + {state.action === 'approve' ? ( + + ) : ( + + )} + + {state.action === 'approve' + ? 'Authorization Approved' + : 'Authorization Denied'} + + + {state.action === 'approve' + ? 'You have successfully authorized the application to access your Backstage account.' + : 'You have denied the application access to your Backstage account.'} + + + Redirecting to the application... + + + + + + ); + } + + const session = state.session; + const isSubmitting = state.status === 'submitting'; + const appName = session.clientName ?? session.clientId; + + return ( + + + + + + + {appName} + + wants to access your Backstage account + + + + + + + } + className={classes.securityWarning} + > + + Security Notice: By authorizing this application, + you are granting it access to your Backstage account. The + application will receive an access token that allows it to act on + your behalf. + + + + Callback URL: + + {session.redirectUri} + + + + + + Make sure you trust this application and recognize the callback + URL above. Only authorize applications you trust. + + + + + + + + + + + ); +}; diff --git a/plugins/auth/src/components/ConsentPage/index.ts b/plugins/auth/src/components/ConsentPage/index.ts new file mode 100644 index 0000000000..9fdd44c96d --- /dev/null +++ b/plugins/auth/src/components/ConsentPage/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 { ConsentPage } from './ConsentPage'; diff --git a/plugins/auth/src/components/ConsentPage/useConsentSession.ts b/plugins/auth/src/components/ConsentPage/useConsentSession.ts new file mode 100644 index 0000000000..a19faae6fe --- /dev/null +++ b/plugins/auth/src/components/ConsentPage/useConsentSession.ts @@ -0,0 +1,144 @@ +/* + * 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 { + useApi, + alertApiRef, + fetchApiRef, + discoveryApiRef, +} from '@backstage/frontend-plugin-api'; +import { useCallback } from 'react'; +import useAsync from 'react-use/esm/useAsync'; +import useAsyncFn from 'react-use/esm/useAsyncFn'; +import { isError } from '@backstage/errors'; + +interface Session { + id: string; + clientName?: string; + clientId: string; + redirectUri: string; + scopes?: string[]; + responseType?: string; + state?: string; + nonce?: string; + codeChallenge?: string; + codeChallengeMethod?: string; + expiresAt?: string; +} + +type ConsentState = + | { status: 'loading' } + | { status: 'error'; error: string } + | { status: 'loaded'; session: Session } + | { status: 'submitting'; session: Session; action: 'approve' | 'reject' } + | { status: 'completed'; action: 'approve' | 'reject' }; + +export const useConsentSession = (opts: { sessionId?: string }) => { + const alertApi = useApi(alertApiRef); + const fetchApi = useApi(fetchApiRef); + const discoveryApi = useApi(discoveryApiRef); + const { sessionId } = opts; + + const sessionState = useAsync(async () => { + if (!sessionId) { + throw new Error('Session ID is missing'); + } + + const baseUrl = await discoveryApi.getBaseUrl('auth'); + const response = await fetchApi.fetch( + `${baseUrl}/v1/sessions/${sessionId}`, + ); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + return (await response.json()) as Session; + }, [sessionId]); + + const [actionState, handleActionInternal] = useAsyncFn( + async (action: 'approve' | 'reject', session: Session) => { + const baseUrl = await discoveryApi.getBaseUrl('auth'); + const response = await fetchApi.fetch( + `${baseUrl}/v1/sessions/${session.id}/${action}`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + }, + ); + + if (!response.ok) { + throw new Error(`HTTP ${response.status}: ${response.statusText}`); + } + + const result = await response.json(); + + if (result.redirectUrl) { + window.location.href = result.redirectUrl; + } + + return { action, redirectUrl: result.redirectUrl }; + }, + [discoveryApi, fetchApi], + ); + + const getConsentState = (): ConsentState => { + if (actionState.value) { + return { status: 'completed', action: actionState.value.action }; + } + if (actionState.loading && sessionState.value) { + return { + status: 'submitting', + session: sessionState.value, + action: 'approve', // This will be set properly when called + }; + } + if (sessionState.error) { + return { + status: 'error', + error: isError(sessionState.error) + ? sessionState.error.message + : 'Failed to load consent request', + }; + } + if (sessionState.value) { + return { status: 'loaded', session: sessionState.value }; + } + return { status: 'loading' }; + }; + + const state = getConsentState(); + return { + state, + handleAction: useCallback( + async (action: 'approve' | 'reject') => { + if (state.status !== 'loaded') return; + + try { + await handleActionInternal(action, state.session); + } catch (err) { + alertApi.post({ + message: isError(err) ? err.message : `Failed to ${action} consent`, + severity: 'error', + }); + } + }, + [state, handleActionInternal, alertApi], + ), + }; +}; diff --git a/plugins/auth/src/components/Router.tsx b/plugins/auth/src/components/Router.tsx new file mode 100644 index 0000000000..fbb5f9aaa9 --- /dev/null +++ b/plugins/auth/src/components/Router.tsx @@ -0,0 +1,29 @@ +/* + * 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 { Routes, Route } from 'react-router-dom'; +import { ConsentPage } from './ConsentPage'; + +/** + * Router component for the auth plugin + * @public + */ +export const Router = () => { + return ( + + } /> + + ); +}; diff --git a/plugins/auth/src/index.ts b/plugins/auth/src/index.ts new file mode 100644 index 0000000000..717cdd4672 --- /dev/null +++ b/plugins/auth/src/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 { default } from './plugin'; diff --git a/plugins/auth/src/plugin.test.ts b/plugins/auth/src/plugin.test.ts new file mode 100644 index 0000000000..a50b718e5d --- /dev/null +++ b/plugins/auth/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * 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 { default as authPlugin } from './plugin'; + +describe('auth', () => { + it('should export plugin', () => { + expect(authPlugin).toBeDefined(); + }); +}); diff --git a/plugins/auth/src/plugin.tsx b/plugins/auth/src/plugin.tsx new file mode 100644 index 0000000000..4ed5d57223 --- /dev/null +++ b/plugins/auth/src/plugin.tsx @@ -0,0 +1,36 @@ +/* + * 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 { + createFrontendPlugin, + PageBlueprint, +} from '@backstage/frontend-plugin-api'; +import { rootRouteRef } from './routes'; + +export const AuthPage = PageBlueprint.make({ + params: { + path: '/oauth2', + routeRef: rootRouteRef, + loader: () => import('./components/Router').then(m => ), + }, +}); + +export default createFrontendPlugin({ + pluginId: 'auth', + extensions: [AuthPage], + routes: { + root: rootRouteRef, + }, +}); diff --git a/plugins/auth/src/routes.ts b/plugins/auth/src/routes.ts new file mode 100644 index 0000000000..09e6a48da4 --- /dev/null +++ b/plugins/auth/src/routes.ts @@ -0,0 +1,18 @@ +/* + * 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 { createRouteRef } from '@backstage/frontend-plugin-api'; + +export const rootRouteRef = createRouteRef(); diff --git a/plugins/auth/src/setupTests.ts b/plugins/auth/src/setupTests.ts new file mode 100644 index 0000000000..b57590b525 --- /dev/null +++ b/plugins/auth/src/setupTests.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. + */ +import '@testing-library/jest-dom'; diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index 3ba5538fc5..7ceff47a80 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.4.15-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/integration-aws-node@0.1.17 + ## 0.4.15-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 9f98b788a7..4dfe5b990d 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", - "version": "0.4.15-next.0", + "version": "0.4.15-next.1", "description": "A Backstage catalog backend module that helps integrate towards AWS", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 31364b56b3..0962c2aa28 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.3.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.3.9-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 51956ca1a5..dad34fec2a 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", - "version": "0.3.9-next.0", + "version": "0.3.9-next.1", "description": "A Backstage catalog backend module that helps integrate towards Azure", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md index 7f31323ddd..d40c4e03e4 100644 --- a/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-backstage-openapi/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-catalog-backend-module-backstage-openapi +## 0.5.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.5.6-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-backstage-openapi/package.json b/plugins/catalog-backend-module-backstage-openapi/package.json index db55d563de..f004e1bb16 100644 --- a/plugins/catalog-backend-module-backstage-openapi/package.json +++ b/plugins/catalog-backend-module-backstage-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-backstage-openapi", - "version": "0.5.6-next.0", + "version": "0.5.6-next.1", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index edb0a14cf3..c462210097 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.5.3-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 56ab813052..97eea0897f 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", - "version": "0.5.3-next.0", + "version": "0.5.3-next.1", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index 42964bad70..66965f3009 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.5.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.5.3-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index a3cf31ee9a..98d28131a9 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.5.3-next.0", + "version": "0.5.3-next.1", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-gcp/CHANGELOG.md b/plugins/catalog-backend-module-gcp/CHANGELOG.md index 9cf3bcb98f..fa30682d37 100644 --- a/plugins/catalog-backend-module-gcp/CHANGELOG.md +++ b/plugins/catalog-backend-module-gcp/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-catalog-backend-module-gcp +## 0.3.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.3.12-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gcp/package.json b/plugins/catalog-backend-module-gcp/package.json index ac095bfc4a..5459221795 100644 --- a/plugins/catalog-backend-module-gcp/package.json +++ b/plugins/catalog-backend-module-gcp/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gcp", - "version": "0.3.12-next.0", + "version": "0.3.12-next.1", "description": "A Backstage catalog backend module that helps integrate towards GCP", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index eaf94c852a..ea0a8a0bbb 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.3.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.3.6-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 62f17f1b26..9dac6c9526 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.3.6-next.0", + "version": "0.3.6-next.1", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-gitea/CHANGELOG.md b/plugins/catalog-backend-module-gitea/CHANGELOG.md index 036dd6b477..f8b03e496c 100644 --- a/plugins/catalog-backend-module-gitea/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitea/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-gitea +## 0.1.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.1.4-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitea/package.json b/plugins/catalog-backend-module-gitea/package.json index 3aaf419c82..8389ee70ef 100644 --- a/plugins/catalog-backend-module-gitea/package.json +++ b/plugins/catalog-backend-module-gitea/package.json @@ -1,10 +1,12 @@ { "name": "@backstage/plugin-catalog-backend-module-gitea", - "version": "0.1.4-next.0", - "license": "Apache-2.0", + "version": "0.1.4-next.1", "description": "The gitea backend module for the catalog plugin.", - "main": "src/index.ts", - "types": "src/index.ts", + "backstage": { + "role": "backend-plugin-module", + "pluginId": "catalog", + "pluginPackage": "@backstage/plugin-catalog-backend" + }, "publishConfig": { "access": "public", "main": "dist/index.cjs.js", @@ -15,19 +17,20 @@ "url": "https://github.com/backstage/backstage", "directory": "plugins/catalog-backend-module-gitea" }, - "backstage": { - "role": "backend-plugin-module", - "pluginId": "catalog", - "pluginPackage": "@backstage/plugin-catalog-backend" - }, + "license": "Apache-2.0", + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "dist" + ], "scripts": { - "start": "backstage-cli package start", "build": "backstage-cli package build", - "lint": "backstage-cli package lint", - "test": "backstage-cli package test", "clean": "backstage-cli package clean", + "lint": "backstage-cli package lint", "prepack": "backstage-cli package prepack", - "postpack": "backstage-cli package postpack" + "postpack": "backstage-cli package postpack", + "start": "backstage-cli package start", + "test": "backstage-cli package test" }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", @@ -42,8 +45,5 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^" - }, - "files": [ - "dist" - ] + } } diff --git a/plugins/catalog-backend-module-github-org/CHANGELOG.md b/plugins/catalog-backend-module-github-org/CHANGELOG.md index d6110b1f5a..9007c5ab97 100644 --- a/plugins/catalog-backend-module-github-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-github-org/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-github-org +## 0.3.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/plugin-catalog-backend-module-github@0.11.0-next.1 + ## 0.3.14-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index 04029f57b9..ff2b78abc1 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github-org", - "version": "0.3.14-next.0", + "version": "0.3.14-next.1", "description": "The github-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index b412ef8780..444d602783 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-backend-module-github +## 0.11.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-backend@3.0.2-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.11.0-next.0 ### Minor Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index a61deeb214..42c8446a75 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github", - "version": "0.11.0-next.0", + "version": "0.11.0-next.1", "description": "A Backstage catalog backend module that helps integrate towards GitHub", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md b/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md index afd3317620..88d11fb806 100644 --- a/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-gitlab-org +## 0.2.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/plugin-catalog-backend-module-gitlab@0.7.3-next.1 + ## 0.2.13-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab-org/package.json b/plugins/catalog-backend-module-gitlab-org/package.json index 05b9e75a0c..98d45ebe61 100644 --- a/plugins/catalog-backend-module-gitlab-org/package.json +++ b/plugins/catalog-backend-module-gitlab-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab-org", - "version": "0.2.13-next.0", + "version": "0.2.13-next.1", "description": "The gitlab-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 958c3b364a..adbc95ee65 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.7.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.7.3-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 7d8fe59327..14d62a2ad8 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", - "version": "0.7.3-next.0", + "version": "0.7.3-next.1", "description": "A Backstage catalog backend module that helps integrate towards GitLab", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md index 9139c3e3f1..1d93406c49 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md +++ b/plugins/catalog-backend-module-incremental-ingestion/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-backend-module-incremental-ingestion +## 0.7.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-catalog-backend@3.0.2-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.7.4-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-incremental-ingestion/package.json b/plugins/catalog-backend-module-incremental-ingestion/package.json index 5a2acc53fc..7a83dd50af 100644 --- a/plugins/catalog-backend-module-incremental-ingestion/package.json +++ b/plugins/catalog-backend-module-incremental-ingestion/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-incremental-ingestion", - "version": "0.7.4-next.0", + "version": "0.7.4-next.1", "description": "An entity provider for streaming large asset sources into the catalog", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-ldap/CHANGELOG.md b/plugins/catalog-backend-module-ldap/CHANGELOG.md index 83b25b4f4c..343a87c514 100644 --- a/plugins/catalog-backend-module-ldap/CHANGELOG.md +++ b/plugins/catalog-backend-module-ldap/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-catalog-backend-module-ldap +## 0.11.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.11.9-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index 9e32b21bb3..02e2216d09 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-ldap", - "version": "0.11.9-next.0", + "version": "0.11.9-next.1", "description": "A Backstage catalog backend module that helps integrate towards LDAP", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index b48d58fbd2..0ecb111c7a 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.8.0-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.8.0-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index facfd228a3..12fcfa0585 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", - "version": "0.8.0-next.1", + "version": "0.8.0-next.2", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-openapi/CHANGELOG.md b/plugins/catalog-backend-module-openapi/CHANGELOG.md index 6c82466060..4a1c9eca0a 100644 --- a/plugins/catalog-backend-module-openapi/CHANGELOG.md +++ b/plugins/catalog-backend-module-openapi/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-openapi +## 0.2.14-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.2.14-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-openapi/package.json b/plugins/catalog-backend-module-openapi/package.json index 3902aafcb7..fec08415cd 100644 --- a/plugins/catalog-backend-module-openapi/package.json +++ b/plugins/catalog-backend-module-openapi/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-openapi", - "version": "0.2.14-next.0", + "version": "0.2.14-next.1", "description": "A Backstage catalog backend module that helps with OpenAPI specifications", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index 141e2d52ad..dee1e885fc 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.2.14-next.1 + +### Patch Changes + +- afd368e: **BREAKING ALPHA**: The module has been moved from the `/alpha` export to the root of the package. +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.2.14-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index bcbdcbef48..51c43d475f 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", - "version": "0.2.14-next.0", + "version": "0.2.14-next.1", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", "backstage": { "role": "backend-plugin-module", @@ -24,16 +24,12 @@ "license": "Apache-2.0", "exports": { ".": "./src/index.ts", - "./alpha": "./src/alpha.ts", "./package.json": "./package.json" }, "main": "src/index.ts", "types": "src/index.ts", "typesVersions": { "*": { - "alpha": [ - "src/alpha.ts" - ], "package.json": [ "package.json" ] diff --git a/plugins/catalog-backend-module-puppetdb/report-alpha.api.md b/plugins/catalog-backend-module-puppetdb/report-alpha.api.md deleted file mode 100644 index 211add3895..0000000000 --- a/plugins/catalog-backend-module-puppetdb/report-alpha.api.md +++ /dev/null @@ -1,13 +0,0 @@ -## API Report File for "@backstage/plugin-catalog-backend-module-puppetdb" - -> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). - -```ts -import { BackendFeature } from '@backstage/backend-plugin-api'; - -// @alpha -const catalogModulePuppetDbEntityProvider: BackendFeature; -export default catalogModulePuppetDbEntityProvider; - -// (No @packageDocumentation comment for this package) -``` diff --git a/plugins/catalog-backend-module-puppetdb/report.api.md b/plugins/catalog-backend-module-puppetdb/report.api.md index f6fa5bfc83..6b846b29dd 100644 --- a/plugins/catalog-backend-module-puppetdb/report.api.md +++ b/plugins/catalog-backend-module-puppetdb/report.api.md @@ -3,6 +3,7 @@ > Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). ```ts +import { BackendFeature } from '@backstage/backend-plugin-api'; import { Config } from '@backstage/config'; import { EntityProvider } from '@backstage/plugin-catalog-node'; import { EntityProviderConnection } from '@backstage/plugin-catalog-node'; @@ -16,6 +17,10 @@ import { SchedulerServiceTaskScheduleDefinition } from '@backstage/backend-plugi // @public export const ANNOTATION_PUPPET_CERTNAME = 'puppet.com/certname'; +// @public +const catalogModulePuppetDbEntityProvider: BackendFeature; +export default catalogModulePuppetDbEntityProvider; + // @public export const DEFAULT_PROVIDER_ID = 'default'; diff --git a/plugins/catalog-backend-module-puppetdb/src/index.ts b/plugins/catalog-backend-module-puppetdb/src/index.ts index b5c5f9d209..9b10bd630f 100644 --- a/plugins/catalog-backend-module-puppetdb/src/index.ts +++ b/plugins/catalog-backend-module-puppetdb/src/index.ts @@ -22,3 +22,4 @@ export * from './providers'; export * from './puppet'; +export { default } from './module'; diff --git a/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts b/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts index aa524f2409..1ab95c90d8 100644 --- a/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts +++ b/plugins/catalog-backend-module-puppetdb/src/module/catalogModulePuppetDbEntityProvider.ts @@ -24,7 +24,7 @@ import { PuppetDbEntityProvider } from '../providers/PuppetDbEntityProvider'; /** * Registers the `PuppetDbEntityProvider` with the catalog processing extension point. * - * @alpha + * @public */ export const catalogModulePuppetDbEntityProvider = createBackendModule({ pluginId: 'catalog', diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md index 4a6c195039..9c17f17eaa 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md +++ b/plugins/catalog-backend-module-scaffolder-entity-model/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-catalog-backend-module-scaffolder-entity-model +## 0.2.12-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.2.12-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-scaffolder-entity-model/package.json b/plugins/catalog-backend-module-scaffolder-entity-model/package.json index 6e040f8078..7019619a6c 100644 --- a/plugins/catalog-backend-module-scaffolder-entity-model/package.json +++ b/plugins/catalog-backend-module-scaffolder-entity-model/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-scaffolder-entity-model", - "version": "0.2.12-next.0", + "version": "0.2.12-next.1", "description": "Adds support for the scaffolder specific entity model (e.g. the Template kind) to the catalog backend plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md index 28436537b0..ede26e78d1 100644 --- a/plugins/catalog-backend-module-unprocessed/CHANGELOG.md +++ b/plugins/catalog-backend-module-unprocessed/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-unprocessed +## 0.6.4-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.6.4-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-unprocessed/package.json b/plugins/catalog-backend-module-unprocessed/package.json index a3de0c75a4..e949240c64 100644 --- a/plugins/catalog-backend-module-unprocessed/package.json +++ b/plugins/catalog-backend-module-unprocessed/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-unprocessed", - "version": "0.6.4-next.0", + "version": "0.6.4-next.1", "description": "Backstage Catalog module to view unprocessed entities", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend/CHANGELOG.md b/plugins/catalog-backend/CHANGELOG.md index ad535f16fd..52ebffab31 100644 --- a/plugins/catalog-backend/CHANGELOG.md +++ b/plugins/catalog-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-backend +## 3.0.2-next.1 + +### Patch Changes + +- 2204f5b: Prevent deadlock in catalog deferred stitching +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 3.0.2-next.0 ### Patch Changes diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index d825f29356..7a2df294fd 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend", - "version": "3.0.2-next.0", + "version": "3.0.2-next.1", "description": "The Backstage backend plugin that provides the Backstage catalog", "backstage": { "role": "backend-plugin", diff --git a/plugins/catalog-backend/src/database/operations/stitcher/markForStitching.test.ts b/plugins/catalog-backend/src/database/operations/stitcher/markForStitching.test.ts index 1afa0b9c30..ff450e9ccf 100644 --- a/plugins/catalog-backend/src/database/operations/stitcher/markForStitching.test.ts +++ b/plugins/catalog-backend/src/database/operations/stitcher/markForStitching.test.ts @@ -435,4 +435,139 @@ describe('markForStitching', () => { } }, ); + + it.each(databases.eachSupportedId())( + 'reproduces deadlock scenario when concurrent transactions update overlapping entity sets %p', + async databaseId => { + const knex = await databases.init(databaseId); + await applyDatabaseMigrations(knex); + + // Setup test data with multiple entities + const entityRefs = [ + 'k:ns/entity-a', + 'k:ns/entity-b', + 'k:ns/entity-c', + 'k:ns/entity-d', + 'k:ns/entity-e', + 'k:ns/entity-f', + ]; + + await knex('refresh_state').insert( + entityRefs.map((ref, i) => ({ + entity_id: `${i + 1}`, + entity_ref: ref, + unprocessed_entity: '{}', + processed_entity: '{}', + errors: '[]', + next_update_at: knex.fn.now(), + last_discovery_at: knex.fn.now(), + next_stitch_at: null, + next_stitch_ticket: null, + })), + ); + + // This test attempts to reproduce the deadlock by running concurrent transactions + // that update overlapping sets of entities in different orders + const errorResults = []; + + for (let attempt = 0; attempt < 10; attempt++) { + // Transaction 1: Update entities A, B, C, D, E + const transaction1 = knex.transaction(async trx => { + await markForStitching({ + knex: trx, + strategy: { + mode: 'deferred', + pollingInterval: { seconds: 1 }, + stitchTimeout: { seconds: 1 }, + }, + entityRefs: [ + 'k:ns/entity-a', + 'k:ns/entity-b', + 'k:ns/entity-c', + 'k:ns/entity-d', + 'k:ns/entity-e', + ], + }); + + // Add a small delay to increase chance of collision + await new Promise(resolve => setTimeout(resolve, 10)); + + await markForStitching({ + knex: trx, + strategy: { + mode: 'deferred', + pollingInterval: { seconds: 1 }, + stitchTimeout: { seconds: 1 }, + }, + entityRefs: ['k:ns/entity-f'], + }); + }); + + // Transaction 2: Update entities F, E, D, C, B (reverse order) + const transaction2 = knex.transaction(async trx => { + await markForStitching({ + knex: trx, + strategy: { + mode: 'deferred', + pollingInterval: { seconds: 1 }, + stitchTimeout: { seconds: 1 }, + }, + entityRefs: [ + 'k:ns/entity-f', + 'k:ns/entity-e', + 'k:ns/entity-d', + 'k:ns/entity-c', + 'k:ns/entity-b', + ], + }); + + // Add a small delay to increase chance of collision + await new Promise(resolve => setTimeout(resolve, 10)); + + await markForStitching({ + knex: trx, + strategy: { + mode: 'deferred', + pollingInterval: { seconds: 1 }, + stitchTimeout: { seconds: 1 }, + }, + entityRefs: ['k:ns/entity-a'], + }); + }); + + // Run both transactions concurrently to create potential deadlock + errorResults.push( + Promise.allSettled([transaction1, transaction2]).then(results => + results + .filter(r => r.status === 'rejected') + .map(r => (r as PromiseRejectedResult).reason), + ), + ); + } + + const allResults = await Promise.all(errorResults); + + const deadlockErrors = allResults + .flat() + .filter( + error => + error?.code === '40P01' || + error?.message?.includes('deadlock detected') || + error?.message?.includes('deadlock'), + ); + expect(deadlockErrors).toEqual([]); + + // Verify final state - all entities should have been marked for stitching + const finalState = await knex('refresh_state') + .select('entity_ref', 'next_stitch_at', 'next_stitch_ticket') + .whereNotNull('next_stitch_at') + .orderBy('entity_ref'); + + expect(finalState.length).toBeGreaterThan(0); + finalState.forEach(row => { + expect(row.next_stitch_at).not.toBeNull(); + expect(row.next_stitch_ticket).not.toBeNull(); + }); + }, + ); }); diff --git a/plugins/catalog-backend/src/database/operations/stitcher/markForStitching.ts b/plugins/catalog-backend/src/database/operations/stitcher/markForStitching.ts index ecc364a9cc..484d6e4ed6 100644 --- a/plugins/catalog-backend/src/database/operations/stitcher/markForStitching.ts +++ b/plugins/catalog-backend/src/database/operations/stitcher/markForStitching.ts @@ -17,9 +17,34 @@ import { Knex } from 'knex'; import splitToChunks from 'lodash/chunk'; import { v4 as uuid } from 'uuid'; +import { ErrorLike, isError } from '@backstage/errors'; import { StitchingStrategy } from '../../../stitching/types'; +import { setTimeout as sleep } from 'timers/promises'; import { DbFinalEntitiesRow, DbRefreshStateRow } from '../../tables'; +const UPDATE_CHUNK_SIZE = 100; // Smaller chunks reduce contention +const DEADLOCK_RETRY_ATTEMPTS = 3; +const DEADLOCK_BASE_DELAY_MS = 25; + +// PostgreSQL deadlock error code +const POSTGRES_DEADLOCK_SQLSTATE = '40P01'; + +/** + * Checks if the given error is a deadlock error for the database engine in use. + */ +function isDeadlockError( + knex: Knex | Knex.Transaction, + e: unknown, +): e is ErrorLike { + if (knex.client.config.client.includes('pg')) { + // PostgreSQL deadlock detection + return isError(e) && e.code === POSTGRES_DEADLOCK_SQLSTATE; + } + + // Add more database engine checks here as needed + return false; +} + /** * Marks a number of entities for stitching some time in the near * future. @@ -32,9 +57,8 @@ export async function markForStitching(options: { entityRefs?: Iterable; entityIds?: Iterable; }): Promise { - // Splitting to chunks just to cover pathological cases that upset the db - const entityRefs = split(options.entityRefs); - const entityIds = split(options.entityIds); + const entityRefs = sortSplit(options.entityRefs); + const entityIds = sortSplit(options.entityIds); const knex = options.knex; const mode = options.strategy.mode; @@ -51,13 +75,15 @@ export async function markForStitching(options: { .select('entity_id') .whereIn('entity_ref', chunk), ); - await knex - .table('refresh_state') - .update({ - result_hash: 'force-stitching', - next_update_at: knex.fn.now(), - }) - .whereIn('entity_ref', chunk); + await retryOnDeadlock(async () => { + await knex + .table('refresh_state') + .update({ + result_hash: 'force-stitching', + next_update_at: knex.fn.now(), + }) + .whereIn('entity_ref', chunk); + }, knex); } for (const chunk of entityIds) { @@ -67,44 +93,74 @@ export async function markForStitching(options: { hash: 'force-stitching', }) .whereIn('entity_id', chunk); - await knex - .table('refresh_state') - .update({ - result_hash: 'force-stitching', - next_update_at: knex.fn.now(), - }) - .whereIn('entity_id', chunk); + await retryOnDeadlock(async () => { + await knex + .table('refresh_state') + .update({ + result_hash: 'force-stitching', + next_update_at: knex.fn.now(), + }) + .whereIn('entity_id', chunk); + }, knex); } } else if (mode === 'deferred') { // It's OK that this is shared across refresh state rows; it just needs to // be uniquely generated for every new stitch request. const ticket = uuid(); + // Update by primary key in deterministic order to avoid deadlocks for (const chunk of entityRefs) { - await knex('refresh_state') - .update({ - next_stitch_at: knex.fn.now(), - next_stitch_ticket: ticket, - }) - .whereIn('entity_ref', chunk); + await retryOnDeadlock(async () => { + await knex('refresh_state') + .update({ + next_stitch_at: knex.fn.now(), + next_stitch_ticket: ticket, + }) + .whereIn('entity_ref', chunk); + }, knex); } for (const chunk of entityIds) { - await knex('refresh_state') - .update({ - next_stitch_at: knex.fn.now(), - next_stitch_ticket: ticket, - }) - .whereIn('entity_id', chunk); + await retryOnDeadlock(async () => { + await knex('refresh_state') + .update({ + next_stitch_at: knex.fn.now(), + next_stitch_ticket: ticket, + }) + .whereIn('entity_id', chunk); + }, knex); } } else { throw new Error(`Unknown stitching strategy mode ${mode}`); } } -function split(input: Iterable | undefined): string[][] { +function sortSplit(input: Iterable | undefined): string[][] { if (!input) { return []; } - return splitToChunks(Array.isArray(input) ? input : [...input], 200); + const array = Array.isArray(input) ? input.slice() : [...input]; + array.sort(); + return splitToChunks(array, UPDATE_CHUNK_SIZE); +} + +async function retryOnDeadlock( + fn: () => Promise, + knex: Knex | Knex.Transaction, + retries = DEADLOCK_RETRY_ATTEMPTS, + baseMs = DEADLOCK_BASE_DELAY_MS, +): Promise { + let attempt = 0; + for (;;) { + try { + return await fn(); + } catch (e: unknown) { + if (isDeadlockError(knex, e) && attempt < retries) { + await sleep(baseMs * Math.pow(2, attempt)); + attempt++; + continue; + } + throw e; + } + } } diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index a756916c38..5fa578c1ad 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-catalog-graph +## 0.4.23-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + ## 0.4.23-next.1 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 7cea775bbe..1167fe111b 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.4.23-next.1", + "version": "0.4.23-next.2", "backstage": { "role": "frontend-plugin", "pluginId": "catalog-graph", diff --git a/plugins/catalog-import/CHANGELOG.md b/plugins/catalog-import/CHANGELOG.md index 77ad27ced9..ecd0d8bc46 100644 --- a/plugins/catalog-import/CHANGELOG.md +++ b/plugins/catalog-import/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog-import +## 0.13.5-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/core-compat-api@0.5.2-next.2 + ## 0.13.5-next.1 ### Patch Changes diff --git a/plugins/catalog-import/package.json b/plugins/catalog-import/package.json index 050e8be908..39ed5bcef0 100644 --- a/plugins/catalog-import/package.json +++ b/plugins/catalog-import/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-import", - "version": "0.13.5-next.1", + "version": "0.13.5-next.2", "description": "A Backstage plugin the helps you import entities into your catalog", "backstage": { "role": "frontend-plugin", diff --git a/plugins/catalog-node/CHANGELOG.md b/plugins/catalog-node/CHANGELOG.md index 18f44ba88f..14ac349b6d 100644 --- a/plugins/catalog-node/CHANGELOG.md +++ b/plugins/catalog-node/CHANGELOG.md @@ -1,5 +1,33 @@ # @backstage/plugin-catalog-node +## 1.19.0-next.1 + +### Minor Changes + +- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog. + + Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog. + This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them + all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination + or fetch all entities at once. + + Example usage: + + ```ts + const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token }); + for await (const page of pageStream) { + // Handle page of entities + for (const entity of page) { + console.log(entity); + } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + ## 1.18.1-next.0 ### Patch Changes diff --git a/plugins/catalog-node/package.json b/plugins/catalog-node/package.json index a61c4b801b..3111765897 100644 --- a/plugins/catalog-node/package.json +++ b/plugins/catalog-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-node", - "version": "1.18.1-next.0", + "version": "1.19.0-next.1", "description": "The plugin-catalog-node module for @backstage/plugin-catalog-backend", "backstage": { "role": "node-library", diff --git a/plugins/catalog-react/CHANGELOG.md b/plugins/catalog-react/CHANGELOG.md index d6eb0dc5fe..7ab8dcd967 100644 --- a/plugins/catalog-react/CHANGELOG.md +++ b/plugins/catalog-react/CHANGELOG.md @@ -1,5 +1,35 @@ # @backstage/plugin-catalog-react +## 1.21.0-next.2 + +### Minor Changes + +- 0e9ec44: Introduced new `streamEntities` async generator method for the catalog. + + Catalog API and Catalog Service now includes a `streamEntities` method that allows for streaming entities from the catalog. + This method is designed to handle large datasets efficiently by processing entities in a stream rather than loading them + all into memory at once. This is useful when you need to fetch a large number of entities but do not want to use pagination + or fetch all entities at once. + + Example usage: + + ```ts + const pageStream = catalogClient.streamEntities({ pageSize: 100 }, { token }); + for await (const page of pageStream) { + // Handle page of entities + for (const entity of page) { + console.log(entity); + } + } + ``` + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + ## 1.20.2-next.1 ### Patch Changes diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index 3912d9ce9d..0b072f51ce 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-react", - "version": "1.20.2-next.1", + "version": "1.21.0-next.2", "description": "A frontend library that helps other Backstage plugins interact with the catalog", "backstage": { "role": "web-library", diff --git a/plugins/catalog/CHANGELOG.md b/plugins/catalog/CHANGELOG.md index 19c35e2137..cddfdf18bc 100644 --- a/plugins/catalog/CHANGELOG.md +++ b/plugins/catalog/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-catalog +## 1.31.3-next.2 + +### Patch Changes + +- 85c5e04: Fix incorrect `defaultTarget` on `createComponentRouteRef`. +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + ## 1.31.3-next.1 ### Patch Changes diff --git a/plugins/catalog/package.json b/plugins/catalog/package.json index 9e1b0fcc05..fd0c1c4375 100644 --- a/plugins/catalog/package.json +++ b/plugins/catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog", - "version": "1.31.3-next.1", + "version": "1.31.3-next.2", "description": "The Backstage plugin for browsing the Backstage catalog", "backstage": { "role": "frontend-plugin", diff --git a/plugins/catalog/src/routes.ts b/plugins/catalog/src/routes.ts index 4f7f0427b1..6043ecd1a1 100644 --- a/plugins/catalog/src/routes.ts +++ b/plugins/catalog/src/routes.ts @@ -22,7 +22,7 @@ import { export const createComponentRouteRef = createExternalRouteRef({ id: 'create-component', optional: true, - defaultTarget: 'scaffolder.createComponent', + defaultTarget: 'scaffolder.root', }); export const viewTechDocRouteRef = createExternalRouteRef({ diff --git a/plugins/devtools-backend/CHANGELOG.md b/plugins/devtools-backend/CHANGELOG.md index 4da746e10a..dbd27d37d9 100644 --- a/plugins/devtools-backend/CHANGELOG.md +++ b/plugins/devtools-backend/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-devtools-backend +## 0.5.9-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/config-loader@1.10.3-next.0 + - @backstage/backend-defaults@0.12.1-next.1 + ## 0.5.9-next.0 ### Patch Changes diff --git a/plugins/devtools-backend/package.json b/plugins/devtools-backend/package.json index 038fcbce82..5bd90bdd41 100644 --- a/plugins/devtools-backend/package.json +++ b/plugins/devtools-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-devtools-backend", - "version": "0.5.9-next.0", + "version": "0.5.9-next.1", "backstage": { "role": "backend-plugin", "pluginId": "devtools", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index ea7326d9b3..1d2709648f 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-home +## 0.8.12-next.2 + +### Patch Changes + +- 929c55a: Fixed race condition in CustomHomepageGrid by waiting for storage to load before rendering custom layout to prevent + rendering of the default content. +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + ## 0.8.12-next.1 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 21469df7cd..bc8d71d23b 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-home", - "version": "0.8.12-next.1", + "version": "0.8.12-next.2", "description": "A Backstage plugin that helps you build a home page", "backstage": { "role": "frontend-plugin", diff --git a/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx b/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx index 5d85e834e8..fec7895170 100644 --- a/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx +++ b/plugins/home/src/components/CustomHomepage/CustomHomepageGrid.tsx @@ -34,7 +34,11 @@ import { } from '@material-ui/core/styles'; import { compact } from 'lodash'; import useObservable from 'react-use/esm/useObservable'; -import { ContentHeader, ErrorBoundary } from '@backstage/core-components'; +import { + ContentHeader, + ErrorBoundary, + Progress, +} from '@backstage/core-components'; import Typography from '@material-ui/core/Typography'; import { WidgetSettingsOverlay } from './WidgetSettingsOverlay'; import { AddWidgetDialog } from './AddWidgetDialog'; @@ -90,7 +94,7 @@ const useStyles = makeStyles((theme: Theme) => function useHomeStorage( defaultWidgets: GridWidget[], -): [GridWidget[], (value: GridWidget[]) => void] { +): [GridWidget[], (value: GridWidget[]) => void, boolean] { const key = 'home'; const storageApi = useApi(storageApiRef).forBucket('home.customHomepage'); // TODO: Support multiple home pages @@ -110,6 +114,9 @@ function useHomeStorage( storageApi.observe$(key), storageApi.snapshot(key), ); + + const isStorageLoading = homeSnapshot.presence === 'unknown' || !homeSnapshot; + const widgets: GridWidget[] = useMemo(() => { if (homeSnapshot.presence === 'absent') { return defaultWidgets; @@ -122,7 +129,7 @@ function useHomeStorage( } }, [homeSnapshot, defaultWidgets]); - return [widgets, setWidgets]; + return [widgets, setWidgets, isStorageLoading]; } const convertConfigToDefaultWidgets = ( @@ -213,7 +220,7 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => { ? convertConfigToDefaultWidgets(props.config, availableWidgets) : []; }, [props.config, availableWidgets]); - const [widgets, setWidgets] = useHomeStorage(defaultLayout); + const [widgets, setWidgets, isStorageLoading] = useHomeStorage(defaultLayout); const [addWidgetDialogOpen, setAddWidgetDialogOpen] = useState(false); const editModeOn = widgets.find(w => w.layout.isResizable) !== undefined; const [editMode, setEditMode] = useState(editModeOn); @@ -322,6 +329,10 @@ export const CustomHomepageGrid = (props: CustomHomepageGridProps) => { ); }; + if (isStorageLoading) { + return ; + } + return ( <> diff --git a/plugins/kubernetes-backend/CHANGELOG.md b/plugins/kubernetes-backend/CHANGELOG.md index 761e87e5e0..0986e613f8 100644 --- a/plugins/kubernetes-backend/CHANGELOG.md +++ b/plugins/kubernetes-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-kubernetes-backend +## 0.20.2-next.2 + +### Patch Changes + +- dd7b6d2: Fix a bug where `getDefault` in the `kubernetesFetcherExtensionPoint` had the wrong `this` value +- Updated dependencies + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration-aws-node@0.1.17 + ## 0.20.2-next.1 ### Patch Changes diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json index bae94407b5..15722c373d 100644 --- a/plugins/kubernetes-backend/package.json +++ b/plugins/kubernetes-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-backend", - "version": "0.20.2-next.1", + "version": "0.20.2-next.2", "description": "A Backstage backend plugin that integrates towards Kubernetes", "backstage": { "role": "backend-plugin", diff --git a/plugins/kubernetes-backend/src/service/KubernetesInitializer.ts b/plugins/kubernetes-backend/src/service/KubernetesInitializer.ts index c32023235f..1b0b9a31e1 100644 --- a/plugins/kubernetes-backend/src/service/KubernetesInitializer.ts +++ b/plugins/kubernetes-backend/src/service/KubernetesInitializer.ts @@ -183,8 +183,9 @@ export class KubernetesInitializer { async init() { const fetcher = - (await this.opts.fetcher?.({ getDefault: this.defaultFetcher })) ?? - (await this.defaultFetcher()); + (await this.opts.fetcher?.({ + getDefault: () => this.defaultFetcher(), + })) ?? (await this.defaultFetcher()); const authStrategyMap = this.opts.authStrategyMap ?? (await this.defaultAuthStrategy()); diff --git a/plugins/kubernetes-cluster/CHANGELOG.md b/plugins/kubernetes-cluster/CHANGELOG.md index 63ee864a46..af3a23232d 100644 --- a/plugins/kubernetes-cluster/CHANGELOG.md +++ b/plugins/kubernetes-cluster/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-kubernetes-cluster +## 0.0.29-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + ## 0.0.29-next.1 ### Patch Changes diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index 6488b959f6..0f9ab60401 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-cluster", - "version": "0.0.29-next.1", + "version": "0.0.29-next.2", "description": "A Backstage plugin that shows details of Kubernetes clusters", "backstage": { "role": "frontend-plugin", diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 6f76f6bc2a..5a1643287e 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-kubernetes +## 0.12.11-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + ## 0.12.11-next.1 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 3fd141319c..d0b553a4eb 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes", - "version": "0.12.11-next.1", + "version": "0.12.11-next.2", "description": "A Backstage plugin that integrates towards Kubernetes", "backstage": { "role": "frontend-plugin", diff --git a/plugins/mcp-actions-backend/CHANGELOG.md b/plugins/mcp-actions-backend/CHANGELOG.md index 0ca964fbd1..e7578dff07 100644 --- a/plugins/mcp-actions-backend/CHANGELOG.md +++ b/plugins/mcp-actions-backend/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-mcp-actions-backend +## 0.1.3-next.1 + +### Patch Changes + +- 1d47bf3: Proxy `/.well-known/oauth-authorization-server` to `/.well-known/openid-configuration` on `auth-backend` when `auth.experimentalDynamicClientRegistration.enabled` is enabled. +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.1.3-next.0 ### Patch Changes diff --git a/plugins/mcp-actions-backend/package.json b/plugins/mcp-actions-backend/package.json index 2a7fbdf8a3..4ed2250925 100644 --- a/plugins/mcp-actions-backend/package.json +++ b/plugins/mcp-actions-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-mcp-actions-backend", - "version": "0.1.3-next.0", + "version": "0.1.3-next.1", "backstage": { "role": "backend-plugin", "pluginId": "mcp-actions", diff --git a/plugins/mcp-actions-backend/src/plugin.ts b/plugins/mcp-actions-backend/src/plugin.ts index f1e89417e9..d04df6cdf5 100644 --- a/plugins/mcp-actions-backend/src/plugin.ts +++ b/plugins/mcp-actions-backend/src/plugin.ts @@ -17,7 +17,8 @@ import { coreServices, createBackendPlugin, } from '@backstage/backend-plugin-api'; -import { json, Router } from 'express'; +import { json } from 'express'; +import Router from 'express-promise-router'; import { McpService } from './services/McpService'; import { createStreamableRouter } from './routers/createStreamableRouter'; import { createSseRouter } from './routers/createSseRouter'; @@ -42,8 +43,19 @@ export const mcpPlugin = createBackendPlugin({ httpRouter: coreServices.httpRouter, actions: actionsServiceRef, registry: actionsRegistryServiceRef, + rootRouter: coreServices.rootHttpRouter, + discovery: coreServices.discovery, + config: coreServices.rootConfig, }, - async init({ actions, logger, httpRouter, httpAuth }) { + async init({ + actions, + logger, + httpRouter, + httpAuth, + rootRouter, + discovery, + config, + }) { const mcpService = await McpService.create({ actions, }); @@ -66,6 +78,26 @@ export const mcpPlugin = createBackendPlugin({ router.use('/v1', streamableRouter); httpRouter.use(router); + + if ( + config.getOptionalBoolean( + 'auth.experimentalDynamicClientRegistration.enabled', + ) + ) { + // This should be replaced with throwing a WWW-Authenticate header, but that doesn't seem to be supported by + // many of the MCP client as of yet. So this seems to be the oldest version of the spec thats implemented. + rootRouter.use( + '/.well-known/oauth-authorization-server', + async (_, res) => { + const authBaseUrl = await discovery.getBaseUrl('auth'); + const oidcResponse = await fetch( + `${authBaseUrl}/.well-known/openid-configuration`, + ); + + res.json(await oidcResponse.json()); + }, + ); + } }, }); }, diff --git a/plugins/notifications-backend-module-email/CHANGELOG.md b/plugins/notifications-backend-module-email/CHANGELOG.md index 9a46dad0bc..8619edd6f4 100644 --- a/plugins/notifications-backend-module-email/CHANGELOG.md +++ b/plugins/notifications-backend-module-email/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-notifications-backend-module-email +## 0.3.13-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration-aws-node@0.1.17 + - @backstage/plugin-notifications-node@0.2.19-next.1 + ## 0.3.13-next.0 ### Patch Changes diff --git a/plugins/notifications-backend-module-email/package.json b/plugins/notifications-backend-module-email/package.json index 602edf0e66..6844a77d3c 100644 --- a/plugins/notifications-backend-module-email/package.json +++ b/plugins/notifications-backend-module-email/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend-module-email", - "version": "0.3.13-next.0", + "version": "0.3.13-next.1", "description": "The email backend module for the notifications plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/notifications-backend-module-slack/CHANGELOG.md b/plugins/notifications-backend-module-slack/CHANGELOG.md index e38e8f9d07..a9d8074e5f 100644 --- a/plugins/notifications-backend-module-slack/CHANGELOG.md +++ b/plugins/notifications-backend-module-slack/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-notifications-backend-module-slack +## 0.1.5-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/plugin-notifications-node@0.2.19-next.1 + ## 0.1.5-next.0 ### Patch Changes diff --git a/plugins/notifications-backend-module-slack/package.json b/plugins/notifications-backend-module-slack/package.json index 227201984b..6b32e1b31d 100644 --- a/plugins/notifications-backend-module-slack/package.json +++ b/plugins/notifications-backend-module-slack/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend-module-slack", - "version": "0.1.5-next.0", + "version": "0.1.5-next.1", "description": "The slack backend module for the notifications plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/notifications-backend/CHANGELOG.md b/plugins/notifications-backend/CHANGELOG.md index 41905ec918..3391980f44 100644 --- a/plugins/notifications-backend/CHANGELOG.md +++ b/plugins/notifications-backend/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-notifications-backend +## 0.5.10-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/plugin-notifications-node@0.2.19-next.1 + ## 0.5.10-next.0 ### Patch Changes diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index 94c42005c0..a7933b0fc8 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend", - "version": "0.5.10-next.0", + "version": "0.5.10-next.1", "backstage": { "role": "backend-plugin", "pluginId": "notifications", diff --git a/plugins/notifications-node/CHANGELOG.md b/plugins/notifications-node/CHANGELOG.md index af3c020fd3..77e35d0996 100644 --- a/plugins/notifications-node/CHANGELOG.md +++ b/plugins/notifications-node/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-notifications-node +## 0.2.19-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + ## 0.2.19-next.0 ### Patch Changes diff --git a/plugins/notifications-node/package.json b/plugins/notifications-node/package.json index c20cf4c820..234d9d342f 100644 --- a/plugins/notifications-node/package.json +++ b/plugins/notifications-node/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-node", - "version": "0.2.19-next.0", + "version": "0.2.19-next.1", "description": "Node.js library for the notifications plugin", "backstage": { "role": "node-library", diff --git a/plugins/notifications/src/alpha.tsx b/plugins/notifications/src/alpha.tsx index 6d32150c35..ca4be58209 100644 --- a/plugins/notifications/src/alpha.tsx +++ b/plugins/notifications/src/alpha.tsx @@ -23,6 +23,7 @@ import { } from '@backstage/frontend-plugin-api'; import { rootRouteRef } from './routes'; import { + compatWrapper, convertLegacyRouteRef, convertLegacyRouteRefs, } from '@backstage/core-compat-api'; @@ -33,9 +34,9 @@ const page = PageBlueprint.make({ path: '/notifications', routeRef: convertLegacyRouteRef(rootRouteRef), loader: () => - import('./components/NotificationsPage').then(m => ( - - )), + import('./components/NotificationsPage').then(m => + compatWrapper(), + ), }, }); diff --git a/plugins/org-react/CHANGELOG.md b/plugins/org-react/CHANGELOG.md index 410b9da982..6cf5609da0 100644 --- a/plugins/org-react/CHANGELOG.md +++ b/plugins/org-react/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-org-react +## 0.1.42-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + ## 0.1.42-next.1 ### Patch Changes diff --git a/plugins/org-react/package.json b/plugins/org-react/package.json index f8410a3f77..06c4135396 100644 --- a/plugins/org-react/package.json +++ b/plugins/org-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org-react", - "version": "0.1.42-next.1", + "version": "0.1.42-next.2", "backstage": { "role": "web-library", "pluginId": "org", diff --git a/plugins/org/CHANGELOG.md b/plugins/org/CHANGELOG.md index ee5def4fcf..9df2d654e3 100644 --- a/plugins/org/CHANGELOG.md +++ b/plugins/org/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-org +## 0.6.44-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + ## 0.6.44-next.1 ### Patch Changes diff --git a/plugins/org/package.json b/plugins/org/package.json index df5b58446c..96a4ab9e62 100644 --- a/plugins/org/package.json +++ b/plugins/org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-org", - "version": "0.6.44-next.1", + "version": "0.6.44-next.2", "description": "A Backstage plugin that helps you create entity pages for your organization", "backstage": { "role": "frontend-plugin", diff --git a/plugins/scaffolder-backend-module-github/CHANGELOG.md b/plugins/scaffolder-backend-module-github/CHANGELOG.md index 9e99278912..2c396607d5 100644 --- a/plugins/scaffolder-backend-module-github/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-github/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-scaffolder-backend-module-github +## 0.8.3-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + ## 0.8.3-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-github/package.json b/plugins/scaffolder-backend-module-github/package.json index 15dedf5ac8..2d28caf5c6 100644 --- a/plugins/scaffolder-backend-module-github/package.json +++ b/plugins/scaffolder-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-github", - "version": "0.8.3-next.0", + "version": "0.8.3-next.1", "description": "The github module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend/CHANGELOG.md b/plugins/scaffolder-backend/CHANGELOG.md index 5fbb8edcc2..305afa351c 100644 --- a/plugins/scaffolder-backend/CHANGELOG.md +++ b/plugins/scaffolder-backend/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-scaffolder-backend +## 2.2.1-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/plugin-auth-node@0.6.7-next.1 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/plugin-catalog-backend-module-scaffolder-entity-model@0.2.12-next.1 + - @backstage/plugin-scaffolder-backend-module-github@0.8.3-next.1 + ## 2.2.1-next.0 ### Patch Changes diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 6b2f9ef0cb..2e77b90177 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend", - "version": "2.2.1-next.0", + "version": "2.2.1-next.1", "description": "The Backstage backend plugin that helps you create new things", "backstage": { "role": "backend-plugin", diff --git a/plugins/scaffolder-backend/sample-templates/notifications-demo/template.yaml b/plugins/scaffolder-backend/sample-templates/notifications-demo/template.yaml index abd18b1d42..56a7e7f5c6 100644 --- a/plugins/scaffolder-backend/sample-templates/notifications-demo/template.yaml +++ b/plugins/scaffolder-backend/sample-templates/notifications-demo/template.yaml @@ -32,7 +32,7 @@ spec: title: Title type: string description: Notification title - description: + info: title: Description type: string description: Notification longer description @@ -67,7 +67,7 @@ spec: recipients: ${{ parameters.recipients }} entityRefs: ${{ parameters.entityRefs }} title: ${{ parameters.title }} - description: ${{ parameters.description }} + info: ${{ parameters.info }} link: ${{ parameters.link }} severity: ${{ parameters.severity }} topic: ${{ parameters.topic }} diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 467b590bed..4144c552fb 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -1385,34 +1385,24 @@ data: {"id":1,"taskId":"a-random-id","type":"completion","createdAt":"","body":{ expect.anything(), ); }); - it('disallows users from seeing tasks they do not own', async () => { - const { permissions, router, taskBroker } = await createTestRouter(); - jest - .spyOn(permissions, 'authorizeConditional') - .mockImplementationOnce(async () => [ - { - conditions: { - resourceType: 'scaffolder-task', - rule: 'IS_TASK_OWNER', - params: { createdBy: ['user'] }, - }, - pluginId: 'scaffolder', - resourceType: 'scaffolder-task', - result: AuthorizeResult.CONDITIONAL, + it('allows payloads up to 10MB', async () => { + const { unwrappedRouter } = await createTestRouter(); + const mockToken = mockCredentials.user.token(); + const mockTemplate = generateMockTemplate(); + + const response = await request(unwrappedRouter) + .post('/v2/dry-run') + .set('Authorization', `Bearer ${mockToken}`) + .send({ + template: mockTemplate, + values: { + requiredParameter1: 'A'.repeat(9 * 1024 * 1024), // ~9MB + requiredParameter2: 'required-value-2', }, - ]); - const response = await request(router).get( - `/v2/tasks?createdBy=not-user`, - ); - expect(taskBroker.list).toHaveBeenCalledWith({ - filters: { createdBy: ['not-user'], status: undefined }, - order: undefined, - pagination: { limit: undefined, offset: undefined }, - permissionFilters: { key: 'created_by', values: ['user'] }, - }); + directoryContents: [], + }); + expect(response.status).toBe(200); - expect(response.body.totalTasks).toBe(0); - expect(response.body.tasks).toEqual([]); }); }); diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 9315e8ccb2..8296a6003f 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -186,9 +186,12 @@ const readDuration = ( export async function createRouter( options: RouterOptions, ): Promise { - const router = await createOpenApiRouter(); - // Be generous in upload size to support a wide range of templates in dry-run mode. - router.use(express.json({ limit: '10MB' })); + const router = await createOpenApiRouter({ + middleware: [ + // Be generous in upload size to support a wide range of templates in dry-run mode. + express.json({ limit: '10MB' }), + ], + }); const { logger: parentLogger, diff --git a/plugins/scaffolder-react/CHANGELOG.md b/plugins/scaffolder-react/CHANGELOG.md index 78d40108f4..00c948a51b 100644 --- a/plugins/scaffolder-react/CHANGELOG.md +++ b/plugins/scaffolder-react/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-scaffolder-react +## 1.19.1-next.2 + +### Patch Changes + +- 58fc108: Fix scaffolder task log stream not having a minimum height +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + ## 1.19.1-next.1 ### Patch Changes diff --git a/plugins/scaffolder-react/package.json b/plugins/scaffolder-react/package.json index 1d8737db72..25c8ea0ec6 100644 --- a/plugins/scaffolder-react/package.json +++ b/plugins/scaffolder-react/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-react", - "version": "1.19.1-next.1", + "version": "1.19.1-next.2", "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder", "backstage": { "role": "web-library", diff --git a/plugins/scaffolder-react/src/next/components/TaskLogStream/TaskLogStream.tsx b/plugins/scaffolder-react/src/next/components/TaskLogStream/TaskLogStream.tsx index a0c4ce94cd..b88d96510e 100644 --- a/plugins/scaffolder-react/src/next/components/TaskLogStream/TaskLogStream.tsx +++ b/plugins/scaffolder-react/src/next/components/TaskLogStream/TaskLogStream.tsx @@ -21,6 +21,7 @@ const useStyles = makeStyles({ width: '100%', height: '100%', position: 'relative', + minHeight: 240, }, }); diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index bbb826965c..420938d6fd 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/plugin-scaffolder +## 1.34.1-next.2 + +### Patch Changes + +- 0d415ae: Render a TechDocs link on the Scaffolder Template List page when templates include either `backstage.io/techdocs-ref` or `backstage.io/techdocs-entity` annotations, using the shared `buildTechDocsURL` helper. Also adds tests to verify both annotations and optional `backstage.io/techdocs-entity-path` are respected. +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/plugin-scaffolder-react@1.19.1-next.2 + - @backstage/integration@1.18.0-next.0 + - @backstage/core-compat-api@0.5.2-next.2 + ## 1.34.1-next.1 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index bad13ef8d2..695afd2244 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "1.34.1-next.1", + "version": "1.34.1-next.2", "description": "The Backstage plugin that helps you create new things", "backstage": { "role": "frontend-plugin", @@ -72,6 +72,8 @@ "@backstage/plugin-permission-react": "workspace:^", "@backstage/plugin-scaffolder-common": "workspace:^", "@backstage/plugin-scaffolder-react": "workspace:^", + "@backstage/plugin-techdocs-common": "workspace:^", + "@backstage/plugin-techdocs-react": "workspace:^", "@backstage/types": "workspace:^", "@codemirror/language": "^6.0.0", "@codemirror/legacy-modes": "^6.1.0", @@ -109,6 +111,7 @@ "@backstage/dev-utils": "workspace:^", "@backstage/plugin-catalog": "workspace:^", "@backstage/plugin-permission-common": "workspace:^", + "@backstage/plugin-techdocs": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/dom": "^10.0.0", "@testing-library/jest-dom": "^6.0.0", diff --git a/plugins/scaffolder/src/alpha/components/TemplateListPage/TemplateListPage.test.tsx b/plugins/scaffolder/src/alpha/components/TemplateListPage/TemplateListPage.test.tsx index a16474a4cf..da544cb2c0 100644 --- a/plugins/scaffolder/src/alpha/components/TemplateListPage/TemplateListPage.test.tsx +++ b/plugins/scaffolder/src/alpha/components/TemplateListPage/TemplateListPage.test.tsx @@ -27,13 +27,19 @@ import { TestApiProvider, mockApis, } from '@backstage/test-utils'; -import { rootRouteRef } from '../../../routes'; +import { rootRouteRef, viewTechDocRouteRef } from '../../../routes'; import { TemplateListPage } from './TemplateListPage'; +import { + TECHDOCS_ANNOTATION, + TECHDOCS_EXTERNAL_ANNOTATION, + TECHDOCS_EXTERNAL_PATH_ANNOTATION, +} from '@backstage/plugin-techdocs-common'; const mountedRoutes = { mountedRoutes: { '/': rootRouteRef, '/catalog/:namespace/:kind/:name': entityRouteRef, + '/docs/:namespace/:kind/:name': viewTechDocRouteRef, }, }; @@ -51,6 +57,127 @@ describe('TemplateListPage', () => { ], }); + describe('TechDocs link rendering', () => { + it('shows TechDocs link when template has backstage.io/techdocs-ref', async () => { + const mockCatalogApiWithDocs = catalogApiMock({ + entities: [ + { + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: { + name: 'tmpl-a', + annotations: { [TECHDOCS_ANNOTATION]: 'dir:.' }, + }, + spec: { type: 'service' }, + }, + ], + }); + + const { findByText } = await renderInTestApp( + + + , + mountedRoutes, + ); + + expect(await findByText('View TechDocs')).toBeInTheDocument(); + }); + + it('shows TechDocs link when template has backstage.io/techdocs-entity', async () => { + const mockCatalogApiWithExternal = catalogApiMock({ + entities: [ + { + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: { + name: 'tmpl-b', + annotations: { + [TECHDOCS_EXTERNAL_ANNOTATION]: 'component:default/other', + }, + }, + spec: { type: 'service' }, + }, + ], + }); + + const { findByText } = await renderInTestApp( + + + , + mountedRoutes, + ); + + expect(await findByText('View TechDocs')).toBeInTheDocument(); + }); + + it('appends path when backstage.io/techdocs-entity-path is set', async () => { + const mockCatalogApiWithPath = catalogApiMock({ + entities: [ + { + apiVersion: 'scaffolder.backstage.io/v1beta3', + kind: 'Template', + metadata: { + name: 'tmpl-c', + annotations: { + [TECHDOCS_EXTERNAL_ANNOTATION]: 'component:default/other', + [TECHDOCS_EXTERNAL_PATH_ANNOTATION]: '/guides/start', + }, + }, + spec: { type: 'service' }, + }, + ], + }); + + const { findByText } = await renderInTestApp( + + + , + mountedRoutes, + ); + + const link = (await findByText('View TechDocs')).closest('a')!; + expect(link).toHaveAttribute( + 'href', + expect.stringMatching( + /\/docs\/default\/component\/other\/?(index\.html)?#?\/guides\/start|\/docs\/default\/component\/other\/guides\/start/, + ), + ); + }); + }); + it('should render the search bar for templates', async () => { const { getByPlaceholderText } = await renderInTestApp( { const additionalLinksForEntity = useCallback( (template: TemplateEntityV1beta3) => { - const { kind, namespace, name } = parseEntityRef( - stringifyEntityRef(template), - ); - return template.metadata.annotations?.['backstage.io/techdocs-ref'] && - viewTechDocsLink + if ( + !( + template.metadata.annotations?.[TECHDOCS_ANNOTATION] || + template.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION] + ) || + !viewTechDocsLink + ) { + return []; + } + + const url = buildTechDocsURL(template, viewTechDocsLink); + return url ? [ { icon: app.getSystemIcon('docs') ?? DocsIcon, text: t( 'templateListPage.additionalLinksForEntity.viewTechDocsTitle', ), - url: viewTechDocsLink({ kind, namespace, name }), + url, }, ] : []; diff --git a/plugins/search-backend-module-catalog/CHANGELOG.md b/plugins/search-backend-module-catalog/CHANGELOG.md index e9a56fa5f9..8f60690872 100644 --- a/plugins/search-backend-module-catalog/CHANGELOG.md +++ b/plugins/search-backend-module-catalog/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-search-backend-module-catalog +## 0.3.8-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.3.8-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-catalog/package.json b/plugins/search-backend-module-catalog/package.json index 9bcc2287ff..0ebd03caa6 100644 --- a/plugins/search-backend-module-catalog/package.json +++ b/plugins/search-backend-module-catalog/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-catalog", - "version": "0.3.8-next.0", + "version": "0.3.8-next.1", "description": "A module for the search backend that exports catalog modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search-backend-module-techdocs/CHANGELOG.md b/plugins/search-backend-module-techdocs/CHANGELOG.md index 1938883b9e..ead9c04a7b 100644 --- a/plugins/search-backend-module-techdocs/CHANGELOG.md +++ b/plugins/search-backend-module-techdocs/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-search-backend-module-techdocs +## 0.4.6-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + ## 0.4.6-next.0 ### Patch Changes diff --git a/plugins/search-backend-module-techdocs/package.json b/plugins/search-backend-module-techdocs/package.json index 1faffa2b90..d1b784a4d8 100644 --- a/plugins/search-backend-module-techdocs/package.json +++ b/plugins/search-backend-module-techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search-backend-module-techdocs", - "version": "0.4.6-next.0", + "version": "0.4.6-next.1", "description": "A module for the search backend that exports techdocs modules", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/search/CHANGELOG.md b/plugins/search/CHANGELOG.md index 8449247680..8e9ca88787 100644 --- a/plugins/search/CHANGELOG.md +++ b/plugins/search/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-search +## 1.4.30-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + ## 1.4.30-next.1 ### Patch Changes diff --git a/plugins/search/package.json b/plugins/search/package.json index 7600d61b86..b58993b65c 100644 --- a/plugins/search/package.json +++ b/plugins/search/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-search", - "version": "1.4.30-next.1", + "version": "1.4.30-next.2", "description": "The Backstage plugin that provides your backstage app with search", "backstage": { "role": "frontend-plugin", diff --git a/plugins/techdocs-addons-test-utils/CHANGELOG.md b/plugins/techdocs-addons-test-utils/CHANGELOG.md index a6b33f9837..714fd56c8f 100644 --- a/plugins/techdocs-addons-test-utils/CHANGELOG.md +++ b/plugins/techdocs-addons-test-utils/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-techdocs-addons-test-utils +## 1.0.53-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/plugin-catalog@1.31.3-next.2 + - @backstage/plugin-techdocs@1.14.2-next.2 + ## 1.0.53-next.1 ### Patch Changes diff --git a/plugins/techdocs-addons-test-utils/package.json b/plugins/techdocs-addons-test-utils/package.json index eebe45a88a..94fd865e02 100644 --- a/plugins/techdocs-addons-test-utils/package.json +++ b/plugins/techdocs-addons-test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-addons-test-utils", - "version": "1.0.53-next.1", + "version": "1.0.53-next.2", "backstage": { "role": "web-library", "pluginId": "techdocs-addons", diff --git a/plugins/techdocs-addons-test-utils/src/test-utils.tsx b/plugins/techdocs-addons-test-utils/src/test-utils.tsx index 91b85e7885..a7cb74cb93 100644 --- a/plugins/techdocs-addons-test-utils/src/test-utils.tsx +++ b/plugins/techdocs-addons-test-utils/src/test-utils.tsx @@ -39,10 +39,12 @@ import { } from '@backstage/plugin-techdocs-react'; import { TechDocsReaderPage, techdocsPlugin } from '@backstage/plugin-techdocs'; import { + catalogApiRef, EntityPresentationApi, entityPresentationApiRef, entityRouteRef, } from '@backstage/plugin-catalog-react'; +import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils'; import { searchApiRef } from '@backstage/plugin-search-react'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; @@ -235,8 +237,19 @@ export class TechDocsAddonTester { }), }; + const catalogApi = catalogApiMock({ + entities: [ + { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { namespace: 'default', name: 'docs' }, + }, + ], + }); + const apis: TechdocsAddonTesterApis = [ [fetchApiRef, fetchApi], + [catalogApiRef, catalogApi], [entityPresentationApiRef, entityPresentationApi], [discoveryApiRef, discoveryApi], [techdocsApiRef, techdocsApi], diff --git a/plugins/techdocs-backend/CHANGELOG.md b/plugins/techdocs-backend/CHANGELOG.md index 036ba4387c..98b42c0b84 100644 --- a/plugins/techdocs-backend/CHANGELOG.md +++ b/plugins/techdocs-backend/CHANGELOG.md @@ -1,5 +1,16 @@ # @backstage/plugin-techdocs-backend +## 2.1.0-next.1 + +### Patch Changes + +- Updated dependencies + - @backstage/backend-defaults@0.12.1-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-node@1.19.0-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/plugin-search-backend-module-techdocs@0.4.6-next.1 + ## 2.1.0-next.0 ### Minor Changes diff --git a/plugins/techdocs-backend/examples/documented-component/catalog-info.yaml b/plugins/techdocs-backend/examples/documented-component/catalog-info.yaml index 6b30213a60..5b90693e23 100644 --- a/plugins/techdocs-backend/examples/documented-component/catalog-info.yaml +++ b/plugins/techdocs-backend/examples/documented-component/catalog-info.yaml @@ -10,3 +10,17 @@ spec: type: service lifecycle: experimental owner: user:guest +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: techdocs-entity-documented-component + title: Example Entity Documented By TechDocs Entity Annotation + description: A Service with TechDocs documentation via the `backstage.io/techdocs-entity` annotation. + annotations: + backstage.io/techdocs-entity: component:default/documented-component + backstage.io/techdocs-entity-path: /inner-component-docs +spec: + type: service + lifecycle: experimental + owner: user:guest diff --git a/plugins/techdocs-backend/examples/documented-component/docs/inner-component-docs/index.md b/plugins/techdocs-backend/examples/documented-component/docs/inner-component-docs/index.md new file mode 100644 index 0000000000..8cb6498c55 --- /dev/null +++ b/plugins/techdocs-backend/examples/documented-component/docs/inner-component-docs/index.md @@ -0,0 +1,5 @@ +# Inner Component Docs + +This is a basic example of documentation within a larger suite of TechDocs that can be referenced by whatever entities necessary. It is intended as a showcase of the `backstage.io/techdocs-entity-path` annotation for linking to a "subpage" in TechDocs that are declared by another entity. + +Please review the [How-To Guides - Deep Linking Into TechDocs](../../../../../../docs/features/techdocs/how-to-guides.md#deep-linking-into-techdocs) section for more information and you can view the example usage on the "Example Entity Documented By TechDocs Entity Annotation" component in this [catalog-info.yaml](../../catalog-info.yaml) file. diff --git a/plugins/techdocs-backend/examples/documented-component/mkdocs.yml b/plugins/techdocs-backend/examples/documented-component/mkdocs.yml index 1a159a4d12..fd954225a3 100644 --- a/plugins/techdocs-backend/examples/documented-component/mkdocs.yml +++ b/plugins/techdocs-backend/examples/documented-component/mkdocs.yml @@ -7,6 +7,7 @@ nav: - Subpage: sub-page.md - 'Code Sample': code/code-sample.md - Extensions: extensions.md + - 'Inner Component Docs': inner-component-docs/index.md plugins: - techdocs-core diff --git a/plugins/techdocs-backend/package.json b/plugins/techdocs-backend/package.json index bc6bfd6175..fd1ed4cadf 100644 --- a/plugins/techdocs-backend/package.json +++ b/plugins/techdocs-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs-backend", - "version": "2.1.0-next.0", + "version": "2.1.0-next.1", "description": "The Backstage backend plugin that renders technical documentation for your components", "backstage": { "role": "backend-plugin", diff --git a/plugins/techdocs-react/src/helpers.ts b/plugins/techdocs-react/src/helpers.ts index e6daf99b26..aebb0b3e52 100644 --- a/plugins/techdocs-react/src/helpers.ts +++ b/plugins/techdocs-react/src/helpers.ts @@ -64,7 +64,7 @@ export function getEntityRootTechDocsPath(entity: Entity): string { /** * Build the TechDocs URL for the given entity. This helper should be used anywhere there - * is a link to an entities TechDocs. + * is a link to an entity's TechDocs. * * @public */ @@ -104,7 +104,7 @@ export const buildTechDocsURL = ( }); // Add on the external entity path to the url if one exists. This allows deep linking into another - // entities TechDocs. + // entity's TechDocs. const path = getEntityRootTechDocsPath(entity); return `${url}${path}`; diff --git a/plugins/techdocs/CHANGELOG.md b/plugins/techdocs/CHANGELOG.md index c4f6ed3cef..02593351ee 100644 --- a/plugins/techdocs/CHANGELOG.md +++ b/plugins/techdocs/CHANGELOG.md @@ -1,5 +1,17 @@ # @backstage/plugin-techdocs +## 1.14.2-next.2 + +### Patch Changes + +- Updated dependencies + - @backstage/plugin-auth-react@0.1.19-next.1 + - @backstage/catalog-client@1.12.0-next.0 + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/integration@1.18.0-next.0 + - @backstage/core-compat-api@0.5.2-next.2 + ## 1.14.2-next.1 ### Patch Changes diff --git a/plugins/techdocs/package.json b/plugins/techdocs/package.json index 7ecec3cd0a..7777133862 100644 --- a/plugins/techdocs/package.json +++ b/plugins/techdocs/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-techdocs", - "version": "1.14.2-next.1", + "version": "1.14.2-next.2", "description": "The Backstage plugin that renders technical documentation for your components", "backstage": { "role": "frontend-plugin", @@ -81,7 +81,7 @@ "@material-ui/lab": "4.0.0-alpha.61", "@material-ui/styles": "^4.10.0", "@microsoft/fetch-event-source": "^2.0.1", - "dompurify": "^3.0.0", + "dompurify": "^3.2.4", "git-url-parse": "^15.0.0", "jss": "~10.10.0", "lodash": "^4.17.21", diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx index 2af4915ef5..aea45a60fa 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.test.tsx @@ -18,6 +18,7 @@ import { ReactNode } from 'react'; import { scmIntegrationsApiRef } from '@backstage/integration-react'; import { + catalogApiRef, entityPresentationApiRef, entityRouteRef, } from '@backstage/plugin-catalog-react'; @@ -26,13 +27,15 @@ import { renderInTestApp, TestApiProvider, } from '@backstage/test-utils'; +import { catalogApiMock as catalogApiMockFactory } from '@backstage/plugin-catalog-react/testUtils'; import { techdocsApiRef, techdocsStorageApiRef } from '../../../api'; import { rootRouteRef, rootDocsRouteRef } from '../../../routes'; +import { TECHDOCS_EXTERNAL_ANNOTATION } from '@backstage/plugin-techdocs-common'; import { TechDocsReaderPage } from './TechDocsReaderPage'; -import { Route, useParams } from 'react-router-dom'; +import { Route, useNavigate, useParams } from 'react-router-dom'; import { TechDocsAddons } from '@backstage/plugin-techdocs-react'; import { ReportIssue } from '@backstage/plugin-techdocs-module-addons-contrib'; import { FlatRoutes } from '@backstage/core-app-api'; @@ -94,6 +97,8 @@ const entityPresentationApiMock: jest.Mocked< }), }; +const catalogApiMock = catalogApiMockFactory.mock(); + const fetchApiMock = { fetch: jest.fn().mockResolvedValue({ ok: true, @@ -114,6 +119,11 @@ jest.mock('@backstage/core-components', () => ({ Page: jest.fn(), })); +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useNavigate: jest.fn(), +})); + const configApi = mockApis.config({ data: { app: { baseUrl: 'http://localhost:3000' } }, }); @@ -129,6 +139,7 @@ const Wrapper = ({ children }: { children: ReactNode }) => { [techdocsApiRef, techdocsApiMock], [techdocsStorageApiRef, techdocsStorageApiMock], [entityPresentationApiRef, entityPresentationApiMock], + [catalogApiRef, catalogApiMock], ]} > {children} @@ -143,6 +154,8 @@ const mountedRoutes = { }; describe('', () => { + const mockNavigate = jest.fn(); + beforeEach(() => { getEntityMetadata.mockResolvedValue(mockEntityMetadata); getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); @@ -150,6 +163,8 @@ describe('', () => { // Expires in 10 minutes expiresAt: new Date(Date.now() + 10 * 60 * 1000).toISOString(), }); + + (useNavigate as jest.Mock).mockReturnValue(mockNavigate); }); afterEach(() => { @@ -285,4 +300,142 @@ describe('', () => { expect(text).toHaveStyle('fontFamily: Comic Sans MS'); }); + + describe('external TechDocs redirect', () => { + beforeEach(() => { + mockNavigate.mockClear(); + catalogApiMock.getEntityByRef.mockReset(); + catalogApiMock.getEntityByRef.mockResolvedValue(mockEntityMetadata); + }); + + it('should navigate to external URL when entity has external techdocs annotation', async () => { + const mockEntityWithExternalAnnotation = { + ...mockEntityMetadata, + metadata: { + ...mockEntityMetadata.metadata, + annotations: { + [TECHDOCS_EXTERNAL_ANNOTATION]: + 'component:external-namespace/external-docs', + }, + }, + }; + + catalogApiMock.getEntityByRef.mockResolvedValue( + mockEntityWithExternalAnnotation, + ); + + await renderInTestApp( + + + , + { + mountedRoutes, + }, + ); + + expect(mockNavigate).toHaveBeenCalledWith( + '/docs/external-namespace/component/external-docs', + { replace: true }, + ); + }); + + it('should render normally when entity has no external techdocs annotation', async () => { + const mockEntityWithoutExternalAnnotation = { + ...mockEntityMetadata, + metadata: { + ...mockEntityMetadata.metadata, + annotations: undefined, + }, + }; + + catalogApiMock.getEntityByRef.mockResolvedValue( + mockEntityWithoutExternalAnnotation, + ); + + const rendered = await renderInTestApp( + + + , + { + mountedRoutes, + }, + ); + + expect(rendered.container.querySelector('header')).toBeInTheDocument(); + expect(rendered.container.querySelector('article')).toBeInTheDocument(); + expect(mockNavigate).not.toHaveBeenCalled(); + }); + + it('should render normally when entity has external annotation but no value', async () => { + const mockEntityWithEmptyExternalAnnotation = { + ...mockEntityMetadata, + metadata: { + ...mockEntityMetadata.metadata, + annotations: { + [TECHDOCS_EXTERNAL_ANNOTATION]: '', + }, + }, + }; + + catalogApiMock.getEntityByRef.mockResolvedValue( + mockEntityWithEmptyExternalAnnotation, + ); + + const rendered = await renderInTestApp( + + + , + { + mountedRoutes, + }, + ); + + expect(rendered.container.querySelector('header')).toBeInTheDocument(); + expect(rendered.container.querySelector('article')).toBeInTheDocument(); + expect(mockNavigate).not.toHaveBeenCalled(); + }); + + it('should render normally when catalog API throws an error', async () => { + catalogApiMock.getEntityByRef.mockRejectedValue( + new Error('Catalog API error'), + ); + + const rendered = await renderInTestApp( + + + , + { + mountedRoutes, + }, + ); + + expect(rendered.container.querySelector('header')).toBeInTheDocument(); + expect(rendered.container.querySelector('article')).toBeInTheDocument(); + expect(mockNavigate).not.toHaveBeenCalled(); + }); + }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx index 80545151d9..c67660fd79 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx @@ -14,19 +14,26 @@ * limitations under the License. */ -import { Children, ReactElement, ReactNode } from 'react'; -import { useOutlet } from 'react-router-dom'; - +import { + Children, + ReactElement, + ReactNode, + useEffect, + useMemo, + useCallback, +} from 'react'; +import { useOutlet, useNavigate } from 'react-router-dom'; import { Page } from '@backstage/core-components'; import { CompoundEntityRef } from '@backstage/catalog-model'; import { TECHDOCS_ADDONS_KEY, TECHDOCS_ADDONS_WRAPPER_KEY, TechDocsReaderPageProvider, + buildTechDocsURL, } from '@backstage/plugin-techdocs-react'; - +import { TECHDOCS_EXTERNAL_ANNOTATION } from '@backstage/plugin-techdocs-common'; +import useAsync from 'react-use/esm/useAsync'; import { TechDocsReaderPageRenderFunction } from '../../../types'; - import { TechDocsReaderPageContent } from '../TechDocsReaderPageContent'; import { TechDocsReaderPageHeader } from '../TechDocsReaderPageHeader'; import { TechDocsReaderPageSubheader } from '../TechDocsReaderPageSubheader'; @@ -34,9 +41,11 @@ import { rootDocsRouteRef } from '../../../routes'; import { getComponentData, useRouteRefParams, + useApi, + useRouteRef, } from '@backstage/core-plugin-api'; - import { CookieAuthRefreshProvider } from '@backstage/plugin-auth-react'; +import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { createTheme, styled, @@ -44,6 +53,7 @@ import { ThemeProvider, useTheme, } from '@material-ui/core/styles'; +import { Progress } from '@backstage/core-components'; /* An explanation for the multiple ways of customizing the TechDocs reader page @@ -177,44 +187,106 @@ const StyledPage = styled(Page)({ export const TechDocsReaderPage = (props: TechDocsReaderPageProps) => { const currentTheme = useTheme(); - const readerPageTheme = createTheme({ - ...currentTheme, - ...(props.overrideThemeOptions || {}), - }); + const readerPageTheme = useMemo( + () => + createTheme({ + ...currentTheme, + ...(props.overrideThemeOptions || {}), + }), + [currentTheme, props.overrideThemeOptions], + ); + const { kind, name, namespace } = useRouteRefParams(rootDocsRouteRef); const { children, entityRef = { kind, name, namespace } } = props; const outlet = useOutlet(); - if (!children) { + const catalogApi = useApi(catalogApiRef); + const navigate = useNavigate(); + const viewTechdocLink = useRouteRef(rootDocsRouteRef); + + const memoizedEntityRef = useMemo( + () => ({ + kind: entityRef.kind, + name: entityRef.name, + namespace: entityRef.namespace, + }), + [entityRef.kind, entityRef.name, entityRef.namespace], + ); + + const externalEntityTechDocsUrl = useAsync(async () => { + try { + const catalogEntity = await catalogApi.getEntityByRef(memoizedEntityRef); + + if ( + catalogEntity?.metadata?.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION] + ) { + return buildTechDocsURL(catalogEntity, viewTechdocLink); + } + } catch (error) { + // Ignore error and allow an attempt at loading the current entity's TechDocs when unable to fetch an external entity from the catalog. + } + + return undefined; + }, [memoizedEntityRef, catalogApi, viewTechdocLink]); + + const handleNavigation = useCallback( + (url: string) => { + navigate(url, { replace: true }); + }, + [navigate], + ); + + useEffect(() => { + if (!externalEntityTechDocsUrl.loading && externalEntityTechDocsUrl.value) { + handleNavigation(externalEntityTechDocsUrl.value); + } + }, [ + externalEntityTechDocsUrl.loading, + externalEntityTechDocsUrl.value, + handleNavigation, + ]); + + const page: ReactNode = useMemo(() => { + if (children) { + return null; + } + const childrenList = outlet ? Children.toArray(outlet.props.children) : []; const grandChildren = childrenList.flatMap( child => (child as ReactElement)?.props?.children ?? [], ); - const page: ReactNode = grandChildren.find( + return grandChildren.find( grandChild => !getComponentData(grandChild, TECHDOCS_ADDONS_WRAPPER_KEY) && !getComponentData(grandChild, TECHDOCS_ADDONS_KEY), ); + }, [children, outlet]); - // As explained above, "page" is configuration 4 and is 1 + if (externalEntityTechDocsUrl.loading || externalEntityTechDocsUrl.value) { + return ; + } + + // As explained above, "page" is configuration 4 and is 1 + if (!children) { return ( - + {(page as JSX.Element) || } ); } + // As explained above, a render function is configuration 3 and React element is 2 return ( - + {({ metadata, entityMetadata, onReady }) => ( { > {children instanceof Function ? children({ - entityRef, + entityRef: memoizedEntityRef, techdocsMetadataValue: metadata.value, entityMetadataValue: entityMetadata.value, onReady, diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx index 6f6ee81c8b..3c10b26f7f 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.test.tsx @@ -52,13 +52,11 @@ const mockTechDocsMetadata = { site_description: 'test-site-desc', }; -const mockUseParams = jest.fn(); -mockUseParams.mockReturnValue({ '*': 'foo/bar/baz/' }); - +let useParamsPath = '/'; jest.mock('react-router-dom', () => { return { ...(jest.requireActual('react-router-dom') as any), - useParams: () => mockUseParams(), + useParams: () => ({ '*': useParamsPath }), }; }); @@ -189,6 +187,7 @@ describe('', () => { getEntityMetadata.mockResolvedValue(mockEntityMetadata); getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); + useParamsPath = 'foo/bar/baz/'; await renderInTestApp( @@ -203,7 +202,31 @@ describe('', () => { await waitFor(() => { expect(document.title).toEqual( - 'Backstage | Test Entity | Foo | Bar | Baz', + 'Test Entity | Foo | Bar | Baz | Backstage', + ); + }); + }); + + it('The header title is abbreviated if path is too long', async () => { + getEntityMetadata.mockResolvedValue(mockEntityMetadata); + getTechDocsMetadata.mockResolvedValue(mockTechDocsMetadata); + + useParamsPath = 'foo/bar/baz/qux/quux/'; + await renderInTestApp( + + + , + { + mountedRoutes: { + '/catalog/:namespace/:kind/:name/*': entityRouteRef, + '/docs': rootRouteRef, + }, + }, + ); + + await waitFor(() => { + expect(document.title).toEqual( + 'Test Entity | Foo | Bar | Baz | Qux | Quux | Backstage', ); }); }); diff --git a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx index bafcdd270c..6328becc73 100644 --- a/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx +++ b/plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx @@ -172,17 +172,16 @@ export const TechDocsReaderPageHeader = ( const removeTrailingSlash = (str: string) => str.replace(/\/$/, ''); const normalizeAndSpace = (str: string) => - str.replace(/-/g, ' ').split(' ').map(capitalize).join(' '); + str.replace(/[-_]/g, ' ').split(' ').map(capitalize).join(' '); let techdocsTabTitleItems: string[] = []; if (path !== '') techdocsTabTitleItems = removeTrailingSlash(path) .split('/') - .slice(0, 3) .map(normalizeAndSpace); - const tabTitleItems = [appTitle, entityDisplayName, ...techdocsTabTitleItems]; + const tabTitleItems = [entityDisplayName, ...techdocsTabTitleItems, appTitle]; const tabTitle = tabTitleItems.join(' | '); return ( diff --git a/plugins/techdocs/src/reader/transformers/html/hooks/attributes.ts b/plugins/techdocs/src/reader/transformers/html/hooks/attributes.ts new file mode 100644 index 0000000000..ae0b4e2ce9 --- /dev/null +++ b/plugins/techdocs/src/reader/transformers/html/hooks/attributes.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 { UponSanitizeAttributeHook } from 'dompurify'; + +/** + * Removes attributes that should only be present on meta tags from other elements. + * This ensures that http-equiv and content attributes are only allowed on meta tags + * where they are required for the redirect feature. + */ +export const removeRestrictedAttributes: UponSanitizeAttributeHook = ( + node, + data, +) => { + if (node.tagName !== 'META') { + if (data.attrName === 'http-equiv' || data.attrName === 'content') { + node.removeAttribute(data.attrName); + } + } +}; diff --git a/plugins/techdocs/src/reader/transformers/html/hooks/iframes.ts b/plugins/techdocs/src/reader/transformers/html/hooks/iframes.ts index 25259dbc43..23711b52b7 100644 --- a/plugins/techdocs/src/reader/transformers/html/hooks/iframes.ts +++ b/plugins/techdocs/src/reader/transformers/html/hooks/iframes.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { isElement } from '../utils'; + /** * Checks whether a node is iframe or not. * @param node - can be any element. @@ -42,9 +44,10 @@ const isSafe = (node: Element, hosts: string[]) => { * @param node - can be any element. * @param hosts - list of allowed hosts. */ -export const removeUnsafeIframes = (hosts: string[]) => (node: Element) => { +export const removeUnsafeIframes = (hosts: string[]) => (node: Node) => { + if (!isElement(node)) return; + if (isIframe(node) && !isSafe(node, hosts)) { node.remove(); } - return node; }; diff --git a/plugins/techdocs/src/reader/transformers/html/hooks/index.ts b/plugins/techdocs/src/reader/transformers/html/hooks/index.ts index a4356db2e9..ce237ec6d2 100644 --- a/plugins/techdocs/src/reader/transformers/html/hooks/index.ts +++ b/plugins/techdocs/src/reader/transformers/html/hooks/index.ts @@ -16,3 +16,5 @@ export { removeUnsafeLinks } from './links'; export { removeUnsafeIframes } from './iframes'; +export { removeUnsafeMetaTags } from './metatags'; +export { removeRestrictedAttributes } from './attributes'; diff --git a/plugins/techdocs/src/reader/transformers/html/hooks/links.ts b/plugins/techdocs/src/reader/transformers/html/hooks/links.ts index 38f775cfbe..eb2cbfc6de 100644 --- a/plugins/techdocs/src/reader/transformers/html/hooks/links.ts +++ b/plugins/techdocs/src/reader/transformers/html/hooks/links.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { isElement } from '../utils'; + const MKDOCS_CSS = /main\.[A-Fa-f0-9]{8}\.min\.css$/; const GOOGLE_FONTS = /^https:\/\/fonts\.googleapis\.com/; const GSTATIC_FONTS = /^https:\/\/fonts\.gstatic\.com/; @@ -41,11 +43,11 @@ const isSafe = (node: Element) => { /** * Function that removes unsafe link nodes. * @param node - can be any element. - * @param hosts - list of allowed hosts. */ -export const removeUnsafeLinks = (node: Element) => { +export const removeUnsafeLinks = (node: Node) => { + if (!isElement(node)) return; + if (isLink(node) && !isSafe(node)) { node.remove(); } - return node; }; diff --git a/plugins/techdocs/src/reader/transformers/html/hooks/metatags.ts b/plugins/techdocs/src/reader/transformers/html/hooks/metatags.ts new file mode 100644 index 0000000000..a207a5bca2 --- /dev/null +++ b/plugins/techdocs/src/reader/transformers/html/hooks/metatags.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 { UponSanitizeElementHook } from 'dompurify'; +import { isElement } from '../utils'; + +/** + * Checks if a meta tag is a refresh redirect tag that should be allowed. + * These tags are required for the TechDocs redirect feature. + */ +const isAllowedMetaRefreshTag = (element: Element): boolean => { + const httpEquiv = element.getAttribute('http-equiv'); + const content = element.getAttribute('content'); + + return httpEquiv === 'refresh' && content?.includes('url=') === true; +}; + +/** + * Removes unsafe meta tags from the DOM while preserving allowed refresh redirect tags. + * Only meta tags used for page refreshing/redirects are allowed as they are required + * for the TechDocs redirect feature. + */ +export const removeUnsafeMetaTags: UponSanitizeElementHook = (node, data) => { + if (!isElement(node)) return; + + if (data.tagName === 'meta' && !isAllowedMetaRefreshTag(node)) { + node.parentNode?.removeChild(node); + } +}; diff --git a/plugins/techdocs/src/reader/transformers/html/transformer.ts b/plugins/techdocs/src/reader/transformers/html/transformer.ts index 7c341c783e..6ebf53f26e 100644 --- a/plugins/techdocs/src/reader/transformers/html/transformer.ts +++ b/plugins/techdocs/src/reader/transformers/html/transformer.ts @@ -20,7 +20,12 @@ import { useCallback, useMemo } from 'react'; import { configApiRef, useApi } from '@backstage/core-plugin-api'; import { Transformer } from '../transformer'; -import { removeUnsafeIframes, removeUnsafeLinks } from './hooks'; +import { + removeRestrictedAttributes, + removeUnsafeIframes, + removeUnsafeLinks, + removeUnsafeMetaTags, +} from './hooks'; /** * Returns html sanitizer configuration @@ -51,26 +56,9 @@ export const useSanitizerTransformer = (): Transformer => { DOMPurify.addHook('beforeSanitizeElements', removeUnsafeIframes(hosts)); } - // Only allow meta tags if they are used for refreshing the page. They are required for the redirect feature. - DOMPurify.addHook('uponSanitizeElement', (currNode, data) => { - if (data.tagName === 'meta') { - const isMetaRefreshTag = - currNode.getAttribute('http-equiv') === 'refresh' && - currNode.getAttribute('content')?.includes('url='); - if (!isMetaRefreshTag) { - currNode.parentNode?.removeChild(currNode); - } - } - }); + DOMPurify.addHook('uponSanitizeElement', removeUnsafeMetaTags); - // Only allow http-equiv and content attributes on meta tags. They are required for the redirect feature. - DOMPurify.addHook('uponSanitizeAttribute', (currNode, data) => { - if (currNode.tagName !== 'meta') { - if (data.attrName === 'http-equiv' || data.attrName === 'content') { - currNode.removeAttribute(data.attrName); - } - } - }); + DOMPurify.addHook('uponSanitizeAttribute', removeRestrictedAttributes); const tagNameCheck = config?.getOptionalString( 'allowedCustomElementTagNameRegExp', @@ -122,7 +110,7 @@ export const useSanitizerTransformer = (): Transformer => { ? new RegExp(attributeNameCheck) : undefined, }, - }); + }) as Element; }, [config], ); diff --git a/plugins/techdocs/src/reader/transformers/html/utils.ts b/plugins/techdocs/src/reader/transformers/html/utils.ts new file mode 100644 index 0000000000..b97b63743c --- /dev/null +++ b/plugins/techdocs/src/reader/transformers/html/utils.ts @@ -0,0 +1,19 @@ +/* + * 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 const isElement = (node: Node): node is Element => { + return node.nodeType === Node.ELEMENT_NODE; +}; diff --git a/plugins/user-settings/CHANGELOG.md b/plugins/user-settings/CHANGELOG.md index 5d4f80079f..cfb4c0b712 100644 --- a/plugins/user-settings/CHANGELOG.md +++ b/plugins/user-settings/CHANGELOG.md @@ -1,5 +1,15 @@ # @backstage/plugin-user-settings +## 0.8.26-next.2 + +### Patch Changes + +- b713b54: Tool-tip text correction for the Theme selection in settings page +- Updated dependencies + - @backstage/plugin-catalog-react@1.21.0-next.2 + - @backstage/core-components@0.17.6-next.1 + - @backstage/core-compat-api@0.5.2-next.2 + ## 0.8.26-next.1 ### Patch Changes diff --git a/plugins/user-settings/package.json b/plugins/user-settings/package.json index d5224ac8b6..3ce96f9146 100644 --- a/plugins/user-settings/package.json +++ b/plugins/user-settings/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-user-settings", - "version": "0.8.26-next.1", + "version": "0.8.26-next.2", "description": "A Backstage plugin that provides a settings page", "backstage": { "role": "frontend-plugin", diff --git a/plugins/user-settings/report-alpha.api.md b/plugins/user-settings/report-alpha.api.md index 5a28aacc02..1c8e844d05 100644 --- a/plugins/user-settings/report-alpha.api.md +++ b/plugins/user-settings/report-alpha.api.md @@ -123,7 +123,7 @@ export const userSettingsTranslationRef: TranslationRef< readonly 'languageToggle.select': 'Select language {{language}}'; readonly 'languageToggle.title': 'Language'; readonly 'languageToggle.description': 'Change the language'; - readonly 'themeToggle.select': 'Select theme {{theme}}'; + readonly 'themeToggle.select': 'Select {{theme}}'; readonly 'themeToggle.title': 'Theme'; readonly 'themeToggle.description': 'Change the theme mode'; readonly 'themeToggle.names.auto': 'Auto'; diff --git a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx index b0ddbf31cf..ce9c1093ca 100644 --- a/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx +++ b/plugins/user-settings/src/components/AuthProviders/DefaultProviderSettings.tsx @@ -26,6 +26,7 @@ import { bitbucketServerAuthApiRef, atlassianAuthApiRef, oneloginAuthApiRef, + openshiftAuthApiRef, } from '@backstage/core-plugin-api'; import { userSettingsTranslationRef } from '../../translation'; import { useTranslationRef } from '@backstage/frontend-plugin-api'; @@ -128,6 +129,14 @@ export const DefaultProviderSettings = (props: { icon={Star} /> )} + {configuredProviders.includes('openshift') && ( + + )} ); }; diff --git a/plugins/user-settings/src/translation.ts b/plugins/user-settings/src/translation.ts index 0161508d14..7445a415f2 100644 --- a/plugins/user-settings/src/translation.ts +++ b/plugins/user-settings/src/translation.ts @@ -28,7 +28,7 @@ export const userSettingsTranslationRef = createTranslationRef({ themeToggle: { title: 'Theme', description: 'Change the theme mode', - select: 'Select theme {{theme}}', + select: 'Select {{theme}}', selectAuto: 'Select Auto Theme', names: { light: 'Light', diff --git a/yarn.lock b/yarn.lock index fde37ae4e3..462290b101 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3182,6 +3182,7 @@ __metadata: "@types/d3-selection": "npm:^3.0.1" "@types/d3-shape": "npm:^3.0.1" "@types/d3-zoom": "npm:^3.0.1" + "@types/fscreen": "npm:^1" "@types/google-protobuf": "npm:^3.7.2" "@types/react": "npm:^18.0.0" "@types/react-helmet": "npm:^6.1.0" @@ -3207,6 +3208,7 @@ __metadata: rc-progress: "npm:3.5.1" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" + react-full-screen: "npm:^1.1.1" react-helmet: "npm:6.1.0" react-hook-form: "npm:^7.12.2" react-idle-timer: "npm:5.7.2" @@ -4120,6 +4122,27 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-auth-backend-module-openshift-provider@workspace:^, @backstage/plugin-auth-backend-module-openshift-provider@workspace:plugins/auth-backend-module-openshift-provider": + version: 0.0.0-use.local + resolution: "@backstage/plugin-auth-backend-module-openshift-provider@workspace:plugins/auth-backend-module-openshift-provider" + dependencies: + "@backstage/backend-defaults": "workspace:^" + "@backstage/backend-plugin-api": "workspace:^" + "@backstage/backend-test-utils": "workspace:^" + "@backstage/catalog-model": "workspace:^" + "@backstage/cli": "workspace:^" + "@backstage/config": "workspace:^" + "@backstage/plugin-auth-backend": "workspace:^" + "@backstage/plugin-auth-node": "workspace:^" + "@backstage/types": "workspace:^" + express: "npm:^4.18.2" + msw: "npm:^2.7.3" + passport-oauth2: "npm:^1.8.0" + supertest: "npm:^7.1.0" + zod: "npm:^3.24.2" + languageName: unknown + linkType: soft + "@backstage/plugin-auth-backend-module-pinniped-provider@workspace:plugins/auth-backend-module-pinniped-provider": version: 0.0.0-use.local resolution: "@backstage/plugin-auth-backend-module-pinniped-provider@workspace:plugins/auth-backend-module-pinniped-provider" @@ -4196,6 +4219,7 @@ __metadata: knex: "npm:^3.0.0" lodash: "npm:^4.17.21" luxon: "npm:^3.0.0" + matcher: "npm:^4.0.0" minimatch: "npm:^9.0.0" passport: "npm:^0.7.0" supertest: "npm:^7.0.0" @@ -4263,6 +4287,41 @@ __metadata: languageName: unknown linkType: soft +"@backstage/plugin-auth@workspace:^, @backstage/plugin-auth@workspace:plugins/auth": + version: 0.0.0-use.local + resolution: "@backstage/plugin-auth@workspace:plugins/auth" + dependencies: + "@backstage/cli": "workspace:^" + "@backstage/core-components": "workspace:^" + "@backstage/dev-utils": "workspace:^" + "@backstage/errors": "workspace:^" + "@backstage/frontend-defaults": "workspace:^" + "@backstage/frontend-plugin-api": "workspace:^" + "@backstage/test-utils": "workspace:^" + "@backstage/theme": "workspace:^" + "@material-ui/core": "npm:^4.12.2" + "@material-ui/icons": "npm:^4.9.1" + "@material-ui/lab": "npm:4.0.0-alpha.61" + "@testing-library/jest-dom": "npm:^6.0.0" + "@testing-library/react": "npm:^16.0.0" + "@testing-library/user-event": "npm:^14.0.0" + "@types/react": "npm:^18.0.0" + msw: "npm:^1.0.0" + react: "npm:^18.0.2" + react-dom: "npm:^18.0.2" + react-router-dom: "npm:^6.3.0" + react-use: "npm:^17.2.4" + peerDependencies: + "@types/react": ^17.0.0 || ^18.0.0 + react: ^17.0.0 || ^18.0.0 + react-dom: ^17.0.0 || ^18.0.0 + react-router-dom: ^6.3.0 + peerDependenciesMeta: + "@types/react": + optional: true + languageName: unknown + linkType: soft + "@backstage/plugin-bitbucket-cloud-common@workspace:^, @backstage/plugin-bitbucket-cloud-common@workspace:plugins/bitbucket-cloud-common": version: 0.0.0-use.local resolution: "@backstage/plugin-bitbucket-cloud-common@workspace:plugins/bitbucket-cloud-common" @@ -6576,6 +6635,9 @@ __metadata: "@backstage/plugin-permission-react": "workspace:^" "@backstage/plugin-scaffolder-common": "workspace:^" "@backstage/plugin-scaffolder-react": "workspace:^" + "@backstage/plugin-techdocs": "workspace:^" + "@backstage/plugin-techdocs-common": "workspace:^" + "@backstage/plugin-techdocs-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/types": "workspace:^" "@codemirror/language": "npm:^6.0.0" @@ -7229,7 +7291,7 @@ __metadata: "@testing-library/user-event": "npm:^14.0.0" "@types/dompurify": "npm:^3.0.0" "@types/react": "npm:^18.0.0" - dompurify: "npm:^3.0.0" + dompurify: "npm:^3.2.4" git-url-parse: "npm:^15.0.0" jss: "npm:~10.10.0" lodash: "npm:^4.17.21" @@ -11083,9 +11145,9 @@ __metadata: languageName: node linkType: hard -"@mswjs/interceptors@npm:^0.39.1": - version: 0.39.2 - resolution: "@mswjs/interceptors@npm:0.39.2" +"@mswjs/interceptors@npm:^0.37.0": + version: 0.37.1 + resolution: "@mswjs/interceptors@npm:0.37.1" dependencies: "@open-draft/deferred-promise": "npm:^2.2.0" "@open-draft/logger": "npm:^0.3.0" @@ -11093,7 +11155,7 @@ __metadata: is-node-process: "npm:^1.2.0" outvariant: "npm:^1.4.3" strict-event-emitter: "npm:^0.5.1" - checksum: 10/faaa95d636363a197f125c32066457fa74d5063d8ccae4c9c0e0510179060d92b1faf8640df45a0623e0bf42a30d610c83364a58e0eb0ca412c87b2e835936c1 + checksum: 10/332d8aa50beb4834ccbda6a800ca00b1204adc0eba23e1c1f7bb9f4e564a92707e563f7a2424d4a8607404ec91424e5d8c34a87c250b191ca7b24dff12eba2c5 languageName: node linkType: hard @@ -20270,6 +20332,13 @@ __metadata: languageName: node linkType: hard +"@types/fscreen@npm:^1": + version: 1.0.4 + resolution: "@types/fscreen@npm:1.0.4" + checksum: 10/78459a457ce7a6b7d72a5f17fdb54bbeb93c58ab77fd2858aac610fed2435bc4be9e5d2fb9883b6669b7f3a1204115cc2be59a027ab937ee8b5186225d2ea53d + languageName: node + linkType: hard + "@types/git-url-parse@npm:^9.0.0": version: 9.0.3 resolution: "@types/git-url-parse@npm:9.0.3" @@ -21470,10 +21539,10 @@ __metadata: languageName: node linkType: hard -"@types/trusted-types@npm:*": - version: 2.0.3 - resolution: "@types/trusted-types@npm:2.0.3" - checksum: 10/4794804bc4a4a173d589841b6d26cf455ff5dc4f3e704e847de7d65d215f2e7043d8757e4741ce3a823af3f08260a8d04a1a6e9c5ec9b20b7b04586956a6b005 +"@types/trusted-types@npm:*, @types/trusted-types@npm:^2.0.7": + version: 2.0.7 + resolution: "@types/trusted-types@npm:2.0.7" + checksum: 10/8e4202766a65877efcf5d5a41b7dd458480b36195e580a3b1085ad21e948bc417d55d6f8af1fd2a7ad008015d4117d5fdfe432731157da3c68678487174e4ba3 languageName: node linkType: hard @@ -26267,7 +26336,7 @@ __metadata: languageName: node linkType: hard -"combined-stream@npm:^1.0.6, combined-stream@npm:^1.0.8": +"combined-stream@npm:^1.0.8": version: 1.0.8 resolution: "combined-stream@npm:1.0.8" dependencies: @@ -26395,10 +26464,10 @@ __metadata: languageName: node linkType: hard -"component-emitter@npm:^1.3.1": - version: 1.3.1 - resolution: "component-emitter@npm:1.3.1" - checksum: 10/94550aa462c7bd5a61c1bc480e28554aa306066930152d1b1844a0dd3845d4e5db7e261ddec62ae184913b3e59b55a2ad84093b9d3596a8f17c341514d6c483d +"component-emitter@npm:^1.3.0": + version: 1.3.0 + resolution: "component-emitter@npm:1.3.0" + checksum: 10/dfc1ec2e7aa2486346c068f8d764e3eefe2e1ca0b24f57506cd93b2ae3d67829a7ebd7cc16e2bf51368fac2f45f78fcff231718e40b1975647e4a86be65e1d05 languageName: node linkType: hard @@ -27622,15 +27691,15 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:^4.3.7, debug@npm:^4.4.0": - version: 4.4.1 - resolution: "debug@npm:4.4.1" +"debug@npm:4, debug@npm:^4, debug@npm:^4.0.0, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4, debug@npm:^4.3.5, debug@npm:^4.3.6, debug@npm:^4.4.0": + version: 4.4.0 + resolution: "debug@npm:4.4.0" dependencies: ms: "npm:^2.1.3" peerDependenciesMeta: supports-color: optional: true - checksum: 10/8e2709b2144f03c7950f8804d01ccb3786373df01e406a0f66928e47001cf2d336cbed9ee137261d4f90d68d8679468c755e3548ed83ddacdc82b194d2468afe + checksum: 10/1847944c2e3c2c732514b93d11886575625686056cd765336212dc15de2d2b29612b6cd80e1afba767bb8e1803b778caf9973e98169ef1a24a7a7009e1820367 languageName: node linkType: hard @@ -28386,10 +28455,15 @@ __metadata: languageName: node linkType: hard -"dompurify@npm:^3.0.0, dompurify@npm:^3.1.7": - version: 3.1.7 - resolution: "dompurify@npm:3.1.7" - checksum: 10/dc637a064306f83cf911caa267ffe1f973552047602020e3b6723c90f67962813edf8a65a0b62e8c9bc13fcd173a2691212a3719bc116226967f46bcd6181277 +"dompurify@npm:^3.1.7, dompurify@npm:^3.2.4": + version: 3.2.6 + resolution: "dompurify@npm:3.2.6" + dependencies: + "@types/trusted-types": "npm:^2.0.7" + dependenciesMeta: + "@types/trusted-types": + optional: true + checksum: 10/b91631ed0e4d17fae950ef53613cc009ed7e73adc43ac94a41dd52f35483f7538d13caebdafa7626e0da145fc8184e7ac7935f14f25b7e841b32fda777e40447 languageName: node linkType: hard @@ -29917,6 +29991,7 @@ __metadata: "@backstage/plugin-api-docs": "workspace:^" "@backstage/plugin-app": "workspace:^" "@backstage/plugin-app-visualizer": "workspace:^" + "@backstage/plugin-auth": "workspace:^" "@backstage/plugin-auth-react": "workspace:^" "@backstage/plugin-catalog": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" @@ -30051,6 +30126,7 @@ __metadata: "@backstage/plugin-auth-backend": "workspace:^" "@backstage/plugin-auth-backend-module-github-provider": "workspace:^" "@backstage/plugin-auth-backend-module-guest-provider": "workspace:^" + "@backstage/plugin-auth-backend-module-openshift-provider": "workspace:^" "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-backend": "workspace:^" "@backstage/plugin-catalog-backend-module-backstage-openapi": "workspace:^" @@ -31056,13 +31132,16 @@ __metadata: linkType: hard "form-data@npm:^2.3.2, form-data@npm:^2.5.0": - version: 2.5.1 - resolution: "form-data@npm:2.5.1" + version: 2.5.5 + resolution: "form-data@npm:2.5.5" dependencies: asynckit: "npm:^0.4.0" - combined-stream: "npm:^1.0.6" - mime-types: "npm:^2.1.12" - checksum: 10/2e2e5e927979ba3623f9b4c4bcc939275fae3f2dea9dafc8db3ca656a3d75476605de2c80f0e6f1487987398e056f0b4c738972d6e1edd83392d5686d0952eed + combined-stream: "npm:^1.0.8" + es-set-tostringtag: "npm:^2.1.0" + hasown: "npm:^2.0.2" + mime-types: "npm:^2.1.35" + safe-buffer: "npm:^5.2.1" + checksum: 10/4b6a8d07bb67089da41048e734215f68317a8e29dd5385a972bf5c458a023313c69d3b5d6b8baafbb7f808fa9881e0e2e030ffe61e096b3ddc894c516401271d languageName: node linkType: hard @@ -31105,7 +31184,7 @@ __metadata: languageName: node linkType: hard -"formidable@npm:^3.5.4": +"formidable@npm:^3.5.1": version: 3.5.4 resolution: "formidable@npm:3.5.4" dependencies: @@ -31309,6 +31388,13 @@ __metadata: languageName: node linkType: hard +"fscreen@npm:^1.0.2": + version: 1.2.0 + resolution: "fscreen@npm:1.2.0" + checksum: 10/ac50f9ac52a157b8fe6aaecdf9efa7c1cfa90b42a76c3bc6b85372fab05c5a9cd72c1b7f4c2e273eba1a0e630e381fd72ae135fcc57acd05a0943d5d0c21b451 + languageName: node + linkType: hard + "fsevents@npm:2.3.2": version: 2.3.2 resolution: "fsevents@npm:2.3.2" @@ -37210,6 +37296,15 @@ __metadata: languageName: node linkType: hard +"matcher@npm:^4.0.0": + version: 4.0.0 + resolution: "matcher@npm:4.0.0" + dependencies: + escape-string-regexp: "npm:^4.0.0" + checksum: 10/d338aff31d8dfd3626873e43777f46b123579734d53bb8d18d64b08a822ba5e8d39f5fe2e23403258e6143aa0cbe20a15662720d825cd0d3af961d5a44230328 + languageName: node + linkType: hard + "material-ui-confirm@npm:^3.0.12": version: 3.0.18 resolution: "material-ui-confirm@npm:3.0.18" @@ -38635,15 +38730,15 @@ __metadata: languageName: node linkType: hard -"msw@npm:^2.0.0, msw@npm:^2.0.8": - version: 2.10.4 - resolution: "msw@npm:2.10.4" +"msw@npm:^2.0.0, msw@npm:^2.0.8, msw@npm:^2.7.3": + version: 2.7.3 + resolution: "msw@npm:2.7.3" dependencies: "@bundled-es-modules/cookie": "npm:^2.0.1" "@bundled-es-modules/statuses": "npm:^1.0.1" "@bundled-es-modules/tough-cookie": "npm:^0.1.6" "@inquirer/confirm": "npm:^5.0.0" - "@mswjs/interceptors": "npm:^0.39.1" + "@mswjs/interceptors": "npm:^0.37.0" "@open-draft/deferred-promise": "npm:^2.2.0" "@open-draft/until": "npm:^2.1.0" "@types/cookie": "npm:^0.6.0" @@ -38664,7 +38759,7 @@ __metadata: optional: true bin: msw: cli/index.js - checksum: 10/e2f25dda1aba66c7444c29c41d3157cb15c0332055ab7ebfb74ef4b506e7b90098cf37c577768edb5b2b2dbf0d6ed6a7a3ca8ee6da3d72df5a25823d82f33316 + checksum: 10/f193329a68fc22e477a6f8504aa44a92bd12847f2eeac1dfbd8ec1cc43ff293112ec067de1c7fe312ba02beecb313fb00aeeebf5817432b57af2d796b2dff2fa languageName: node linkType: hard @@ -40614,7 +40709,7 @@ __metadata: languageName: node linkType: hard -"passport-oauth2@npm:1.8.0, passport-oauth2@npm:1.x.x, passport-oauth2@npm:^1.1.2, passport-oauth2@npm:^1.4.0, passport-oauth2@npm:^1.6.0, passport-oauth2@npm:^1.6.1, passport-oauth2@npm:^1.7.0": +"passport-oauth2@npm:1.8.0, passport-oauth2@npm:1.x.x, passport-oauth2@npm:^1.1.2, passport-oauth2@npm:^1.4.0, passport-oauth2@npm:^1.6.0, passport-oauth2@npm:^1.6.1, passport-oauth2@npm:^1.7.0, passport-oauth2@npm:^1.8.0": version: 1.8.0 resolution: "passport-oauth2@npm:1.8.0" dependencies: @@ -42270,7 +42365,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.10.1, qs@npm:^6.10.3, qs@npm:^6.11.2, qs@npm:^6.12.2, qs@npm:^6.12.3, qs@npm:^6.14.0, qs@npm:^6.7.0, qs@npm:^6.9.4": +"qs@npm:^6.10.1, qs@npm:^6.10.3, qs@npm:^6.11.0, qs@npm:^6.11.2, qs@npm:^6.12.2, qs@npm:^6.12.3, qs@npm:^6.14.0, qs@npm:^6.7.0, qs@npm:^6.9.4": version: 6.14.0 resolution: "qs@npm:6.14.0" dependencies: @@ -42849,6 +42944,17 @@ __metadata: languageName: node linkType: hard +"react-full-screen@npm:^1.1.1": + version: 1.1.1 + resolution: "react-full-screen@npm:1.1.1" + dependencies: + fscreen: "npm:^1.0.2" + peerDependencies: + react: ">= 16.8.0" + checksum: 10/70ad927b9d6c485ac46b5bb4b1639ef9a860da28290b3a1c419c42b9c427d78b80e8dba403eb6451458af56838012c81d5e12ef05097395f154defc32fe06c34 + languageName: node + linkType: hard + "react-grid-layout@npm:1.3.4": version: 1.3.4 resolution: "react-grid-layout@npm:1.3.4" @@ -46509,30 +46615,30 @@ __metadata: languageName: node linkType: hard -"superagent@npm:^10.2.3": - version: 10.2.3 - resolution: "superagent@npm:10.2.3" +"superagent@npm:^9.0.1": + version: 9.0.2 + resolution: "superagent@npm:9.0.2" dependencies: - component-emitter: "npm:^1.3.1" + component-emitter: "npm:^1.3.0" cookiejar: "npm:^2.1.4" - debug: "npm:^4.3.7" + debug: "npm:^4.3.4" fast-safe-stringify: "npm:^2.1.1" - form-data: "npm:^4.0.4" - formidable: "npm:^3.5.4" + form-data: "npm:^4.0.0" + formidable: "npm:^3.5.1" methods: "npm:^1.1.2" mime: "npm:2.6.0" - qs: "npm:^6.11.2" - checksum: 10/377bf938e68927dd772169c5285be27872bf6e84fac01c52bcd9396bc5b348c9ded8f8be54649510ec09a67bc5096055847b37cb01b3bca0eb06ff1856170e35 + qs: "npm:^6.11.0" + checksum: 10/d3c0c9051ceec84d5b431eaa410ad81bcd53255cea57af1fc66d683a24c34f3ba4761b411072a9bf489a70e3d5b586a78a0e6f2eac6a561067e7d196ddab0907 languageName: node linkType: hard -"supertest@npm:^7.0.0": - version: 7.1.4 - resolution: "supertest@npm:7.1.4" +"supertest@npm:^7.0.0, supertest@npm:^7.1.0": + version: 7.1.0 + resolution: "supertest@npm:7.1.0" dependencies: methods: "npm:^1.1.2" - superagent: "npm:^10.2.3" - checksum: 10/ecb5d41f2b62b257dbdcabac245c32b8e8fb264fe2636dd85c2c883569d23dc14adc0a471abb84187cbdb49bc36ad870ad355b4a0b85973f510fd57fc229e6cc + superagent: "npm:^9.0.1" + checksum: 10/20069f739a44821dfa4f7f397b9086ef31a358366331138f97945eedb2e231796e7c55b032125d3bd12f9839f089fbb809893dbc0f98edc57e12333b9f42b726 languageName: node linkType: hard @@ -49862,6 +49968,7 @@ __metadata: "@backstage/backend-test-utils": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/cli-common": "workspace:^" + "@backstage/errors": "workspace:^" "@backstage/release-manifests": "workspace:^" "@yarnpkg/builder": "npm:^4.2.1" "@yarnpkg/core": "npm:^4.4.1" @@ -50031,10 +50138,10 @@ __metadata: languageName: node linkType: hard -"zod@npm:^3.22.4, zod@npm:^3.23.8": - version: 3.25.76 - resolution: "zod@npm:3.25.76" - checksum: 10/f0c963ec40cd96858451d1690404d603d36507c1fc9682f2dae59ab38b578687d542708a7fdbf645f77926f78c9ed558f57c3d3aa226c285f798df0c4da16995 +"zod@npm:^3.22.4, zod@npm:^3.23.8, zod@npm:^3.24.2": + version: 3.25.67 + resolution: "zod@npm:3.25.67" + checksum: 10/0e35432dcca7f053e63f5dd491a87c78abe0d981817547252c3b6d05f0f58788695d1a69724759c6501dff3fd62929be24c9f314a3625179bee889150f7a61fa languageName: node linkType: hard From d4b682feafb757d601972a79bd14973e5d1ecbcd Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Thu, 11 Sep 2025 22:24:11 +0300 Subject: [PATCH 017/244] feat(yarn-plugin): custom manifest location added two environment variables that can be used to control the location of backstage manifest file used by the yarn plugin. this helps using the plugin in restricted environments without direct or access at all to the internet. closes #31101 Signed-off-by: Hellgren Heikki --- packages/yarn-plugin/README.md | 15 + .../src/util/getPackageVersion.test.ts | 460 ++++++++++++++++++ .../yarn-plugin/src/util/getPackageVersion.ts | 71 +-- 3 files changed, 513 insertions(+), 33 deletions(-) create mode 100644 packages/yarn-plugin/src/util/getPackageVersion.test.ts diff --git a/packages/yarn-plugin/README.md b/packages/yarn-plugin/README.md index 5c112506e3..fe90cebe7b 100644 --- a/packages/yarn-plugin/README.md +++ b/packages/yarn-plugin/README.md @@ -25,6 +25,21 @@ The yarn plugin recognizes the version string `"backstage:^"`, and replaces it with the appropriate version based on the overall Backstage version in backstage.json. +### Configuration + +The plugin functionality can be configured with environment variables: + +- `BACKSTAGE_MANIFEST_BASE_URL` - The base URL for fetching the Backstage version + manifest. Defaults to `https://versions.backstage.io/v1/releases/VERSION/manifest.json`. + Useful for running the plugin in environment without direct access to the internet, + for example by using a mirror of the versions API or a proxy. + Note that the environment variable is just the host name, and the path is appended by + the plugin. +- `BACKSTAGE_MANIFEST_FILE` - Path to a local manifest file. If set, the plugin + will not attempt to fetch the manifest from the network. Useful for running + the plugin in environment without internet access and without mirror of the + versions API. + ## Local Development - Run unit tests: `yarn test` diff --git a/packages/yarn-plugin/src/util/getPackageVersion.test.ts b/packages/yarn-plugin/src/util/getPackageVersion.test.ts new file mode 100644 index 0000000000..d093a8f3ad --- /dev/null +++ b/packages/yarn-plugin/src/util/getPackageVersion.test.ts @@ -0,0 +1,460 @@ +/* + * 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 { + Configuration, + Descriptor, + httpUtils, + structUtils, +} from '@yarnpkg/core'; +import { xfs } from '@yarnpkg/fslib'; +import { getManifestByVersion } from '@backstage/release-manifests'; +import { getPackageVersion } from './getPackageVersion'; +import { getCurrentBackstageVersion } from './getCurrentBackstageVersion'; + +jest.mock('@yarnpkg/core'); +jest.mock('@backstage/release-manifests'); +jest.mock('./getCurrentBackstageVersion'); + +const mockHttpUtils = httpUtils as jest.Mocked; +const mockStructUtils = structUtils as jest.Mocked; +const mockGetManifestByVersion = getManifestByVersion as jest.MockedFunction< + typeof getManifestByVersion +>; +const mockGetCurrentBackstageVersion = + getCurrentBackstageVersion as jest.MockedFunction< + typeof getCurrentBackstageVersion + >; + +describe('getPackageVersion', () => { + const mockConfiguration = {} as Configuration; + + beforeEach(() => { + jest.clearAllMocks(); + + mockGetCurrentBackstageVersion.mockReturnValue('1.23.4'); + mockStructUtils.stringifyIdent.mockImplementation( + (descriptor: any) => + `${descriptor.scope || ''}${descriptor.scope ? '/' : ''}${ + descriptor.name + }`, + ); + + mockStructUtils.parseRange.mockImplementation((range: string) => ({ + protocol: range.includes('backstage:') ? 'backstage:' : 'npm:', + selector: range.includes('^') ? '^' : range.split(':')[1] || '', + })); + }); + + describe('successful package resolution', () => { + beforeEach(() => { + mockHttpUtils.get.mockResolvedValue({ + packages: [ + { name: '@backstage/core-plugin-api', version: '1.9.0' }, + { name: '@backstage/core-app-api', version: '1.12.0' }, + ], + }); + + mockGetManifestByVersion.mockResolvedValue({ + releaseVersion: '1.23.4', + packages: [ + { name: '@backstage/core-plugin-api', version: '1.9.0' }, + { name: '@backstage/core-app-api', version: '1.12.0' }, + ], + }); + }); + + it('returns the correct version for a package in the manifest', async () => { + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:^', + } as Descriptor; + + const result = await getPackageVersion(descriptor, mockConfiguration); + + expect(result).toBe('1.9.0'); + expect(mockGetCurrentBackstageVersion).toHaveBeenCalledTimes(1); + expect(mockGetManifestByVersion).toHaveBeenCalledWith({ + version: '1.23.4', + versionsBaseUrl: undefined, + fetch: expect.any(Function), + }); + }); + + it('uses custom versionsBaseUrl from environment when provided', async () => { + const originalEnv = process.env.BACKSTAGE_MANIFEST_BASE_URL; + process.env.BACKSTAGE_MANIFEST_BASE_URL = 'https://custom.example.com'; + + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:^', + } as Descriptor; + + await getPackageVersion(descriptor, mockConfiguration); + + expect(mockGetManifestByVersion).toHaveBeenCalledWith({ + version: '1.23.4', + versionsBaseUrl: 'https://custom.example.com', + fetch: expect.any(Function), + }); + + process.env.BACKSTAGE_MANIFEST_BASE_URL = originalEnv; + }); + + it('uses yarn httpUtils for fetching with proper response format', async () => { + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:^', + } as Descriptor; + + const mockResponse = { + packages: [{ name: '@backstage/core-plugin-api', version: '1.9.0' }], + }; + + mockHttpUtils.get.mockResolvedValue(mockResponse); + + await getPackageVersion(descriptor, mockConfiguration); + + expect(mockGetManifestByVersion).toHaveBeenCalledTimes(1); + + // Get the fetch function that was passed to getManifestByVersion + const fetchFunction = mockGetManifestByVersion.mock.calls[0][0].fetch; + + // Test the custom fetch function + const testUrl = 'https://example.com/manifest.json'; + const fetchResult = await fetchFunction!(testUrl); + + expect(mockHttpUtils.get).toHaveBeenCalledWith(testUrl, { + configuration: mockConfiguration, + jsonResponse: true, + }); + + expect(fetchResult).toEqual({ + status: 200, + url: testUrl, + json: expect.any(Function), + }); + + expect(await fetchResult.json()).toEqual(mockResponse); + }); + }); + + describe('error cases', () => { + it('throws error for unsupported protocol', async () => { + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'npm:^1.0.0', + } as Descriptor; + + mockStructUtils.parseRange.mockReturnValue({ + protocol: 'npm:', + selector: '^1.0.0', + }); + + await expect( + getPackageVersion(descriptor, mockConfiguration), + ).rejects.toThrow( + 'Unsupported version protocol in version range "npm:^1.0.0" for package @backstage/core-plugin-api', + ); + }); + + it('throws error for unexpected version selector', async () => { + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:~1.0.0', + } as Descriptor; + + mockStructUtils.parseRange.mockReturnValue({ + protocol: 'backstage:', + selector: '~1.0.0', + }); + + await expect( + getPackageVersion(descriptor, mockConfiguration), + ).rejects.toThrow( + 'Unexpected version selector "~1.0.0" for package @backstage/core-plugin-api', + ); + }); + + it('throws error when package is not found in manifest', async () => { + const descriptor = { + scope: '@backstage', + name: 'non-existent-package', + range: 'backstage:^', + } as Descriptor; + + mockGetManifestByVersion.mockResolvedValue({ + releaseVersion: '1.23.4', + packages: [{ name: '@backstage/core-plugin-api', version: '1.9.0' }], + }); + + await expect( + getPackageVersion(descriptor, mockConfiguration), + ).rejects.toThrow( + 'Package @backstage/non-existent-package not found in manifest for Backstage v1.23.4. ' + + 'This means the specified package is not included in this Backstage ' + + 'release. This may imply the package has been replaced with an alternative - ' + + 'please review the documentation for the package. If you need to continue ' + + 'using this package, it will be necessary to switch to manually managing its ' + + 'version.', + ); + }); + + it('propagates errors from getManifestByVersion', async () => { + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:^', + } as Descriptor; + + const manifestError = new Error('Failed to fetch manifest'); + mockGetManifestByVersion.mockRejectedValue(manifestError); + + await expect( + getPackageVersion(descriptor, mockConfiguration), + ).rejects.toThrow('Failed to fetch manifest'); + }); + + it('propagates errors from getCurrentBackstageVersion', async () => { + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:^', + } as Descriptor; + + const versionError = new Error('Failed to get current version'); + mockGetCurrentBackstageVersion.mockImplementation(() => { + throw versionError; + }); + + await expect( + getPackageVersion(descriptor, mockConfiguration), + ).rejects.toThrow('Failed to get current version'); + }); + }); + + describe('different package name formats', () => { + beforeEach(() => { + mockGetManifestByVersion.mockResolvedValue({ + releaseVersion: '1.23.4', + packages: [ + { name: '@backstage/core-plugin-api', version: '1.9.0' }, + { name: 'backstage-plugin-simple', version: '0.5.0' }, + { name: '@internal/custom-package', version: '2.1.0' }, + ], + }); + }); + + it('handles scoped packages correctly', async () => { + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:^', + } as Descriptor; + + const result = await getPackageVersion(descriptor, mockConfiguration); + expect(result).toBe('1.9.0'); + }); + + it('handles non-scoped packages correctly', async () => { + const descriptor = { + name: 'backstage-plugin-simple', + range: 'backstage:^', + } as Descriptor; + + mockStructUtils.stringifyIdent.mockReturnValue('backstage-plugin-simple'); + + const result = await getPackageVersion(descriptor, mockConfiguration); + expect(result).toBe('0.5.0'); + }); + + it('handles packages with different scopes', async () => { + const descriptor = { + scope: '@internal', + name: 'custom-package', + range: 'backstage:^', + } as Descriptor; + + mockStructUtils.stringifyIdent.mockReturnValue( + '@internal/custom-package', + ); + + const result = await getPackageVersion(descriptor, mockConfiguration); + expect(result).toBe('2.1.0'); + }); + }); + + describe('BACKSTAGE_MANIFEST_FILE environment variable', () => { + const manifestFilePath = '/path/to/manifest.json'; + + beforeEach(() => { + // Clean up environment variables + delete process.env.BACKSTAGE_MANIFEST_FILE; + }); + + afterEach(() => { + // Clean up environment variables + delete process.env.BACKSTAGE_MANIFEST_FILE; + }); + + it('reads manifest from file when BACKSTAGE_MANIFEST_FILE is set', async () => { + process.env.BACKSTAGE_MANIFEST_FILE = manifestFilePath; + + const mockManifest = { + packages: [ + { name: '@backstage/core-plugin-api', version: '1.9.0' }, + { name: '@backstage/core-app-api', version: '1.12.0' }, + ], + }; + + const readJsonSyncSpy = jest.spyOn(xfs, 'readJsonSync'); + readJsonSyncSpy.mockReturnValue(mockManifest); + + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:^', + } as Descriptor; + + const result = await getPackageVersion(descriptor, mockConfiguration); + + expect(result).toBe('1.9.0'); + expect(readJsonSyncSpy).toHaveBeenCalledWith(manifestFilePath); + expect(mockGetManifestByVersion).not.toHaveBeenCalled(); + expect(mockHttpUtils.get).not.toHaveBeenCalled(); + }); + + it('finds package in file-based manifest', async () => { + process.env.BACKSTAGE_MANIFEST_FILE = manifestFilePath; + + const mockManifest = { + packages: [ + { name: '@backstage/core-plugin-api', version: '2.1.0' }, + { name: '@backstage/backend-common', version: '0.19.5' }, + { name: 'simple-package', version: '1.0.0' }, + ], + }; + + const readJsonSyncSpy = jest.spyOn(xfs, 'readJsonSync'); + readJsonSyncSpy.mockReturnValue(mockManifest); + + const descriptor = { + scope: '@backstage', + name: 'backend-common', + range: 'backstage:^', + } as Descriptor; + + mockStructUtils.stringifyIdent.mockReturnValue( + '@backstage/backend-common', + ); + + const result = await getPackageVersion(descriptor, mockConfiguration); + + expect(result).toBe('0.19.5'); + expect(readJsonSyncSpy).toHaveBeenCalledWith(manifestFilePath); + }); + + it('throws error when package not found in file-based manifest', async () => { + process.env.BACKSTAGE_MANIFEST_FILE = manifestFilePath; + + const mockManifest = { + packages: [{ name: '@backstage/core-plugin-api', version: '1.9.0' }], + }; + + const readJsonSyncSpy = jest.spyOn(xfs, 'readJsonSync'); + readJsonSyncSpy.mockReturnValue(mockManifest); + + const descriptor = { + scope: '@backstage', + name: 'missing-package', + range: 'backstage:^', + } as Descriptor; + + mockStructUtils.stringifyIdent.mockReturnValue( + '@backstage/missing-package', + ); + + await expect( + getPackageVersion(descriptor, mockConfiguration), + ).rejects.toThrow( + 'Package @backstage/missing-package not found in manifest for Backstage v1.23.4. ' + + 'This means the specified package is not included in this Backstage ' + + 'release. This may imply the package has been replaced with an alternative - ' + + 'please review the documentation for the package. If you need to continue ' + + 'using this package, it will be necessary to switch to manually managing its ' + + 'version.', + ); + + expect(readJsonSyncSpy).toHaveBeenCalledWith(manifestFilePath); + expect(mockGetManifestByVersion).not.toHaveBeenCalled(); + }); + + it('propagates errors from xfs.readJsonSync when file cannot be read', async () => { + process.env.BACKSTAGE_MANIFEST_FILE = manifestFilePath; + + const fileError = new Error('ENOENT: no such file or directory'); + const readJsonSyncSpy = jest.spyOn(xfs, 'readJsonSync'); + readJsonSyncSpy.mockImplementation(() => { + throw fileError; + }); + + const descriptor = { + scope: '@backstage', + name: 'core-plugin-api', + range: 'backstage:^', + } as Descriptor; + + await expect( + getPackageVersion(descriptor, mockConfiguration), + ).rejects.toThrow('ENOENT: no such file or directory'); + + expect(readJsonSyncSpy).toHaveBeenCalledWith(manifestFilePath); + expect(mockGetManifestByVersion).not.toHaveBeenCalled(); + }); + + it('handles non-scoped packages in file-based manifest', async () => { + process.env.BACKSTAGE_MANIFEST_FILE = manifestFilePath; + + const mockManifest = { + packages: [ + { name: 'backstage-plugin-simple', version: '0.5.0' }, + { name: '@backstage/core-plugin-api', version: '1.9.0' }, + ], + }; + + const readJsonSyncSpy = jest.spyOn(xfs, 'readJsonSync'); + readJsonSyncSpy.mockReturnValue(mockManifest); + + const descriptor = { + name: 'backstage-plugin-simple', + range: 'backstage:^', + } as Descriptor; + + mockStructUtils.stringifyIdent.mockReturnValue('backstage-plugin-simple'); + + const result = await getPackageVersion(descriptor, mockConfiguration); + + expect(result).toBe('0.5.0'); + expect(readJsonSyncSpy).toHaveBeenCalledWith(manifestFilePath); + expect(mockGetManifestByVersion).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/yarn-plugin/src/util/getPackageVersion.ts b/packages/yarn-plugin/src/util/getPackageVersion.ts index 25ff795c06..ed1c1ee6d8 100644 --- a/packages/yarn-plugin/src/util/getPackageVersion.ts +++ b/packages/yarn-plugin/src/util/getPackageVersion.ts @@ -20,10 +20,12 @@ import { httpUtils, structUtils, } from '@yarnpkg/core'; +import { PortablePath, xfs } from '@yarnpkg/fslib'; import { getManifestByVersion } from '@backstage/release-manifests'; import { PROTOCOL } from '../constants'; import { getCurrentBackstageVersion } from './getCurrentBackstageVersion'; +import { env } from 'process'; export const getPackageVersion = async ( descriptor: Descriptor, @@ -45,43 +47,46 @@ export const getPackageVersion = async ( } const backstageVersion = getCurrentBackstageVersion(); + const manifestFile = env.BACKSTAGE_MANIFEST_FILE; + const manifest = manifestFile + ? await xfs.readJsonSync(manifestFile as PortablePath) + : await getManifestByVersion({ + version: backstageVersion, + versionsBaseUrl: env.BACKSTAGE_MANIFEST_BASE_URL, + // We override the fetch function used inside getManifestByVersion with a + // custom implementation that calls yarn's built-in `httpUtils` method + // instead. This has a couple of benefits: + // + // 1. This means that the fetch should leverage yarn's built-in cache, so we + // don't need to explicitly memoize the fetch. + // 2. The request should automatically take account of any proxy settings + // configured in yarn. + fetch: async (url: string) => { + const response = await httpUtils.get(url, { + configuration, + jsonResponse: true, + }); - const manifest = await getManifestByVersion({ - version: backstageVersion, - // We override the fetch function used inside getManifestByVersion with a - // custom implementation that calls yarn's built-in `httpUtils` method - // instead. This has a couple of benefits: - // - // 1. This means that the fetch should leverage yarn's built-in cache, so we - // don't need to explicitly memoize the fetch. - // 2. The request should automatically take account of any proxy settings - // configured in yarn. - fetch: async (url: string) => { - const response = await httpUtils.get(url, { - configuration, - jsonResponse: true, + // The release-manifests package expects fetchFn to resolve with a subset + // of the native HTTP Response object, but yarn's httpUtils implementation + // keeps most of the details hidden. This means we need to construct an + // object which quacks like a Response in the appropriate ways. + return { + // The function has some custom handling for non-200 errors. Yarn + // doesn't provide the status code, but if we've got to this point + // without throwing, we can assume the request has been successful. + status: 200, + // The requested URL, used to correctly report errors + url, + // Yarn automatically parses the response as JSON, so our implementation + // can simply return it. + json: () => response, + }; + }, }); - // The release-manifests package expects fetchFn to resolve with a subset - // of the native HTTP Response object, but yarn's httpUtils implementation - // keeps most of the details hidden. This means we need to construct an - // object which quacks like a Response in the appropriate ways. - return { - // The function has some custom handling for non-200 errors. Yarn - // doesn't provide the status code, but if we've got to this point - // without throwing, we can assume the request has been successful. - status: 200, - // The requested URL, used to correctly report errors - url, - // Yarn automatically parses the response as JSON, so our implementation - // can simply return it. - json: () => response, - }; - }, - }); - const manifestEntry = manifest.packages.find( - candidate => candidate.name === ident, + (candidate: { name: string; version: string }) => candidate.name === ident, ); if (!manifestEntry) { From 33faad237f81899bbc8bdb17e5b6738688ea1455 Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Fri, 12 Sep 2025 09:02:52 +0300 Subject: [PATCH 018/244] feat(cli): also support custom manifest in version bump Signed-off-by: Hellgren Heikki --- .changeset/heavy-chicken-find.md | 20 ++ .../migrate/commands/versions/bump.test.ts | 315 +++++++++++++++++- .../modules/migrate/commands/versions/bump.ts | 27 +- 3 files changed, 351 insertions(+), 11 deletions(-) create mode 100644 .changeset/heavy-chicken-find.md diff --git a/.changeset/heavy-chicken-find.md b/.changeset/heavy-chicken-find.md new file mode 100644 index 0000000000..96308ed2b8 --- /dev/null +++ b/.changeset/heavy-chicken-find.md @@ -0,0 +1,20 @@ +--- +'@backstage/cli': patch +--- + +Allow using custom manifest location in the yarn plugin and version bump. + +The Backstage yarn plugin and version bump allows two new environment variables to configure custom manifest location: + +- `BACKSTAGE_MANIFEST_BASE_URL`: The base URL for fetching the Backstage version + manifest. Defaults to `https://versions.backstage.io/v1/releases/VERSION/manifest.json`. + Useful for running the plugin in environment without direct access to the internet, + for example by using a mirror of the versions API or a proxy. + Note that the environment variable is just the host name, and the path is appended by + the plugin. If you are using the yarn plugin, bump version command will also try + to fetch the new version of the yarn plugin from the same base URL (defaults to + `https://versions.backstage.io/v1/releases/RELEASE/yarn-plugin`) +- `BACKSTAGE_MANIFEST_FILE`: Path to a local manifest file. If set, the plugin + will not attempt to fetch the manifest from the network. Useful for running + the plugin in environment without internet access and without mirror of the + versions API. diff --git a/packages/cli/src/modules/migrate/commands/versions/bump.test.ts b/packages/cli/src/modules/migrate/commands/versions/bump.test.ts index a309ddb192..bea7a551a1 100644 --- a/packages/cli/src/modules/migrate/commands/versions/bump.test.ts +++ b/packages/cli/src/modules/migrate/commands/versions/bump.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 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,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import fs from 'fs-extra'; import { Command } from 'commander'; import * as runObj from '../../../../lib/run'; @@ -24,8 +23,8 @@ import { setupServer } from 'msw/node'; import { rest } from 'msw'; import { NotFoundError } from '@backstage/errors'; import { - MockDirectory, createMockDirectory, + MockDirectory, } from '@backstage/backend-test-utils'; // Avoid mutating the global agents used in other tests @@ -1055,3 +1054,313 @@ describe('createVersionFinder', () => { ); }); }); + +describe('environment variables', () => { + const worker = setupServer(); + registerMswTestHooks(worker); + + beforeEach(() => { + delete process.env.BACKSTAGE_MANIFEST_FILE; + delete process.env.BACKSTAGE_MANIFEST_BASE_URL; + }); + + afterEach(() => { + jest.resetAllMocks(); + delete process.env.BACKSTAGE_MANIFEST_FILE; + delete process.env.BACKSTAGE_MANIFEST_BASE_URL; + }); + + it('should use custom base URL when BACKSTAGE_MANIFEST_BASE_URL is set', async () => { + process.env.BACKSTAGE_MANIFEST_BASE_URL = 'https://custom.example.com'; + + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ + workspaces: { + packages: ['packages/*'], + }, + }), + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), + }, + }, + }); + + jest.spyOn(runObj, 'run').mockResolvedValue(undefined); + worker.use( + rest.get( + 'https://custom.example.com/v1/tags/main/manifest.json', + (_, res, ctx) => + res( + ctx.status(200), + ctx.json({ + releaseVersion: '1.5.0', + packages: [ + { + name: '@backstage/core', + version: '1.5.0', + }, + ], + }), + ), + ), + ); + + const { log: logs } = await withLogCollector(['log', 'warn'], async () => { + await bump({ pattern: null, release: 'main' } as unknown as Command); + }); + + expectLogsToMatch(logs, [ + 'Using default pattern glob @backstage/*', + 'Checking for updates of @backstage/core', + 'Some packages are outdated, updating', + 'bumping @backstage/core in a to ^1.5.0', + 'Your project is now at version 1.5.0, which has been written to backstage.json', + 'Running yarn install to install new versions', + 'Checking for moved packages to the @backstage-community namespace...', + 'Version bump complete!', + ]); + + expect(runObj.run).toHaveBeenCalledTimes(1); + expect(runObj.run).toHaveBeenCalledWith( + 'yarn', + ['install'], + expect.any(Object), + ); + + const packageA = await fs.readJson( + mockDir.resolve('packages/a/package.json'), + ); + expect(packageA).toEqual({ + name: 'a', + dependencies: { + '@backstage/core': '^1.5.0', + }, + }); + }); + + it('should use custom manifest file when BACKSTAGE_MANIFEST_FILE is set', async () => { + const manifestPath = mockDir.resolve('custom-manifest.json'); + process.env.BACKSTAGE_MANIFEST_FILE = manifestPath; + + const customManifest = { + releaseVersion: '2.0.0', + packages: [ + { + name: '@backstage/core', + version: '2.0.0', + }, + { + name: '@backstage/theme', + version: '3.0.0', + }, + ], + }; + + mockDir.setContent({ + 'custom-manifest.json': JSON.stringify(customManifest), + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ + workspaces: { + packages: ['packages/*'], + }, + }), + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + '@backstage/theme': '^1.0.0', + }, + }), + }, + }, + }); + + jest.spyOn(runObj, 'run').mockResolvedValue(undefined); + + const { log: logs } = await withLogCollector(['log', 'warn'], async () => { + await bump({ pattern: null, release: 'main' } as unknown as Command); + }); + + expectLogsToMatch(logs, [ + 'Using default pattern glob @backstage/*', + 'Checking for updates of @backstage/core', + 'Checking for updates of @backstage/theme', + 'Some packages are outdated, updating', + 'bumping @backstage/core in a to ^2.0.0', + 'bumping @backstage/theme in a to ^3.0.0', + 'Your project is now at version 2.0.0, which has been written to backstage.json', + 'Running yarn install to install new versions', + 'Checking for moved packages to the @backstage-community namespace...', + '⚠️ The following packages may have breaking changes:', + ' @backstage/core : 1.0.6 ~> 2.0.0', + ' https://github.com/backstage/backstage/blob/master/packages/core/CHANGELOG.md', + ' @backstage/theme : 1.0.0 ~> 3.0.0', + ' https://github.com/backstage/backstage/blob/master/packages/theme/CHANGELOG.md', + 'Version bump complete!', + ]); + + // Should not make any HTTP requests since using local manifest + expect(mockFetchPackageInfo).not.toHaveBeenCalled(); + + expect(runObj.run).toHaveBeenCalledTimes(1); + expect(runObj.run).toHaveBeenCalledWith( + 'yarn', + ['install'], + expect.any(Object), + ); + + const packageA = await fs.readJson( + mockDir.resolve('packages/a/package.json'), + ); + expect(packageA).toEqual({ + name: 'a', + dependencies: { + '@backstage/core': '^2.0.0', + '@backstage/theme': '^3.0.0', + }, + }); + }); + + it('should use custom base URL for yarn plugin when BACKSTAGE_MANIFEST_BASE_URL is set with yarn plugin', async () => { + process.env.BACKSTAGE_MANIFEST_BASE_URL = 'https://custom.example.com'; + + mockDir.setContent({ + '.yarnrc.yml': yarnRcMock, + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ + workspaces: { + packages: ['packages/*'], + }, + }), + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), + }, + }, + }); + + jest.spyOn(runObj, 'run').mockResolvedValue(undefined); + worker.use( + rest.get( + 'https://custom.example.com/v1/tags/main/manifest.json', + (_, res, ctx) => + res( + ctx.status(200), + ctx.json({ + releaseVersion: '1.5.0', + packages: [ + { + name: '@backstage/core', + version: '1.5.0', + }, + ], + }), + ), + ), + ); + + const { log: logs } = await withLogCollector(['log', 'warn'], async () => { + await bump({ pattern: null, release: 'main' } as unknown as Command); + }); + + expectLogsToMatch(logs, [ + 'Using default pattern glob @backstage/*', + 'Checking for updates of @backstage/core', + 'NOTE: this bump used backstage:^ versions in package.json files, since the Backstage yarn plugin was detected in the repository. To migrate back to explicit npm versions, remove the plugin by running "yarn plugin remove @yarnpkg/plugin-backstage", then repeat this command.', + 'Some packages are outdated, updating', + 'bumping @backstage/core in a to ^1.5.0', + 'Updating yarn plugin to v1.5.0...', + 'Your project is now at version 1.5.0, which has been written to backstage.json', + 'Running yarn install to install new versions', + 'Checking for moved packages to the @backstage-community namespace...', + 'Version bump complete!', + ]); + + expect(runObj.run).toHaveBeenCalledTimes(2); + expect(runObj.run).toHaveBeenCalledWith('yarn', [ + 'plugin', + 'import', + 'https://custom.example.com/v1/releases/1.5.0/yarn-plugin', + ]); + expect(runObj.run).toHaveBeenCalledWith( + 'yarn', + ['install'], + expect.any(Object), + ); + }); + + it('should handle missing manifest file when BACKSTAGE_MANIFEST_FILE is set', async () => { + process.env.BACKSTAGE_MANIFEST_FILE = '/nonexistent/manifest.json'; + + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ + workspaces: { + packages: ['packages/*'], + }, + }), + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), + }, + }, + }); + + await expect( + bump({ pattern: null, release: 'main' } as unknown as Command), + ).rejects.toThrow(); + }); + + it('should handle network errors when using custom base URL', async () => { + process.env.BACKSTAGE_MANIFEST_BASE_URL = 'https://custom.example.com'; + + mockDir.setContent({ + 'yarn.lock': lockfileMock, + 'package.json': JSON.stringify({ + workspaces: { + packages: ['packages/*'], + }, + }), + packages: { + a: { + 'package.json': JSON.stringify({ + name: 'a', + dependencies: { + '@backstage/core': '^1.0.5', + }, + }), + }, + }, + }); + + worker.use( + rest.get( + 'https://custom.example.com/v1/tags/main/manifest.json', + (_, res, ctx) => res(ctx.status(500), ctx.json({})), + ), + ); + + await expect( + bump({ pattern: null, release: 'main' } as unknown as Command), + ).rejects.toThrow(); + }); +}); diff --git a/packages/cli/src/modules/migrate/commands/versions/bump.ts b/packages/cli/src/modules/migrate/commands/versions/bump.ts index 23202ee1b5..b4c21be58c 100644 --- a/packages/cli/src/modules/migrate/commands/versions/bump.ts +++ b/packages/cli/src/modules/migrate/commands/versions/bump.ts @@ -16,6 +16,7 @@ maybeBootstrapProxy(); +import { env } from 'process'; import fs from 'fs-extra'; import chalk from 'chalk'; import semver from 'semver'; @@ -26,9 +27,9 @@ import { isError, NotFoundError } from '@backstage/errors'; import { resolve as resolvePath } from 'path'; import { paths } from '../../../../lib/paths'; import { - mapDependencies, fetchPackageInfo, Lockfile, + mapDependencies, YarnInfoInspectData, } from '../../../../lib/versioning'; import { BACKSTAGE_JSON } from '@backstage/cli-common'; @@ -96,8 +97,14 @@ export default async (opts: OptionValues) => { let findTargetVersion: (name: string) => Promise; let releaseManifest: ReleaseManifest; - // Specific release specified. Be strict when resolving versions - if (semver.valid(opts.release)) { + if (env.BACKSTAGE_MANIFEST_FILE) { + // Use specific manifest file if provided + releaseManifest = await fs.readJson(env.BACKSTAGE_MANIFEST_FILE); + findTargetVersion = createStrictVersionFinder({ + releaseManifest, + }); + } else if (semver.valid(opts.release)) { + // Specific release specified. Be strict when resolving versions releaseManifest = await getManifestByVersion({ version: opts.release }); findTargetVersion = createStrictVersionFinder({ releaseManifest, @@ -107,9 +114,11 @@ export default async (opts: OptionValues) => { if (opts.release === 'next') { const next = await getManifestByReleaseLine({ releaseLine: 'next', + versionsBaseUrl: env.BACKSTAGE_MANIFEST_BASE_URL, }); const main = await getManifestByReleaseLine({ releaseLine: 'main', + versionsBaseUrl: env.BACKSTAGE_MANIFEST_BASE_URL, }); // Prefer manifest with the latest release version releaseManifest = semver.gt(next.releaseVersion, main.releaseVersion) @@ -118,6 +127,7 @@ export default async (opts: OptionValues) => { } else { releaseManifest = await getManifestByReleaseLine({ releaseLine: opts.release, + versionsBaseUrl: env.BACKSTAGE_MANIFEST_BASE_URL, }); } findTargetVersion = createVersionFinder({ @@ -132,11 +142,12 @@ export default async (opts: OptionValues) => { `Updating yarn plugin to v${releaseManifest.releaseVersion}...`, ); console.log(); - await run('yarn', [ - 'plugin', - 'import', - `https://versions.backstage.io/v1/releases/${releaseManifest.releaseVersion}/yarn-plugin`, - ]); + + const yarnPluginUrl = env.BACKSTAGE_MANIFEST_BASE_URL + ? `${env.BACKSTAGE_MANIFEST_BASE_URL}/v1/releases/${releaseManifest.releaseVersion}/yarn-plugin` + : `https://versions.backstage.io/v1/releases/${releaseManifest.releaseVersion}/yarn-plugin`; + + await run('yarn', ['plugin', 'import', yarnPluginUrl]); console.log(); } From d0baa442e873bfe028a7f0353f3336205f369596 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 12 Sep 2025 11:53:27 +0100 Subject: [PATCH 019/244] Add CSS variables + class name structure Signed-off-by: Charles de Dreuille --- .../css-classname-structure.png | Bin 0 -> 42743 bytes docs/conf/user-interface/index.md | 154 +++++++++++++++++- microsite/src/theme/customTheme.scss | 5 + 3 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 docs/assets/user-interface/css-classname-structure.png diff --git a/docs/assets/user-interface/css-classname-structure.png b/docs/assets/user-interface/css-classname-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..c241b182cc49d9044901d7e4c0dcbb30479bf006 GIT binary patch literal 42743 zcmeFY^;aA1w>}(7k>YK!;uMNo3&q{trD#hj5+q1)Zz)nJ?pEBjIKc{(;_ezeSa1js ziY)kX((jc5Df!=l=vODA!OMSQpeE$ zO6!xV&Pyq+RgA}DkH_#=51=595Afjj17q|yN~ngO%H#RuW#mlcgX6>O9N#c z&G=tjq$UtkBq|q-V&R^4VBwxWLI0;vASjz>_nNNvT55rZ)j2SK)yC8FDwVGPCeCo5 zXYc4pASftkjT1XTwb?{}o#bBZpK^dxvQKZVyu9Wgo5va&85wo#9#IF7Y`%S<2gW3@ zNT#Kw-FSeU@_*SN4wubsWZymhr(pFRDJiLHf%cOJM+~8n4npbt2O@;fM+`+NCsz*a zsC%E|Ucz12+L}4<>(}PW1#xKq6qH10c}yG}*po9=G*dlR%KAPTImIuD)0GD$?8>Xc z2$;%HusT|4GlxC>rvw1chk7&UhZw;UXmoZDJwD?ZGU7hLRH3 z5l;{6pAwoJX=F;vif3nMYoqXxIy(xw=C$#wD^JgV$4kRZJfEF1QwHNK9udjdK@^BOjP&%W*K%4lfUGj;T z?%$!w7GRatW+J{Cn=UhWXhS;g%gj~an<7;1u2(yQtUi4B^>4%39-LfUY3Txvd(j?A zNl7cTO?k94A~9c%cc8lu3=9natB)eT#>Qe^(9q1#BJcd=^=68bb%F4=m&zT=F{!?3EW?5C$=)Lo(x2C z(f)TG0Az{&XMX6u0G|9)9Psq9;=jMc=p-Ngb0YZ|?SG!v*K{-;0@NheP41 zExjIm07>irn9=Ntt!X_SH6l7a6~F)7QD0+!6@>}dAxD`*Nn>!mC9kpZYh#Cp)j(Fn z87@KK0b4|wm6iX7DF5pPYxxlJ;TIz5mG9oW+eU44`xRz&f9y?fZ<(kjZwv6~Pbi@~ zZ*2}H;WY-*$S2(F!@kAlv>(r~vUe(6ws<5NuM~-nS%+W+ZILgnfDOtl3nsAuny$Wg z=zzL=wFCpTc~n=Ii%q5Sr!3`mY&B<7opC-gbY~a`8iU!*n`{#a6NHV3 zQ>f%u% zP2QuH>fWkAwpW3ZLPlz(;@paAK3+yTOQQqm2>;6$SEFlvkYfN<3$|2KkirU7?F6ZC z94|3pF_a$sU($Ox31T=nLn-Mvxg6jo5(W2>&Gco1R&BfyTps|E-2b?6dP3>%n` zSHKE(;_IqTP9Gi;Ig2Ey`2qm+^cKDN4+aRU4nDqj^5jy+k`&qdWppHt6ZHae2>`SO zM)LwBHA<)ShfJKxII76;gW7A19xN-DW~~SA{Hz3MYPY;>ay&9H>W!jU4k&}fmx$#w<9^i>tRzldqw zcm`b>WqwWdN7A4#AQEMymWUf&@LlmmCSb`WH!h~G*aMt++?UMW^r;laTE^*w`pHHYY4oC+fD%a#Rx zu7x#TS<`2P1m~%r<6dvHxX*~&0VV1eoqRp*x*6IIm)i7d>sqf(v}uY*M-wh?OV2Fb z=68vme<)N*_<2~~EtQ?kY92$79s(-G9BlN1$!xEoEFDKWf*$uI6?_Zd}+Ld_5ZKD*2hDNAIn_mbkhYDrr*3h~p6*YXqZ z-r+=*rEVp`p0|vaI(0n1G=v^>%@DpXg6EtqOGg|VuYH4`j$P|X4X?G`eM6TU*2z0d zay$Ke6EY2L4&YuObJY=aa($5eM2j8Wyt_~cfQrlSpNz>mnM4+fG&UH~-uoNT%*|>1 z6x(LIc(9|L-&-XC1gft+#|Ml(?^-R;ek(v~r`DZk6`gKW9NfqlT}wcK|1~GJpz?> z#jxmi4Xn}EWsVgI`*_Jqg=Z20R}8D8;O3@N4z1xcqN?7 zXxf3J$<>iQdaZ|)FN6K;tVV)c&QiqLS27Ki&fCvZN*4Q3i$G>D;QG%SSd7D)j+xKD zmlObjX3|*C0NKa(p1KZ1fD6P$YOHn^>xILT0onA8`M9dvJO@`*N*=@3@oS}}jxu|H z!+C6f5LQQhbn*qH-`^{PpsNbQTCv&NgP3-DZl1yvpKEPQtn;&&Zsh|NRlAile86>( z6ye(AslWGb4Ez=+iZ5R~<`tz+pIumveD}yaVw~L|lzE=NzTR!!rBS2G)oloamWS<@ zKbPQ1i#j7!xUH9)PEI4)tV&~_MV8*X*UbW^3QDna(pUPfS}da4o*Q;`rsr=sNl0%F4lL4xh=5Gbb>^btpanEU@X>0oToOrQunq%M(#S#-<`B8-kX6(Fk@xtWXOck8M^&ufw(d`(o zJ&+5uYQYe_&hq?Vv`5rTp?#sxF&_?;-*CZpL(TYm4+XIpf!|*omsIo@>Pz9rq zHVZ%Vz^O3mm;LzI=e0PIN|ieStL@r?9_k|AP|(xM`@1_UPrA<6KR!g&$}j#Q=q&sK z&U47SSS6&iY}Cl;vTdC7X?ACyzh`5UA04Wa51+d51I<&3q}aFFP*O=yJ-n{PWwZCN zDsE;R91kxn(P9qqxy8q4dXThj7(K*q82%BvjV!0x08wfwd`qH__DX@oNvXUME`#ots34oKE?#ABx=6hPeOD0+el1XulaOBsTX9v)aem#?jj{wi-ZS+SD} zJO5SbX`Ud>GwbhY)2cu4`UnP9ThnUJdhaxzX)iTYkh^||H1e>t5&z!rCnd>il7((# z@gw!ToAO#tnFK(xSBLwVk1V*0IDq`6*!#F&vQ@LR8}Hyp(IKh@?b~bmq{9u7!d6Bk z3J$;c_?N6JRUIEcG7r=??B_#h2posOyLd^Y-qh~ zW91g5pgh!|BAWApn6O>hfzsTO<-$gF_)9qhb)p82TmvYxjtMd#(%%!#%3lX{BcTGWw}l;j~w!Rtl*#NVp~I21ewj z8+o+17)Ot7-k696$cFs|k~k{eBfHz$2E$HYG=CF3g@q{MBwi*UpA%Yod}^}y7wV{^ zv0+sWe=ZN)5f*q{MrhjGsxUXdoo7`w*E~);eJb`#h1iWYtO4LK5FuXR%FT?)$vvx9i%~YuZxW zz@qQr8Egm3O**%^Kd3`S3bGl2zjDlf)`1+x8_g8W;EKId`kLl*oL|d=7=|yW{d4`g zE6GTLj&${L$nZ9$dR!56Y81Lg?lx}_UIc~YGwcVabH+x51+PHAikfY$*fRGo<6^gN z#(;9`Suke#xX=Q~!yO9fq5MeS*`F6&BbF@yQ7Fj2cwFiZ`A599ZpoL{hPbdG zm0KfvT&UZuI$MJF6S)Wg5Q7FqQ98l-t38>c%yzR;UCgr;tBqHQ)0;gs_>nMoD&W(% zwAu{b{tr-Mqu1qB?hyGLHK8p_4Yoqd-IeNYVnZPFpOuYZ_4_l@V5nuht2lFVrqfEA z>5l#9w)mvB(TFuXsky`P9Saf`I3JGH66kyNB%@py$Ne>L~gn089!FM_ZNPXatN-1rUxh>ix)Fd9CZva3chE@ zSlO-JesVc}MU*z7?vn#CT-#*w~B!2YDkH(F$aEr| zsvdK%$2eTj->P!muG^KZWkNC^%t&o_p%LLDy#(-~h$qBXCT%2Y&)(k7%sD|uKXzDv zda#mRTHf(J83e5T)YEm&Az*L zHZZYm{?*-9YjmVP7IE3fUachZX~~Aj9n#IMzHCO&Vtu;fJ^y6NYcoXQdEQ-W%bQyv z>r$QO5|KBGZPl9*CAlbf$# zldlYwQz_f0?^kcXS;UX1Q?CP+){hYLR<$JrV|+v0}Ho zwviGj2~-OG!bC#2igz)EM|Hn|_u|CCU)&nr!Izpz0DuGgTO4!%3spdV%D}0z6EAhn z?7$o8Z!{v!cE3zYbSZC*vxFdJ_5k~LW^h%s^5(|k z=Mt2kVgzL6fGv%9H~*~{-yEfF%&GrpL=6o&XSjzcet>dKjA#c&77PxpR~WJ*K`o~y zoswEtvD^<}@^42Fov-;Hq3~^iZd%!E~v4H(I=FTQp!3BAr6AM?$;D z8Hd$@s4Zc5GED{0^xWIr-IiMALyX%yoH?HIc0%ElL;SKdffYF)GeQh)iE*xUTXCxr z2thJIY@nI$xDw+Nn)k$PwzfaA1iL+U@9e~E{O~H>R&B)EPSpJ^0;t7e?&9g9Ro@36 z^!r_0`{)u?aa7cqDm177Z$Nh^-sK_3dzRiE0*A8ESZ*|KZ?Jb{nR9s}&D|HEZaN>{ zlr45C4-&~f6e4G23KDsIr=2Hp(aQ1lH@-?9Hc$H>vJ8z{C~Ba(PyaU-kAl|cssFf> zSw_YduI*E}sj94P0DSQI4+OJrBIcaaZ*i4n8TR69 ztJC7qhE3gf-Y6V#XIAF#7NotP{UFXLd7G1+1Qu>5OIBs`&oQQcmPun(mJY-gmk`xH zc`v~D98L^! z3rD}o?8S_{&WVd63pivH;WmyPQCSmp8G$8q<;pz2Gyki)RcBuDqoSM)m-puzb~(7# zIQq%s=O52)H~QB;^Ds`p`;O%=3>oZ9+h#peL_QR~p!iPeamEJWnu^O}=3|UAPSCYU zcqO_QtTb%BowvxK;`y8LNDC){Z`0Iot_9!SKi|v=u3tA+MYs9^tHtV;K+3H=yU}JP zev#B<;Pm%>$8oL^zX;m0DvpHFbc2*=S74nDEsYq|6&a+;i!5XFe}z!qroW~ zS~*Fjc6f^7cS5^omW}o`jj&gK`$VvBkMYRNn_E)?iRdh;-IbRW?vFn>U&;C4k0%wJ z6+=u8)-RNUxNt}uCvD$mDaG2f4RMu+EOYV`4^CWXyBQgVktWnvhKrlz3Uh3e@~^~4 z6<{6iA6TyxN(#@ZKWDHqcJ)RA{WD%_HAZe@)XLzMwt(#g@0{~24%MB8<}5THX2E3U z>cW`@cM&9ljgJ6#H~nztY+IwfD*OLp4CK*z*f6B@3XI>z#lqiGY{u`sehI9-7igLe%g1rAasGY6n zT)iVFCh=8AN>n9#+k=-RQ5~Vv$S)pE>~2LZZ1<^&8#{*I-;Bc(_PvW?nFB76wpcO= zhS;p6u)?e{{6gPgPPo78bWxH4UG^-jtRdmC=GbSsULAZ{X>VUokUdspdh3AYr!E^3 zXu=;%4yxNzi{5@GjGM$vYs(!n?YO+_ST9?55s`YorqCJsL9aTAAER}adc4s#j1 za`sz$X_oasp6}hX)eghkqdgAwcsmHQcXSn9mw%`Qs20!d6XMrVFRgoNal!>3DVaGvwb2gqSEHdqnSv3ar+95}D^}AsoL3yt7 zSa}85!9I9)sivMF%PiC?7JB*Dpv6)D8PVR(HQ$)fo{bUN%z%W%xj$mPYSu21zgL%; zO*B@WtC*dGxiVY&(N-iNTLQ?*ByXEJbn#S-&xfBaCEVopsxHv)G_d_XZDBj5c{BQ+ z)=;=q_iL5=wr(Tm)b9EK1^LZ>19rF5+gyiouV@p6%L_-KK^Tte_a++!K#;aS*3vF%6&AoAH;k_K_-n(EL4#YMXFp=U3bFK42| z;c^xTzs53IbM+)I(1a#d95gt8OPS*3TW<+NSn2%k?OE#xE-+|UK2tz0mCV-j16VMt zkWvMfVTQAf>c7Y8A{QXLdP)myBSKOp*%Njp7Hr126a$^+SRk~W4h(hes<7QE=L8>#~wx$ zuuuL-9;3{k-FB=m@2{YybDlrS5VqTQ4C5bIaVw%-j!iDb*hL_G9mFA)GM)R$Hy=fR zm>*Zm>0arK8}!HyV#=h^nRLsS6w`3xI1Z_-V?JeL+~ap+H`JPN=W3$=9`2gh^9L>2 zR31a7(JE-mWX?0A3j;&@5c$)Tsi1yCxjWmE)pOz6Y-wwHf7k5-QNZ7Oq)D`m*SPB{ zBslKK1)cLGY#^$-7%zV=voG82e~mJ%9ge@2@TyYYn|5S{7rGlJZXk2s35YZmNthr& zJjIA|p+I>|WVfF_+EQT-W)PyI`0(3@fN}3rnL5Uth|6KdZcjZ@{kE(NsAn_+#s{oVrPgb07DvS`tWVp-?JYijYKq?liOspWmR;=QUKbEfs*rhZEJFOgN*fz7NJ*J# zYEJG_MiWw8s{sp?&y*Dgv8gcOUEF1xAbZ?{6M;alGxM)HT!8>s1C;^!w3@cSg%q^~WqKwo^RH5&$q- zwRnbtaq-<3(Yyk(+Qq!JHRB}tMDk*C)1)$tKysmu=PU%nK6UG&j%fr;TIBr3_&D@- z9ZmaUt&L4JC4+1c{if*Y+rYGMUcl0sGuZ&b;e)8kqDQlv?ZchX;pXO2L*-wCrGxSP zpAKr%x!7pjNPi^%=#_~D5jJaF%ih_vdV^z`Y?~fRlSU3F?8X>BT?m*3vk}z}U@51f z$IB0vN#}#$#eqVibKa)AVs?J*`y7pCDvK-}ngrKp@(x@)w$#N}l@7f8ABPU4H!P>Y z)MA?D;HV^nOc#)pNCtXYp`X=;f5TbnyuV#N&NhYCYq3FJ;|o8L6+dSA^#`^RgpeCM zls_!Cdyg$VptVjU>#>5>Rc*uYsqz{9?}PiY4T|{^r-%C>^z;$q`|I%^`^FBGJ{=W5 ztl0^LN63pHsa2THIOWQ$9pT@XeAcP!jlytb zVM{M(-!*BH{%pjkIjmp1F1u(}$0@(8vx381e`aeq0`llwoT5U*!*6HXk+Q|N;i?jD zoX?f#-eo@gg{Z_75j3MxcHDO;BDbHrgM!vkv>-oUUAtj)oPY;8@tIk>i0UcSKm;pX zdi}xS-^`mnNNGG9ev2%R<#F;DxxkmJ&i6D(qXc`z3+D=hpdfQ$j z8dLUO*6d|Wf_hux(72WKnW`CujI!x^d_>g6TMi;So7WYDVj5Md07sF~I)65m6KL`! zHHp6)`@k)yT>QBwDZIm?+wZYAH8DY3LzVcHMXfn{`nb^hXqAbI*@}Z^nX|#3>+fSe zvlh2>Ds}Fa6at2nONh?c9q%W+313o1W$1R zbKbL+rnnCpe>D>8$glKIJ6@r;$p=TnsV?mWd%w7FKgMK}kAm;vI(ms31OyzB>^J&k z$$|HK&%&h0#+yGB(F*JhOjtjL>Hme-#edhre;ssRP&^6%z*v~0X*5129FHWYK~Y=T z@hG|GH5g$unmTR6f=ZNH|Bt*X`4Nuubo!ah7OI5n!oVA}r+{oQc^AQd*M&-fas8WZ zm5s8TuWDN<9`^LN_fUBPJFR{ecUB+y?#Z~@^Uwfs|5cZ8>WaN!1O1{7geA(h+F|P`Zq@{yHmo-qq1)y4HXs9Yh zU`2_Pj#?}m(2puhUIYY4aup`qZr@0AUOm*Hw%klNg9`nGY%}rF%`j4a!0KbR0L~!J zfR*iVfR?rs{{&Pc5YxWa*5PgIn;GrU1Q4KF&x)-Rk+<+?^f`l{iPw9;JuFm(Ol1>z zb2xC5rKg)kK0jYe(6rxObfLpVa#p(}LAKdUdp+vl+>QpwmqYceZ&TT_|JI_w)~d9k ziXX+a!~nhfQ&i4WtWb$6LiN^j-xI>`B7Sz|(Jq(QwPmfqP>Qpcr*HA`(TkY77GpAc z-Qpc4okoM9<_JoX#K~T)otQ_E-;|ECFAXZPe6v5Pw^t$j_53c9>lK+{j#(6&1IS03 zp67@v1A)7?FA-32F`H9u!|&}QHCgR``e*6mm1xoB!5fj! zA*~_-upckRNxXx6@&2ZbdUL;y%e^18FtBw)tuv z3K8&j*lxiVk7ge3-^|dt^63ouODGc}X$X4PJ>eauTk(R|%`TV=Wg=aqr*Qy8#(p$e zHi(!mx?lw*7TxPPKZbPad;u6~H$kDhlJoxPyBX=J)=|{&Q}<{AbgxiZKY*X6Y45{t%QYE+o}1$O^b>?D z>F={BmAW_XERHD%ql6j_MvD}Q-@e!yn>H-$J)R4e))XBXK;I| z$LI={heiIf&RF%kY@?hd5QeFUT2TIOX~I9vZgxLj!M=^(tL|+j z3jjbA@r61|IIL#ESD|I_F7~i+AGe+^W8nVjTODHpnJQ(6Y2Bp#K?&_W-sheBk$C6n z-#%x)?f-%gtK&N4tV$^$vA_&cYhs^^GGaEOHGcb$u-%T6+_T8G?vq;-kX7=0o zbz<=Jg;K3vUphG)HxxKOkozM^2F$5zm!53-smZYy|3%&f5hz{mIVj84$v0W$Vy(YU zosT#nguVOn1Yzibw7)p1U8aCnc|R;DAT;cuCw7goK6t^f_<9TMMVZAOVeb#fb{X4_ z%#w2X%h-w~N6NN)b+KqZW3pwZR`un|qbeiJE_Ia7r)!Ox**R29XztQP^(1CHd2$s0 z6HIHuR}G#tKeFcPns4u&`Xx=kI{BlUJJ9&{#-`ZDh=|?0A>+@)h-%ZqiFf26a zTGwJX3W+C77#a`Sjfj-+&!ZqMUN}jU9gc>UV+3 z*3z?izbfXo-73V}@eHJ*vUna(OQm{FrF1#}EwA@*k|u- zrwQ;x>8J_r|iZ;bu9o?WohJ zTbm8?cJs1LR_2j927Ne4!6Q*8SYWvLx$2Rm$G2H#W#?y(3b5$E1 zR&HJ}b;#1NZt-~jmUGvWC*9vy-A_M%{w+7-uIuW*k$Kgt+jNj@+i8(B+)K+^gripX ze&MiCHoB~WDGe*vRH`~Qe^Fkz*{>nIvbw6ZR_l9Xw~?Fl9QB6%L%u;BJKxwnnFo@s zd9Jb?}ZAyQL=6I-W)#Zq_TG z5-4VK_b0a3BaqKkDzuor+(1SY@M~sG`!PV$-ajQAE7wVmltGFx-1Y`8pa- z!>?4bA=}88sf|PF?^^pTM59gmXcueptOORX?Ud)H-9LukaBq@m+r$CP+K;4LMfSs$ zyUmHmk-A@RS^|oha9B7<3`wpwr7-F`0@~78L|sb4&OIKgiCeP{dUYH7Y8+(uwK2wD zPK?P`s)G#N=;X|N82vwFkGvugo(u_Eu&!F_gOM+QE)Y6u)4_RuCcOa*lI4lVf;ZO_ zg)sdbL#g1)dU;buNJkRuaD$vnY*Z8{SKmIlYVE`By)f3NYpOb=VcNzY@p~VbH%v5l zw7h98cCfNnJwt}#XV&1}_G17Y`(JYR=d!@NH;F!!!Q}zv93kD`9j04_hFJu)5wR+n zsz;RLn)a`FwYVxm->+pTO2yY-lQa@VJ>6-NX$on@Zm*IiTNu4&>;ScqDt&O} zFHY;*8K1+6?X}8tNG~&T7DiTWKx!w%NA^YdaUsY-RNmm^;VLridQ*axnL=N&XW*`7 zkt}lx<9TKt!+a~264Sgo#DPsEZOrEthcpC(uYzG&!Jwb)+w#g~o6Vway4^}dD-eWl zumsQdbKldivng})a}B7DJY;uRuqM&ny>f0TId6BpXk9Uw7-7bLPa?21b{ql3opR=5 zUxD;ie-ZLAS-8mQLdq9u-3htgZa0{yl*JP1^+tzCyC(Nc{Dfyg?Ip8ELfq@18GP`P z7UkZpKW{FW_nLO6oAvD#6vXBhA-S#a56(cJDG9QhMgPOFJ1SLSS>VFPABpHNKSH^~ z5G|)o8p?^ojD=mWB7?UnGR>714R9)n!hK5RKhiCrj3 zZgb|lHJ$*ELk#+fVkPD1i*5#oc&ly<5XYcolf#r-zTc3x!PMc0#d_SU1OBL5Ur=D3 zPxd`zhoE7jms?W8-9Fp=DMyB=uSZ+8$En}NnveZcwE%UI#%P;%$_}Ec+#!n&eOvO! zCE11P(!?a`W^Jvnec$KQgvTy#q=lKqcT|@9JYJsfBtF1eAg&b<{TEaS9Zi) zlW5Ki$o4n^qJV~4u%8=!a~BaSHpkT4nrULdRrd%h;L39->cukbIZ~l}gkI^}I+^43;%Mu7Vm#$Wu##u;P4zeRwZo-ay1j05)yC^VWJ!=de9& zkysqzr4MZk40ktUugjy*TEw|btAeR@ysFJVE`if+4tY8lio<%NFDG|?#yoJ2o|Q-8 z!f~BLV}`n?;E`Tsbq~8u-=AaiiG;krv%I~_A4e%YOoz^SVBZM{&%L zd*Y6hC%>rjLdoUM;hK}r98B9YzcMFumv|32jI*i~LC@w2WJz|HyV2K`1mlXak?wlM z7n9K-8Ke?~2~h!4N)NS!W~~h9mGh0~yzkNBg!kuJQlEG{c;hnva1il`-jr{;t;A_W z2*u1O;pEHF-Qf!2BIM3ekIky12xeS$kL~b_O;Da-CfD*GLW8=FLPJ^{uf0riksKWw((q()uwFJfXki;mgf~JYsLs87|H0sF70CntZR?g!+mV?5P9t zC4NPr+geEMgDN=9_RV zaj7BOfc2A`h9C(%ot7;G>(+=2B3S5fkxZm$j5OYfQzxjvwP4|yWhRkY|3h=$_*k=sTu0ducX9B zG~C~+44Pl*F+S`JV_T-wmE^V1Bo?ruewI7@s@?} zZ}ps`%-yi%er$ZU?*!(ZDQa=$ra;=7ku0Ndlyda+cozepsFo7}GWhagZNhhY$>B9? zpfm<$pDICe&@XGc+W;ejL%HtE4U3cQE1;arQ8WGbZI6YlJ7DA2q-lHyV#uc_QwLxc z-P-QQY`Qw0d6n7vx9Y|HYX|QI>No^~W@k@#F6y}*dU(Fgd9!u31dmngyxPzd@b*n( z|Dnfna~_JNX4$`~%?FiOAsYeGLrR-#s%_;%BHp&fg^XyEg@|w~82JmRxix!YIJJeQ zUPq3$4@{J%+C1aoV@p{WiM5h4u^gxDsvOq*d~bJk#`lUO+aqC)F7 zf=a5H-g{?~L^ZDUA(Afb$290>P!&i zN*^jhmLm>B9PyhvdNV<|gny#mINovBH3I-r=joKt{uIy!YK@Jtsiqkfhcw1cd=#|S zN^1@Q2`@|GC^KQ!kkt|^Hlf8y<8G)e-epgzLq5v0FtubJh;g$S4Q7bJex_f|ux(`UV8M>jAPaazu3p4B|(uZSkF zCqzZE)PHm3T=M7?&WQY69*X}WF2>BSj@%Zio(CB25KBK}yMZjYnfxv|%!2D*?8)uv&(DWH+}{P(8j^(> zf5n4UIalsD@+VAgTXfdd0h?MfqNqDO4?Heh*(GAA`gbY5w$7B*?e92T&wYkV6y?qyGwwl5>3X z>!)RUcKuk$Q&NrbLs=#(6v4flYDZ!wglA>uJh>wj0mjxBZQzq_pq-p~e=qGfC`lQz zW!YgEr}pqx9p?*Q>P=bl?0tn&;3gIw9CC7dkvc1WU;IWDDzmA4t|b#iw!zc?*4#E`2*b@?SIYmxbIQ{x!!_QX@)C0QT_9X<)VYgdcV- z_!*NOm9mfbwh1+ouLw(>JtU|h$RZBC_D@k3%Sz;Gv2LlCyI=7SH`~_R17l`b7ad3V zLU?s?ESyad0)BiACN%^pehU3s(=%mtW`5l{@%!Dr-y9TX)@FjD)7hoh3~n#9zJi~u z4%lT~WED-nKA;uw56l1xDUYi!fwHj1Xd_!PCc}LEQ!oLNjSMJm#-3GVX!&HExbM{V?66|P$gpWMSW@Ac%06IwN=KirPBK=bc>*7ZO!T&?>+XK3vj1^! zTUoG5L+epU>rUzUZp($TMJuvb45p9_exAodPud(%;(41a|1%^PxDuK zM}%_YVNdZH41YHtmWy^MT$xh<0L$M|FFaRs5));v)Usz-D4^a1q2CyRHd~9kLyOS@ zK@`&3a`yr&W+36s6b%D%c1CRG2-3cwSccWXmH1W~`@2Mo^oNY&|cfaQE=RwlS zEuI|fB{c+uQIb4BJ*|bFJ-fQC?!#oPyb%>_)AH4aO-DnE8#oI0@7SlbLZhS^D$>%1NCK2obGXDO z74Sq(*EGtb;|4~G^ki_JrANKc6@nT!qKIuy?P812XdiooCMXjPC-z=zv;%U2yFVp8 zOhpY8CDWewnIG2<5bT{$Ck5fc$QJK{&^bfV4(41u!8EU^PYI4A44U2WIr7=VO2Qsc zbT9*bVDUSN=0yJ>1c@;h;W1f@LyE#@6+vrkBqBA;`;p0@2-gpiTzu-u_K6I z8hY3%%b;3iKp&T0c=jUr#gmz}?`O3w6%DRJ$}2Ha_LPj9WXMytn*27GtLeeP^sc=4 zBlgsdP!$m-I#hs`(L!vRilc!dH>>kP4Rt)-x7u#}Ynsu48?rmTPv7z$)?=ry||C^rl82y0CM;d>G}CYeT`tMsx!B#ez%A=EXG(%kBQ> z(>sA9ACsu`z5t2k`xg)|@}d7W3qe41z{e9AlrHNVu$!ewgrkNh8&sCAG9=wn*1gEg z75w>-$0Knou^P-t=p{}DNq*ltP=@`Z@I&6m*+fKcZ`_x-ctX5`zGFo`tOR4($;%s5 zuzYkS(e|#-blHcnTI}z9tzbO@3!vy&v@ASpr}>&f9R_v0djnYO72a8 z6EB8}?GY`-HG)z3YE9ajk+-#x6%xocKe_IwRt2!D`$!@1<+9BX~hvXJtV#?Z=R4a&lc3B9>{f4lB<8^rkb8p`}N zcYYPYGh1>}H^n$S+pj-^d~7dfLU?5NgN5;b?+gXmMS9qik zel{b&ULGg&?h7$i!BBaF?0*G1x+GK*ULO&75{3Dk;%7xg^o|e~0bJBjb4RbrrLqt( ztL1AQQ#0BdwIh{GKCj`kDWJa%*zYIBSKE15NgB?VuIe(IidvSD%XUYbU#gs-ukwyi zV_V@YJrn;ALR#AtDP{#;=DLp?gO9wgYU4_}Upe#!J_vS@XX=`PtL@1|9;XyYG7c_j zv`wK*nKk2{@Ir@(5zCT9yO(J*vYwK^e$U93iRzi7EYjf)R*md`LCVdE5X7$P<92%( z(@A>t9zWg+VceFiqBFRC_36~Y5cbk-m7aD1Q-RRkJ*v`$P!+B4&due0!;$E{wPBgi zwEb-4qFm|)@4H*jN_ke1vD}f*&EcP#vWVCF{wib)fNY!p%xQ7A9NHI=#u1eIFr;v~ z4SupV++&j*E|DBHN?3OeD@U6s^B`mBUdvpl9i&=L75V1S!)cp zmOH{cfpzs6WxxwQ-WFbe?>a2i&L1q*8lT~unL*E5yf@7lB*bs$WS8#CK8+L?m1JJM+Ny)z>U#@O%%Xsi8p)aT2hk$wCM=Qh$fiu z_hd0E=nXNfJo7kAt*g{6ja{99Uhar7L&=tBb)A%adMd*|c#+tZzL2+AimJ{}^E>au zmf#tvG4uHuMha&Nzkh#gemFx5b7cb3Fm~{=qk{6{jX!XL3Fr7NTZDWMtbCcsSPk~P zajtA*{pfuah$6Sk-#F%AlxD52C;kzZ?DW|JZxasHVCuTr{YNhNc3d zR0|5C6b0!WX(Aw?fK(Br_ui5q3Q>?Eyn>Vv=_n=i4iOMh>Ai#ydT0qHw2%gA%DUGR zILuGaJhK77!*A`KVpBy!_91sH{AZh_k+Ih8$f1Hy@Xnk!qv^ge4*AJcPKihZ6gD>M z)&}OesHJw6|I%4$a6HsU9{c5mXSb*an8D!ovO|d5zSn}I|Mh0s^sv#F%y$b3tJ}4q z=Cr-$`bVFOEhL4<3qhZ&-U{;gtRi+gxQ@Yg``}f9XKsKmV^3PZlUwqa#=Y|pPn%5P zr+iOm|9#aw<1!Y%m*-$w+{mlBY8K68Bb`>xh(;m`D9O7YF-JQaG~1gBgHk)EiPn`XO=IfndY3=*hTOjcq2-+qPluc>kd1HJ z+FR=6AY9o_F;!1mItdYkz^4FKwA<=E*=j*9CZXJefu6_Ty?!W-vVNUoX$Z~rI2(6Pa<}^4o-nB5 zt#-Er@6El7@vf)Dj}Ay)HyYbyl&WF8=CP%rVSvS5-W>8{E)3de@KX$?0}AXa)r_Z2 z_b3SAVAk|8r|~QxDIM^<0nLleh7K^g0z0Cn1T#BWO!<8*ttYv`5-OcIm$Q6eKOdJa zur{U)UF{ki+mdya)950?wX^LWZIJSiqN!*K+33LW$VM5qF=Zq(g=l0^3aQ9&o<`j$ zYZo@3-L&Iaa+_fBxH7d`nfpm|e{738@L2KaW$+MLb|v`H>?hboIPRj^nVyD(3b*)d zf1gvJ04b$v5a>f;5Kd^uP-gRp+jrK>j!^g%bxn1DpK)*1=kbG${uRZ>8?8~ypCs+g zi~1k!4?UpHG?VrADZi(!B6)Aa zlT)Be^7WT*A7BN98<5C)&go}ga2)JZt;f4I2`;J^p1!bVh6}iwWS~*12Lo|x^z=&5 z@vpOEe#U|yiIt&WVeVH=dzxoCxFOBDe4uusn&0IA?| zc~ADXmF9X(rw2E^LWAq;3OhRCT&Fb94l=FLml>q^Y@qx6=#g+RPVKyh4E6k27!=0db=&O?89j!=lBq zD-R!-A>UiUY+gvFw_V~08w_Ax4mRNDKL-c-+So(}aqRiim!G=OtO=2+oxyRM^b8X| zYpedbjO=P9_lp#Mds>38@Iy+zd9$`~Iz7cSvMDHDq?&n>{X39=H~wXm5+x^FwGJ-x zGxj#b=mQ+gqXUg#dPCdm-p_fZxz`@i%gUqQWulz2I)1+2Yds6YWuMleq|&e~R`}8a zlX%x=p4~Z=^8WjpB#*;D#acztwiy>_^{m%x=eX<5nv=m6tMNAHJ+|abl6a&;SkaIW zaZ4ro*WRZrBkyRer~Ou&ZLWEP)Eejy7s z7F<7|R01*W^fHpeQPkraC~85y{NG?_*DP(UM)5ZDS$h8HcqJa#Rkw4WllhLZ$70j6 zkB}rn!(I3H#6X8hLY9Bl#_0x|B7a+DiXR=2{?|C6$ZKl=kp8z5T=&rZd{r?0inHHSe+D?<(Yw{Y(K#dtN+aU zT$ygV_>O&bPFvkdOR$qcf2^Uk@dZ9Jl&G{B&u z?;!>jst55%vR|7(U5J6x~8Pt|c=TdsRv5TnfQ#Te64`vCN49#PX8c2|BE;<=AWyxI!m9qxVJ}RRa>FQFE<$% zH&wLcpz9S+M26vAjTW)A3SJiH+8QRX*041t(%Y# zVteb}^01V*p2)NI;8X{f^x9apo9^5qTFLH7ku~3QWadDWwlaFL?A=+o-B!^wLM( zn%yq88YrQR!hd!JB5Qpcf1Y=2ll|vXfa?fcuVPI=j+!=|6ty#aOQ*)nq>b) zuFJ*gLIQWVp|alox-Z*nR4)q;y5TPvVU7;5@5M`GLLe4;ABR!YS_EAHv7!obam^P} zGEk1ny84DN$c$9YAW4^r0szH(o4^xp*Oy<%o_X)vF9B=LzGJI-C zNW2`v!B>xclKA?Z9BBC=m$~=qk`IOg0!2sutAh8To_<2JP4)^9ytq})C!L=4(g~!)> z!s3Azz%f~9X%XKHkpHmW^uV~*q%9q>KAnfRuM-C5@5ljeAqZ6UupY(Eu50=V;2gf! zS)}u0pnt>?Tky))2{xUBkk;Bi0LO?8pkYQ%k(yg$i* zRv#QcMg9a#3rD>Bk91(!ywJ5lcOQPz)su_IZtDF<83=g&|I5Dt%k;lw5l`rWC&bbJ zj{j3W?|ZtFsa5y=U2hE>bq4IFZq1x1i-9WlO?oW7bYJ=KH?#f-I002bD!M?-v|lg( zfseF~*X$`!RsaZgAkd5}uH;LlveicjEK&=0w9a?>W$4BE6C&EbCzEG3x5*VV?mXm$U)jw0jwZN`Sb$N(nw3R~kCs*BpFvn^eilFR7C0*D-Hl>bj;3 zJBrD$0X=G_P9~CPi$->l{IFuT%pkvh5O$`dsH@d+f|`$3_C5|L4?1cxl|83!Jd1S_ znwN-YP8;g%Vp1J_-Ey$o$b6i+@e7m&&@%(R(l0Fiiqh`zr@M-Ktp{t5bbX4&)fpuvI2dp5^&9;C)T?0NjgCFv(XZ5#vcJ>4}rdd-u4 zLzjRmh`$IVg=@xE7`kSemo-^|;_^P4_0e4Q$)Z^mY%jp!O#QKvj!X0LENPXl*mqo$ z`UsuwociYV;76Fb$PFyxaoFu~eNaD>qx-*`G+Z?Q6}3S50sHh4v84D|F-x!^b;;gu zA}gRAvL0+7W^aed2>yq3E_~?(YdRTV6)PUR=t!Hg>lcj%+5VniO`!AG_JAloz_&Sl z3*;1aeH~Qwti+^ea4<0yiDZR)+V%3Y12y3t-So8+=8!4EpV^A5{Ns~0HQ3iz_=Qr- zXLf5tuG+g~)$AR+)bZVhlZ9shVBe#l#9A46I%#BY?L2=}Ilo#IF4dx^0Sl8d_e2KO-ty6?R7sbn_3x72VZPR+@0!J zJ^Z|-tKnV$QLj+^>VHEpjN zwF4Zuec+gZX*RvDF;$bSVR9x_25!)}wBR-K`FY(r>-z-H9D%`7Qr)CGcL_JIbg&0^ zAljvhrMlGbo@?rK15gx%bxy59DwAhtUt$GtW4le9r6RS>xQ?Q(biNe(w5wQC%ySb|u)E_^mE5mUlb59Xn?`G!>h?0V1t;n5r?+U%G-UT&9q zT0kV}vwiAxFrJrGWOMX4H!JSmsa#@q*>aI*3wPA15&(FiEbq0UJW>l_?lvBDtrOQS z1kncl+Qr*!&PH-KIA5i$zhzyR^v>ST_a6{aA#FI0satn_6@S#1l3b%_ zPmP_yO%m=R%#<%VDsSx@@9*w#U$VOe1Z{y$6iTjZT1aL$y zbqo$Z(+8^^thrVKLmBv3KNLHok&QZTB|f9Sr`X4M{_V9?-7Oi83%}S(E9x+s>wAW( z$NLf4WB9j(q?*kU5h@{PH`CNxt8eXcjuP+`OnS#hnW|lS#S!7pABt9p<5e`BIx^^t zva$fcg(v|qTGM}`#t!Yyw~w=coxJ)O=1IS zhdkiXcz_$Ax+g`2dbm3hyEhLTYHXb{VtDu_dn#SJJH-a+!hKkkgC7uCAvs;8 zO~i|(r%X4yZhw6_%L;>5y9W*bdA+O|0CBPzIMk^?EmT9RJaZ=u*4G-XwB+A3#6gb@ z9ADA1i&{-kv~XXTp;!AnD;zlHk(AM}Ighg(4^EsDTl_OIoksTs4C>z5_-2cPKUGJs zTH4|j_GGOd5=ztIasOQ6SgGcjl=6;wQL4`)UsAVWj6y73xqFG@Jo*41$mW?Ia!m#) z{4`D-UyJHEN3@jN+qI5{@^F5LU~G(S$a4LGweh3g#=;ZJkg~WB6Q9=xD^`4E;vvsB z?yo>ml-2tPIjA8{)Q0xUa?ZVp7xRnnW{5js2zK$NUr&;JJeMy&-TSv+uBwa&?`(I8 zd2*HNtB(*SDg~Rq*=g@rVzorMl^}C$NNvSjYycMz&lAa7;~d+gvLp5{Oy!O@?NBR5@D?Zja!-BgvKV;vOqzL}3vfjC3s#|q*S?ls!l~z|FR24I_Gasv zEAeI{Q*6{2WtCgHd*P|9v7kQ!H)gXM(<;?y9>f0H|Mj=%^ESt? z_K0d6rrh+mgx6t0W^p%LeVk;jH{Mfr6Biiq#bvUpg&WP?Rovy9-?R}U&JQ|OyZb#S zylvepM=5i7q%Zz%;+@4YM6%Iy0FFbDt^6nU)xx1xV&Ejr)5_}nsA|oAj%~E1!NV&z zzF&>h0&|5;N^zCq%a)eRQ7lLaH#Y|`gF@6Zg_-#L}j7qV*(4trqD z@}u5U9=I~9dsb)ctuM9q#aeh7S;|mI(BPlaHv*j~Ub&F~KL5v4eHkYBhmELw!ntGz z9R1E@JVR$0#Y#oJ$60o2UZZovEXnpb!I}>@Q030zc;#@rtT#oZtw<9oW=oj7TGk%+!<7J_)Too= zx>4YHcsS`4TciddD$m%^I$nOw@1Mdllr4_7@JT1>of@~Yf}CP`R~XHVWZTiQGeg_F zA5zSHp^$AA4cRgKexb-PDA#}MGn}=WDUZ7NR6Eg+x2|`cpV`w}k@KC2W9?UxvrATk z(t7&n2L3H%p^{aS@ABg{UEllUHBGu1)3;@t>F6z`q<^BiN$oiSln;`VN?^Ir7gt27 zi|hHXK1GWfz}1nv4$)d&qRAn_*{Pt+2=x411ZzV0wHJJ zdrPI?XCf{xpeqMG_Vgw6LjLQIp**maW3Ka_-pO6q6y$lnb_L$QYLvDeHpj$)wyp9iUtDddaQQx`aaeuTyCEwva=UMIQvOLUp15lp;|+c zT;M+JhLa5?9pJ8*rNx-j4tz^s8|3&_ayKz%%u@u8m!V)=iG2oVD3NjL`i%j;w=A_- zrm-|J=n!BXIHL;Bp|CS2J~>7bRhhUv|4Ne+cfV#3z@c3ReXwSp{k=y&mA z8jW+q8r!C5?T$$osr( zzs9)|@LmHl^wz$m%qXNBUO}pj1@ng>ZJaKyf2h&R2^LyauVoKBSA59B&b?s~NxQev zxiS1bFyberx`$P{Y6C*TJ*jHWZW!>sX;JNNZOvUFHkCqq8CZ8uuH{!~ZcOfgrGv17 zE2c_5-U+h|H3*`2~t&Q95k8XyB>P@nKmi(?LLAzT)Iw{|c>&S&dH z@$*fP%rp8jynq5g;_suXVw`r6txgWe%s2cfi*~W>Ep}m{FBJq8w!cI&}^Ebi7FT9rz*pxvi5p}~jsU(c6}j)1)of#DyZ;V_Jhlh4!}Q;p}pPw|VD`JG-Zv4;`J-$SY;3 z$GklOhQIQTwDEH=T7kqGtYE{*0C9D7xxZnuz@PZUmk4NgsxVv%Pl(826V(5b%YLJt z#6W&?sb2>yL$&Q2)<|+#t}ST3{&OyX?xA@UDnr3OanO~5LM2=)jq1Ai&d9^jmf{`&m7EYelw^=y`v^C+m-!nSf|B{+%Y*?Gh}otN8;E z^`4S@c94*%BzS=5pNvPCR{jcc(MVTwY3G`O7*j_n5%tLn+LV-r6lz?)^(<%qt*)nv z!cjn=!k@*B6a5lVgHbV^U(25>8MnpB1$TG~PRyoF z5fi+$3*J#;(0#X3@e7~Fvg7qarxdEBJU>9hQ18@NJ2q;b09tbkf0OpSYY&RAY5Th6 zW_=wLDMU7!^-R?lkjy8ES485ME|d=jgk&Gc4Fu;iicHxF66hI|d+)EZSL16^-uf;{ z+*b;umOhOAR44A4R|1e-1-G_x?f2w0ExdA!u>Qi}JTXZVv$f z$aa6=xAx(dCo7N4g|j-VN|%moeDAJo3}A+D<@81qww0$5vD6HyD`o6w3JX0OAB&!u z4fkNJUN*VPEfk3=A|}>P`e1@n%mHRW2u};3#`AcZBr$MTvhtqR(bl};)oZWMA1wS_ zek!2yodH=A6F4a?+N}}88oyxxjm*`>KIKvq^I&-PY2oVRyLg*5nvR6!$0a+%EPTk* zAA=m<(4^U&_8^23pU4%=OskB}}wBrNCM@a)3OOkE~>u*&Uy#cF)1D`qdS**`O{D#+}*d@<8eWm^8 zKtO+(1n~j_JZ-@o&mF)NisP?{dJS&PJWhXXZ!IVwU9-pAlWD;ZlRUa`NDGvN$&Bm& z_5sd(iDvkjYXePMC7J37tx*D|_IyIWA=J?Nx^ z^f6}bo42kml?ib%w}1W&)iGeZw&Lx`CsDr{<2vTaA))fOQumP+t0SyotFrXA=(fUj zu2Y@N;nt6@Tq7fd!O!PPSvfRGQ&P}6Y0jpSEf%SBywhWir1pho_bD&2_#5~SHz!); zzgmXLwmHN@@0anQMcVS#*E)}vnoEf$^(z&rlO)$dDHUw%w_#*EFx=}nnY2j4{b|;^c z!J$+7QC>2?&iGn2A3T=40R4ViU9DrW?@#|q_*YZB(&`y2{|%!+v&%1HX6@*C11^zQ ze%4O~RKAd_T^gWY;Ur*sZZ5GV?Y-2ueQ^<9M(`)rdj$Y;@wUy=spr1dZhoU*_kwOF zCG)HGba!9L4J2>BmQY4Q+}8Ke$49AAf^J#}b{pB?-wUdwtBNpZxxJ%;CfTIzWu?US z_JO+-qP_lmt18T@`QfT4-|Mf<78%%IG`ihWezHa%>_-z=47{^gjdFm9VO@qsT4dRi zk8F`Of8As*l6=g-O*`_a6(9*6 zm}2n$ul+4|e-v@8qq^!nxa|u_a~7@MIqviDz88({znofBIk(Y_3nPnuKN+83BIjxQ zQB6^+=~KE+Em(&!wa1a~J%f3FSlDKO&a1oup+-SaCP2&>8Vr zSu(KltviJaV4gFfi5!ctAYY{vkLx{l3uz^braQas*`z?>@+cKo$KG@XL6m!9KIUw? z)xO-HZF3ZKe1dUF?pfidaux<{s9CNWRe$4w&*}3$DY^ZH#+Vtkvgsr8TO;yt>66yj zD78VK@%?YM>n%H}d&qX0{nl#Q+JeFZVoiDL8IrdjgY>;YDI-${!P*`f-bc%7#41we#tuL*u$`r%cKBumYN5hQG73Xw1m3h#5vkq4hj!Cmk`eD;U|f_oo;0JHH1fTmR(PuS%A3{IG7GZwDO>Or(OfPo_Mpz`? zK(!UYiTuA`zpwVl@mc@?B>|ROk{9c1P|9u=Vh8J~v%4UjDyY74UE|8pb0Nq|0r&nG zZF?o&oW%J$FP87<*Q zPUouFR8=0-qwMt+Wy+L#k34Bb7Wt-y2fF~QHhKAn`?amCmk1$AqfbjeC!0*TrbSR7 z9rc!@-O34N()KwK1C+aOBg*m|Bkisp987xKVSE*@6wS>up`w=5=8ADbSGNlvX_TSS z{vyYv(+GXcA$h}O@^XB&dzB&!J*FKeWkWs0W-?jRr6?MkH36b8mO}I4l7@ zx*hMtV0JaOttJ}NK#D5LcHl$xOMAg5(Zx3oOwkW6R)dHv+J-dxRIn*IH4-%3hH){V)ri16%Bgh{DFW1%spOi}Iy1Xz9aF!-JOTSPA_ z2}%8(KyE7tNG)07j|ryNPK#lf*y3dd)tsdRf{c?eaKRR;B)4v2?R%H5$IsYldqf(C zW#>a=j=xrdxglkn3rOhoLxgECJtI?fGAqocSqAO2?FG%>Z#Yd=)5|oC$QL;bt5!{k z1#cO^TyhCbQq9_HTV1#>F;qmfq=Djnp0oVyj;q5L7o+I8N{bD}b9YyWHoHYRL(Kf& z<3s_H8EM7;dDv@=8xqiM?Y#-+;#ewoujzv^wRth$8P~Bnev6ggCf$hfSfR>#|D>=4 zK16Per=>7VC>~>j0r8_BmuEhL|261iq<+P>`lOg`%t);F-bp^e&+qv7Z#zRzL2Vhg zi;ql5)8fOb39>ws%|CDnO6SL5(yzll&ZW!kKO}So)Asg#6&oPzHzw3R$w>qBV!#^= z9(-pg{2NU*-w6uY^UYZr;_p>b)-!}`^=)WEM?W{8geHDZg4j=ed;glz;t-Z&yDo{3 zSX*H-9jDNB0O?dGAQEx=DR*o*(p$7^^f~2?Zy z_?g&=-+czhlP$xuhLdsp%rSVml%a+o*Op4t1tRZ+;Z>i|fFB>S8V+NfWUajYFF3BxE* z>dS`_BF44bsYT4Yw)9p8Ko6mNvjbD7X8A&pN~Tk!v1-g+Td&Fy$$v7Bn{x;170x42 zq}8(CZ3W}n7)WLxNj^;+%>k0s0`#_g=YKK#&itTD>Zo=dyP;eg+S1zUWcb>_;a6_n zrVuLY;3?0liV*{xw?Q<%G)|H#noz)}eL1sXhi`CmEb%6KD=!0RsQGnqX z2wrpXw0ToRCu&`_6_=~tR1a&qm75)KtMnBhAUf`ffI0-jbkRsP1Hk&d#+JMW2+ zzBwP%RiLx`obBOr4$j&Ilygdw_hWxM%Zja`3_@ttaMSPbvrxw6qlA&$&+Yt3;@C zoic#wOYB(j@jesE7i1+!;p!X8H<}N6c}Y9vklQiJRPxAI6&ox5%R~}-G>q>iY+QkR zA=iKJuvn+dhI94f-%HmJ5NQiIQ}*!Z{QloWiNj;*hzrZ9^AtU!KAR9vOqAOcm{#`i z1w3YeBae1L(3>Cs-G&)4dq7)>xFd)5LcE63mEcUR*9b)0(8UH3pGXofy@qh(v~}1m z^G6CKr^8v;(b0%2|fwmWO3jrqlV-ueLZ*oy`T zX7Bi>jfu;!u2G9w1bbM=M2AOYF}#V-Y)5@@X{_>INrMXhFM3hnm|mLSykq2%^FEH0 z5>2@}wJdL*?CUBPrgb`8f6nL%$kxkuwv8U>S0pr6ZrAyWUNt8t=M!=$;G$J?$jD2_ zkT94Zzft%D3*BSgRJlifm00Npa(lafw6%n;(>#ii`BSo#{kfDyIXa_E$&Xlx&KyK4 z?)<5~T*RY3n>1^rZx@oG*mPViHczcb`hjIhQN&PyF88b5iWF#rMAYx$&ugWo8K55` zA6wF^zm#WB6{%K zE_3r+Vi6R~brI}_tj@vpKlL#yYS+-G0|Xhxh%fbpK~5h)=a+8)$ykpdOf(q+-HNgK z^7vM8>krYKyB^X>%H7yC6xt)v2%mU-I4(PEJKrZlIzB_cC&{h=+3g9u2}|*Ne_v5+ z60{cCH4!C18jC#G5d2fI;{)#skY#%phE!s2_AyyI>_Qn-Tj9VGBfJIuI#o6)k16_rU=E!h@zHx%O>2+}Aq4bp`+1ay)nd_wOQ99%S9j z8%I<%;2fJ@58NjMoB-!g%hj;s4iqjnj7Wa-%(5U}OZhH)Snm0V7Q@ZHnXR+3O@mgZTK^~IySwLrE&f1w>iN4UjL(?G4pQ_afuh*QO!I2~w{ zOEBrmgI*g>FmI;8mBRY2?0sq3pH8*GAxo`COV?3Fdb}FP>zyg>;o5H!8_??nSI&ZV z^jHr9vu$Kl~vJXlWCzsRL~tgB&l5Nk>KQ2)253B7ay|opHY1Yx2gq2)td; z)Rwpu^LyyLXJ+K#qnSU}>X^kC*z`eIierJMv^V3|ka*$ShwY2@2>ja5qXA$4v|#kJ zug9ykOWZWflw!22Gr9A1T2`W8F`hn-g!a& z+!vcF0JzY*>fT z8cDa$moQr06IYsYjDEbTS-y<*{RgxWNQJ zoh2iqpvA!Jcf@1ZUQKLjACIkN%6PZEbTk_4aooVMksIr*c(+HVUYTX=!`+O7*d5=O z6*P^FiidD6%^jV}nR(ph+!((T;!*c?(O~d=uK#RcU7_8r-iH1Ph5e;iZNX<^fpu=2 z%&+$y`J0q8D*qOQYtv=cylr-#7Lb;?l{o$-*2?u8F^60W)=7<^D68HAveoH-atXF?#{DNC82~4 zk%dT8TLw(OXcEpjIY21W18;M`vF(m zcz)#oquKEnNGD^|HJ0(C5sDmPeFvC)t+yO7{iIxqWXRiy2uGNh+>^>)E%b3gpdF-z zjO<8O<2ja)V1Y<)$$wgZu%d7{Rf`|p3I_WOg`xXKiFWFEwoqI_ufVbO zu%1+4ksu{*sWb*amaojQf~34&+%Idtqi{IhsdPC?HCtr~M(aDidRAU5j^}>p-ueq< zk@j&uOP1?c>BIHte{)BTl;4o4y1fRD>5_KF~=e28DRD9z?DIFxJcgS$89HqaMMQ^EQ&vnEi%g==RGpPbT;q!>NR) zbn~WsN>$Ft)#t*6$|P9a7yPk<9j;$&M>rRXUyLl%)iEu^oXVl;v8mmC=fx-`Tn9ah zX?%;;<h&Vc@cIS`-F&w~?-|qB zp^54f)ekU@vSigYb>92L07E+c$f`>HYlTlWOkFXrM;4Zx@gJ6N)6T3zRqwmrH>{ej z)+bQ8jL;P!_rqus)&~U;W6TnKHo-sUlUi|2*L>@dO~8`tpzk+v$Nl&MjHN27leRgs z)R}>E&xb68e0;SzbRIS3S<4eFk|HS&r4qz;XP1-PN$=$-fX7OD-|IM;S=swQ@yH-B zvNKCQWt9JD(XtHEwT8kHWkeGT`1s>8JlB=n`_fAQdU?$Z{Wf7xq!Z=8RNlH-?x8&g z1zLtww`KLGD z#OL%qWU_^=aT+=45#7^d*?-toIv`DL4^QRxk{>@!FtxSjRT1UR{F%48ykfT{@41r( z+x~4o-m!32JmB1ea>Nr~y(R5I^qTC>ap&8aUl3Lg&O}ypf{E{MJ^@#L5S&NWw2emHh+SeNy{ND?~Fu8HUBeK8%Gv z`?@cG9>1_kFYM7RQtZ)CVPbmtJ$xWeWc-~*p6>1Y94^O0_|BV%tJ(cOS%P1|Cx?7` zrGyHXal1U`XF2?*PN6Z8xv)NSfpe%~+SGXd^|`h-|BvUhp9gVy8XLP->A95&3I}{F zVU8IpF3X?mO&OgovM~!x+5IP4S@FWP58#ZR+bc>(FO}L2T@ab9r-m8zYx{rIqyho; zRMGsA`+R`j%HIu>$eBZ`-4>i}@Myl?DXKNOm}t^z5M+6F7Vs3Xr1yXVP4CTY zLeVRiadK_ZrFvwe`y5ZFMivP$6Oew9e>w@%3J}+D(49OFS*VqbnYvw~ zod1?kw_!q3Zo1ZN(y42;#zJ@GsTpe50<{&22DY8*Ir#4T@mj977zV~h9X)=qlWxC4 zd^+=Q?$p-lW=XQf>%QlC+{CT7%k zyrgDyE1xJ?dsh$PD-W@F*WS%@ClWADcOe~Tr3Hu(PWgM6o*i;Nmp*$Cva!Y z%lsnSqoP7m{@8(7>o#pb+JUVEC6LCk{fIuzf!>S5Wmt9g@;fe$(a=u~?Nu#Qf8!07 zu8k|lOX$>d@f@}19I7X!7m!!R(hWn1E>kce3i0ic9;?7jqFR72p z(x~)}1|q-Z_4;Zd00sM62w-!fbA1f<6A1-uD7(hcN7(ypY-~%W=)>pZ&xeGy2Ym}k zTD1y7=LXk~0ZQ39{7V;hfe)jR*2ccl_3eu*5J?Ldpps^3L~Ia!K+iY&)^6hVQGj#Z zgZ=vXZsppV0?; zNj)nojy-jkUIv`EV>$MAaV#Np)|IJ4nX`~h=S`Zmy6Pa1b9%TAt*GKt;%_QNE3n3$ z#RL)d`{0`Mtc_WVwd!XBj2a>RI24PcFuRSxli+3Y|Q&GA;I847jdvz((+sDo*Hu=^@~*_*QW#n+47 z-gH{uN@w6mt8QxeYidfg`6w&+!z_YoxuKr*9z3@i;`}_{H5j#ipjy0qaPP6dNbO#{rn>dFmnFRq-R<1DYoAVe$m&la zHx4()w#*nBkn2h%q@S!dMZeMl39Xbn{<$L}ot`&|`*aY8D)~5b2yLMUSzGkEKJv3( zydEh;PRrG*id)|RW9%zP#_3KGc=kizNBMV=o%Epm8unHA_n2=7Zu(Amozl_h-VhP3qYodoM3>Cd+M>>M$-P z1C;Aqf##Zqj0!(FTgUILbfynE5xp!NM;!Muz-@{8{(+LARvduADSAXwv|>&E6XjCV zo|m*n=bwgojC~n!MV(pWi~q7BbNX`c?5-)mUm-n(s|m=Dh3DBiJv)aLHRogIWIHRa z>TO9+$C3Z+DK@&uh4B1WnqBK<{2H4$YgN-+UCKyp=ift128(9B{)~u6ymxEr3L(!) zqC(44A1E%hWhC!1_wXGqUado_;jERaDj!lA%w`S90pn_SxPqD97W7`1?@kLlVhxaH zl1wba#ZL9vmcS7KO0)9jTPuMqfd@a(&}6O)Wmb|5&0a59!t>o;R`SwSs(mk6Wm5Ar zcFM6x%UX#(Xeb#@$cxd}ilR0e(PXFu&#!$ay${|S;R-6n*kSQL%* znXj+h5*}U&SSlw>+;%E$K~|sw(znE4zQ%xFxOI3-*4HldlvjSaqhe$`#T>uz^JwC& zCpq=qv(w8F2 zyCMZZ6zbER_fHvOm_Gqb>?mKKJcPjtc|#Na!PK-?j`a;f#pqs}t2^(6V?B zVux&lam++ZHq!zRNoMu9u*0WRaxJ^c5#}18t)^_WKQPql>zM~|!_U^ri)@hACoTB_ z0=LHA4uEvxTbeIY!w8L^H;;AH1UPy*_?oHaex)`&ji=Yy-gjfz-S9@a!Ak-@}MIcjbFjqqKBfWYm zNyDjDOIZ|MJ^rE@ZF*mS5i%A7j{hQf0T84plmb5F_6emB_M1A}hx^bC_uD(fZsuQD z{yCl?tMH5k-k5G)jMKtudUOK1i33US`9N`?_~n|czli|^GGSR)(?knQ>(Z8vR5_tK zXDzcZz%nhk^Vifah&L}z;Q&X(xgj0|qVGQ`;PKl0b5kqs3hV9s5t9 zTgr(#B&eTWQgHC@5NRnp>U+A)$8PUj{hV?mG$06mk}Gh63Z9GK2?TC*+!`-B+7|pt z)TOWiXgD5lee%Wq`dXZV-*LDs#~CdHsQvq1H;_u!Nn5S|Ij*&x)wXN{|M$=Tqb>$` z=h6Q@FXBICMgLB`2qZH8JKq1dojLG^%9;N=g*5-G^al9E{|CMzyoOerA{HeL!Y;1w zHqMrl0fz6BX(-7C3-&x&#InyPY~0z68$c}@Q#b*TfnQih)5eauro#z8q32Gf0DG7b zASN8cLiaDcOVMhLpqSOP69H^N{InfuG`avq^DpBc6Ezt<`Y(aOB~X8}079 z+l_0bjf3Bx7j0h-2;C>@b;j|s3EU^l^+b7=%XBG2WTySm5ZUY{#EC1DqvKLzY^gO5Q#;KICmz~JBQYAln{WWPP-+? z{}ZivC}ydjzTs|wQbY^TN%w8dcaoYx=kpEEXqWHq?k;9sdXjQ3=2cIQQ`VK|UPF23 zK82@?jouC=w=51BL7tVIJE=s>$BZ&86(IWV?R7k?`vYtk%cR1PAiOlhT zTg%?w7`P`H;?pyz@TlS9-u}mh=HHDHPG%(-Q%&y#7af*A>;&)~zF=azsRanj)Zr(h*QV1Of;| zlwJ}*0t7_qMNTM&7V1F*0hNQGKEziYg14+|fz>W1bT}1zfqHBBr7V1%(LU<;{rjEWZW2?3^O?Se(a#mVyQAZ= z4hDTN^jBm@94w~n&+GCDk}>ksDsY_3VUX-DpvC`a&*F1{!pjo4vP9 z+Vw%aIo!P9omPEDl7I_1oM3m`U)b8{yi1xX8NEBNOY=`j#A6Nv8UM*X?j zw^o&sLmWnU+rEmm>~$ulj%@K7h*iSl)*NR;181EO-Cc<lB4$svO z-;A{bBMJ_B4R%7O!xXyjhl~c&GUED?L)%|<8| zt4m>w5Y?a%#ZAP!bc)Ns=-QXajc=5MKL$qkmt*>Z48*(QsZ7zK!SAoh-*=O+rPbg% zmySRwg$eK&e_zC6Xmg0@-QajTXYZW^7SkTejlQDrt z55Mzuax<(Ko_23mF9FUO0-7;<3N<>sx?;fLH!*g#`T0&X`}ZYJVRv_yHL zyc=`9WG~29rldlg{e|j?4W0Ha0Won?lhaCnMY67|1ov?<{h)rv-uBHo3vwpvMXhT!vl)!sGBL+6JGxLIm8KY6WB5Q8uHE2#N ziclWm8M1c0SWJt>L0NSezVr5TE=NL;q)e-aDHAf3pTMO1Zq%SOZwrm1~?c09uqw3I% zuop2}n~_<|O+@88EF*YhJI3!aKpr#TQU}}?f5>t>3jF2&{A%#3F??*Xepo7GW)k?PYC zGb9=rTh@51*(lrm-1Rm7GhEs{w+x{@>Q&Be_P2Nj#^^f(sNnj?;HCupWrC8t>g)0S z1I@2R4-Pg~G}=EUSihM?AN2doATf_zO?(i$lSRmUP~n-k@muzt-xjJ+Qd6IP? z?e$;3C2%S<;_cs5ir79?_9Kg!VjS>;+R+kR#kzy$(2dW0AN8vi zRwW407)*wWTuTcd=H(+YVdY-5jhPTMv_8lo1-%Br^K|PJ zpKD$;hc@|DBSsKtuApfAYn0nq#3DV?Zvd+KqMjrOVl)4AjxK|wp{qnd`I-ly)B}p$z+YrRODc#pP5E=ZLQ=oJRWqp;jzP=EbiRU*SPgO)0~C{xPmc`3Eps1he+{X_r_^?su(KJXJ~!V~$Kv z0W;RngMnM++u-{G^39qJ%_O;D@|!k=#Kmo~4>CcdqczXo}5lp$Z?T z6oJ`{CcvwdoVs>4&sXk^Cr)PHBB_RriQ%pe4i_iHxG$OKRz3Cp%e96drf2qw_Yz!zl;e(h zpX-X|U+NKnmHJV6<>}^!gQ{Q%zJG4C$DfyMDy=GD)k8$oU*z;kz@2yBO+OFwR8qBP z)m{s#oKx$~${|=Y3dPmXIvLfG(qgZ!gC2zfPTU?X{QiC(;KR*3OGjp~RV^H|&qfy4 z7Lo!LHA!qSZL^AJN2ZX+Kw6@JUl+Ad^{Q^EdZcfuW@3C}Rg4gz4Hans68RRm3r9K) zxg&;0d`KDHvXN!d9D}JS%!eGanC=J1OUm}gYGuAW1&Abvt5bNX|TW{pm)hqQg1=wPmf=BO}nZ%Pbz+1-t+b;eBQ2iWBYiF|(T78D#z2g!VHEG;!* z*4`sj5dU>iiSR^HH_JC`CB%Ns0{*=Jrq4RU{#5+v9-`8gIR6?MZ3ACP4KiEW%-}0N z9xl!M(WKH(&DVJyREQrPDs%S^xilSgROy!$?I+ZBjscEqpC>o$SNNx*UE{jXNSoLb z+n+q4c}ApDJMHCFeep&WxI5jld)ettzuFM0cNc(xlP4?itMlhlL&h>9dZmk?wS4>c zdMe(2M2u}p<#|)miw69McgE_tK|She%NZ%h?nGHsr;JQk>@*qXwq>wo3&1XM#KYDU z-I)QR{#cmK=7w?OZ8L@0?;#*iNv1RDL#33>3}mLO(Bh2%jvuB`PBAr`zizQOQX|Lt zTtpoM^8EA{$Bv+=?)|NyAeWhLCq~Lq)D?5l6OAR6_M?qC9(&eiSGbAe0$6NYzI7~q zch7luvb{xCxQ;|9mb0vHUAQ?qce7N$ql!P<(swDSwt~T3%1GR9kq6lpaui8Nm@@Qq z3Q4!fM$tNB7hoDzKA~A*(j!MR6%R&*25_E>SZFcX@5lCB-pUP%Cqd%^D4Zs)#ZmyP zERm+bR718OjUfRpgcllntDi!!d9Qdb0zS?L=8Wfb3wEcRxkA!J3%5FrcU1LTLu5DfM`RNC*h}Iu?@5>cHNfRo7Ak@{bC*O&bFL(F!^lVR`aWsK) z!0MRGPnQTef6g{A#@lsLe(qg7s9h8pXo*-fZ3G?9i^F#=;wFpcg| zm!Zeo=16^uC+`^%JkNC*t-$HdWGmy57_x{{!PrA&baqP;0yMT=CHC*j^gi(gI?@}GA4y6@ z*>^@36FEENNcP-67FS+vUr9}Rqu0u)Dz!?S*fDg`7`Rb;!UCjQC1TB`gu1n>Zm)cYEQYd4uN&>pfp7Tx_SIi1#n?~QM)3})& zdxyyk5>M}+n;q@A$+NQGDWerf9F85KTmg(FZk+P`_*MI^rW|(E6X+i=+QMEO(@_(4 z8^vuE>Z$eNIIk7};aoXnIYE}*Z(tFvz%{A6&4YYG$R8x^A0FBtsA;fd-40vxj`vd6 zXv+I;zd7z>rDqVdjJRs}GxP?5Tmhb~j!Q+B#I{fA_w8~#&IJ>5^j$`(z2@h7b5W~M zC=28)H;tYAmts=ql>RK&Km(rwDb>Uit4&m~w|nk?h3-Oq(sQ4Qxq{;DIDvpsbZp*d zfe}aNzA71r6AcT6N0Lfq6<^25d(BUIc35~USoQ0^ft=5iT>v1ox&$C>T?w`Mg+u-)KvF{mB>!oteq}jiVrV(|0_el$(2n0j zaBo)(fK-Y-w#Zw?^d zAZNRpKRFdyl{UWFt)dJk!Qt@3%Ojf*Qr*G9!EY@PuUyM2U&YI{|8)RaqH(k2Nto0E z5|X5kv;V~Qf#xkl-suK}B^7$xS-BE#JnDR{gcfR8c9;9r*@s0~22+=BW61~2BnHh^ z83sJp+?(Rm^zic9H(67m=wf7palby53VvILul2GM77nGsCwA}U(%}WQlP;N|Te@)g zh+IXiK}D!dwdcLpH+<}WPZ{;RfPlVBSNhWc|FufFm)9`feo5F@*R)QG8>d^R*)1ME z92tJx=-Qi8FHqRf0RF8AdVG9*UWH3{K^(svU+n4X>gt2L4N8gbc4pyFytf;_s;cU` zyyVueQH|R65=z(-a@Ji95dk3s4`gZXcCc`s904~!zYP~zS=qx{6+W6sXQn1PByP6( z-&}woEjq;7Z)bf*5diCBZ*!e(=4);J@zHE+xQH=|G?{?e?k*h7YqEZ}Va<2BAr%~| z@@r&|`X3H;j>{xp4_T8g$*F5sXp2)jBdi2Nwn1X80U + All available CSS variables + +#### Base colors + +These colors are used for special purposes like ring, scrollbar, ... + +| Token Name | Description | +| -------------- | ----------------------------------------------------------------------- | +| `--bui-black` | Pure black color. This one should be the same in light and dark themes. | +| `--bui-white` | Pure white color. This one should be the same in light and dark themes. | +| `--bui-gray-1` | You can use these mostly for backgrounds colors. | +| `--bui-gray-2` | You can use these mostly for backgrounds colors. | +| `--bui-gray-3` | You can use these mostly for backgrounds colors. | +| `--bui-gray-4` | You can use these mostly for backgrounds colors. | +| `--bui-gray-5` | You can use these mostly for backgrounds colors. | +| `--bui-gray-6` | You can use these mostly for backgrounds colors. | +| `--bui-gray-7` | You can use these mostly for backgrounds colors. | +| `--bui-gray-8` | You can use these mostly for backgrounds colors. | + +#### Core background colors + +These colors are used for the background of your application. We are mostly using for now a single elevated background for panels. `--bui-bg` should mostly use as the main background color of your app. + +| Token Name | Description | +| ------------------------- | ------------------------------------------------ | +| `--bui-bg` | The background color of your Backstage instance. | +| `--bui-bg-surface-1` | Use for any panels or elevated surfaces. | +| `--bui-bg-surface-2` | Use for any panels or elevated surfaces. | +| `--bui-bg-solid` | Used for solid background colors. | +| `--bui-bg-solid-hover` | Used for solid background colors when hovered. | +| `--bui-bg-solid-pressed` | Used for solid background colors when pressed. | +| `--bui-bg-solid-disabled` | Used for solid background colors when disabled. | +| `--bui-bg-tint` | Used for tint background colors. | +| `--bui-bg-tint-hover` | Used for tint background colors when hovered. | +| `--bui-bg-tint-focus` | Used for tint background colors when active. | +| `--bui-bg-tint-disabled` | Used for tint background colors when disabled. | +| `--bui-bg-danger` | Used to show errors information. | +| `--bui-bg-warning` | Used to show warnings information. | +| `--bui-bg-success` | Used to show success information. | + +#### Foreground colors + +Foreground colours are meant to work in pair with a background colours. Typeically this would work for icons, texts, shapes, ... Use a matching name to know what foreground color to use. These colors are prefixed with `fg` to make it easier to identify. + +| Token Name | Description | +| ------------------------ | ----------------------------------------------------------------- | +| `--bui-fg-primary` | It should be used on top of main background surfaces. | +| `--bui-fg-secondary` | It should be used on top of main background surfaces. | +| `--bui-fg-link` | It should be used on top of main background surfaces. | +| `--bui-fg-link-hover` | It should be used on top of main background surfaces. | +| `--bui-fg-disabled` | It should be used on top of main background surfaces. | +| `--bui-fg-solid` | It should be used on top of solid background colors. | +| `--bui-fg-tint` | It should be used on top of tint background colors. | +| `--bui-fg-tint-disabled` | It should be used on top of tint background colors when disabled. | +| `--bui-fg-danger` | It should be used on top of danger background colors. | +| `--bui-fg-warning` | It should be used on top of warning background colors. | +| `--bui-fg-success` | It should be used on top of success background colors. | + +#### Border colors + +These border colors are mostly meant to be used as borders on top of any components with low contrast to help as a separator with the different background colors. + +| Token Name | Description | +| ----------------------- | --------------------------------------------------- | +| `--bui-border` | It should be used on top of `--bui-bg-surface-1`. | +| `--bui-border-hover` | Used when the component is interactive and hovered. | +| `--bui-border-pressed` | Used when the component is interactive and hovered. | +| `--bui-border-disabled` | Used when the component is disabled. | +| `--bui-border-danger` | It should be used on top of `--bui-bg-danger`. | +| `--bui-border-warning` | It should be used on top of `--bui-bg-warning`. | +| `--bui-border-success` | It should be used on top of `--bui-bg-success`. | + +#### Special colors + +These colors are used for special purposes like ring, scrollbar, ... + +| Token Name | Description | +| ----------------------- | --------------------------------- | +| `--bui-ring` | The color of the ring. | +| `--bui-scrollbar` | The color of the scrollbar. | +| `--bui-scrollbar-thumb` | The color of the scrollbar thumb. | + +#### Font families + +We have two fonts that we use across Backstage UI. The first one is the sans-serif font that we use for the body of the application. The second one is the monospace font that we use for code blocks and tables. + +| Token Name | Description | +| -------------------- | ---------------------------------- | +| `--bui-font-regular` | The sans-serif font for the theme. | +| `--bui-font-mono` | The monospace font for the theme. | + +#### Font weights + +We have two font weights that we use across Backstage UI. Regular or Bold. + +| Token Name | Description | +| --------------------------- | -------------------------------------- | +| `--bui-font-weight-regular` | The regular font weight for the theme. | +| `--bui-font-weight-bold` | The bold font weight for the theme. | + +#### Spacing + +We built a spacing system based on a single value `--bui-space`. This value is used to calculate the spacing for all the components. By default if you would like to increase or decrease the spacing between your components you can do it simply by updating `--bui-space` and it will apply to all spacing values. + +`--bui-space` is not used directly in any components but serve as an easy way to calculate the other values. + +| Token Name | Description | +| ------------- | ----------------------------------------------------------------- | +| `--bui-space` | The base unit for the spacing system. Default value is `0.25rem.` | + +#### Radius + +We use a radius system to make sure that the components have a consistent look and feel. + +| Token Name | Description | +| ------------------- | --------------------------------------------------------- | +| `--bui-radius-1` | The radius of the component. Default value is `0.125rem`. | +| `--bui-radius-2` | The radius of the component. Default value is `0.25rem`. | +| `--bui-radius-3` | The radius of the component. Default value is `0.5rem`. | +| `--bui-radius-4` | The radius of the component. Default value is `0.75rem`. | +| `--bui-radius-5` | The radius of the component. Default value is `1rem`. | +| `--bui-radius-6` | The radius of the component. Default value is `1.25rem`. | +| `--bui-radius-full` | The radius of the component. Default value is `9999px`. | + + ### Component class names -### Custom font +All Backstage UI components come with a set of CSS classes that you can use to style them. To make it easier to identify the class name you can use, we use a specific structure for the class names. + +![classname-structure](../../assets/user-interface/css-classname-structure.png) + +Every component has a unique prefix `.bui-` followed by the component name. Component props are represented using the `data-` attribute. That way, class names are easily identifiable. ## Create a theme for MUI (Legacy) diff --git a/microsite/src/theme/customTheme.scss b/microsite/src/theme/customTheme.scss index 707acb4073..823327b28f 100644 --- a/microsite/src/theme/customTheme.scss +++ b/microsite/src/theme/customTheme.scss @@ -171,6 +171,11 @@ html[data-theme='light'] { border-left: 3px solid rgb(255, 255, 255, 0.5); } +table { + width: 100%; + display: table; +} + /* #endregion */ /* For the docusaurus-pushfeedback plugin */ From 1dfaeeebdf23e744c4b494831102a04fc6c6eb31 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 12 Sep 2025 11:58:41 +0100 Subject: [PATCH 020/244] Update mkdocs.yml Signed-off-by: Charles de Dreuille --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index eea5fc9c40..45fdd2c9d6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -28,7 +28,7 @@ nav: - Database: 'getting-started/config/database.md' - Authentication: 'getting-started/config/authentication.md' - Configuring App with plugins: 'getting-started/configure-app-with-plugins.md' - - Customize the look-and-feel of your App: 'getting-started/app-custom-theme.md' + - Customize the look-and-feel of your App: 'conf/user-interface/index.md' - Customizing your Homepage: 'getting-started/homepage.md' - Deployment: - Deploying Backstage: 'deployment/index.md' From f5f1cece1712ffdf84f477405415db36354ab6ba Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 15 Sep 2025 11:37:57 +0100 Subject: [PATCH 021/244] Update docs/conf/user-interface/icons.md Co-authored-by: Patrik Oldsberg Signed-off-by: Charles de Dreuille --- docs/conf/user-interface/icons.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf/user-interface/icons.md b/docs/conf/user-interface/icons.md index 44b8782430..26a6f11096 100644 --- a/docs/conf/user-interface/icons.md +++ b/docs/conf/user-interface/icons.md @@ -20,7 +20,7 @@ You can change the following [icons](https://github.com/backstage/backstage/blob ### Create React Component -In your front-end application, locate the `src` folder. We suggest creating the `assets/icons` directory and `CustomIcons.tsx` file. +In your front-end application, locate the `src` folder. We suggest creating the `assets/icons` directory and `customIcons.tsx` file. ```tsx title="customIcons.tsx" import { SvgIcon, SvgIconProps } from '@material-ui/core'; From 95c442a9bdc17e52f273eb6de03604abee6882dc Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 15 Sep 2025 12:39:09 +0100 Subject: [PATCH 022/244] Docs fixes Signed-off-by: Charles de Dreuille --- docs/conf/user-interface/index.md | 2 +- microsite/docusaurus.config.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/conf/user-interface/index.md b/docs/conf/user-interface/index.md index d4ecbc6940..aeae086b59 100644 --- a/docs/conf/user-interface/index.md +++ b/docs/conf/user-interface/index.md @@ -38,7 +38,7 @@ We recognize that maintaining two separate theming systems is not ideal. Because ## Creating custom themes -During the transition to Backstage UI, you will need to maintain themes in two places: some components and plugins still rely on MUI, while others use Backstage UI. At this time, there is no automated solution to generate MUI themes from your Backstage UI theme, so you will need to manage both separately until the migration is complete. +During the transition to Backstage UI, you will need to maintain themes in two places: some components and plugins still rely on MUI, while others use Backstage UI. We are working on a plugin that will make help you convert your existing MUI theme into a Backstage UI CSS file you can add to your application. We'll update this page when the plugin is available but for now you can follow progress on this PR [#31140](https://github.com/backstage/backstage/pull/31140). ```tsx title="packages/app/src/App.tsx" /* highlight-add-start */ diff --git a/microsite/docusaurus.config.ts b/microsite/docusaurus.config.ts index d7538cd12d..83f2f75689 100644 --- a/microsite/docusaurus.config.ts +++ b/microsite/docusaurus.config.ts @@ -269,6 +269,10 @@ const config: Config = { from: '/docs/plugins/url-reader/', to: '/docs/backend-system/core-services/url-reader', }, + { + from: '/docs/getting-started/app-custom-theme', + to: '/docs/conf/user-interface', + } ], }), [ From 8ed53eb466c328bb67f426e52f3a1452dd58d63d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 16 Sep 2025 00:05:27 +0200 Subject: [PATCH 023/244] frontend-plugin-api: add coreExtensionData.title Signed-off-by: Patrik Oldsberg --- .changeset/nasty-moose-rescue.md | 5 +++++ .../building-plugins/04-built-in-data-refs.md | 8 ++++++++ packages/frontend-plugin-api/report.api.md | 1 + .../frontend-plugin-api/src/wiring/coreExtensionData.ts | 1 + plugins/catalog-react/report-alpha.api.md | 6 +++--- 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 .changeset/nasty-moose-rescue.md diff --git a/.changeset/nasty-moose-rescue.md b/.changeset/nasty-moose-rescue.md new file mode 100644 index 0000000000..ff8cf1b02c --- /dev/null +++ b/.changeset/nasty-moose-rescue.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Added `coreExtensionData.title`, especially useful for creating extensible layout with tabbed pages, but availble for use for other cases too. 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 b69e4cb3f4..c01520d7bd 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 @@ -34,6 +34,14 @@ const examplePage = createExtension({ }); ``` +### `title` + +| id | type | +| :----------: | :------: | +| `core.title` | `string` | + +The `title` data reference can be used for defining the extension input/output of string titles. + ### `routePath` | id | type | diff --git a/packages/frontend-plugin-api/report.api.md b/packages/frontend-plugin-api/report.api.md index f9e2336408..52a50659b6 100644 --- a/packages/frontend-plugin-api/report.api.md +++ b/packages/frontend-plugin-api/report.api.md @@ -377,6 +377,7 @@ export interface ConfigurableExtensionDataRef< // @public (undocumented) export const coreExtensionData: { + title: ConfigurableExtensionDataRef; reactElement: ConfigurableExtensionDataRef< JSX_3.Element, 'core.reactElement', diff --git a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts index 18466d8196..b778539101 100644 --- a/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts +++ b/packages/frontend-plugin-api/src/wiring/coreExtensionData.ts @@ -20,6 +20,7 @@ import { createExtensionDataRef } from './createExtensionDataRef'; /** @public */ export const coreExtensionData = { + title: createExtensionDataRef().with({ id: 'core.title' }), reactElement: createExtensionDataRef().with({ id: 'core.reactElement', }), diff --git a/plugins/catalog-react/report-alpha.api.md b/plugins/catalog-react/report-alpha.api.md index 30cdd91704..cf28d80c11 100644 --- a/plugins/catalog-react/report-alpha.api.md +++ b/plugins/catalog-react/report-alpha.api.md @@ -92,12 +92,12 @@ export const catalogReactTranslationRef: TranslationRef< readonly 'entityTableColumnTitle.title': 'Title'; readonly 'entityTableColumnTitle.description': 'Description'; readonly 'entityTableColumnTitle.domain': 'Domain'; + readonly 'entityTableColumnTitle.system': 'System'; + readonly 'entityTableColumnTitle.tags': 'Tags'; readonly 'entityTableColumnTitle.namespace': 'Namespace'; readonly 'entityTableColumnTitle.lifecycle': 'Lifecycle'; readonly 'entityTableColumnTitle.owner': 'Owner'; - readonly 'entityTableColumnTitle.system': 'System'; readonly 'entityTableColumnTitle.targets': 'Targets'; - readonly 'entityTableColumnTitle.tags': 'Tags'; } >; @@ -533,8 +533,8 @@ export const EntityTableColumnTitle: ({ translationKey, }: EntityTableColumnTitleProps) => | 'Title' - | 'Domain' | 'System' + | 'Domain' | 'Lifecycle' | 'Namespace' | 'Owner' From 606f2c1f71a851feebbc1adc09f307f7d8939156 Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Fri, 12 Sep 2025 09:19:43 +0300 Subject: [PATCH 024/244] chore: use BACKSTAGE_VERSIONS_BASE_URL instead Signed-off-by: Hellgren Heikki --- .changeset/heavy-chicken-find.md | 2 +- .../migrate/commands/versions/bump.test.ts | 17 +++++++---------- .../modules/migrate/commands/versions/bump.ts | 10 +++++----- packages/yarn-plugin/README.md | 2 +- .../src/util/getPackageVersion.test.ts | 12 +++++++----- .../yarn-plugin/src/util/getPackageVersion.ts | 2 +- 6 files changed, 22 insertions(+), 23 deletions(-) diff --git a/.changeset/heavy-chicken-find.md b/.changeset/heavy-chicken-find.md index 96308ed2b8..645984b1bd 100644 --- a/.changeset/heavy-chicken-find.md +++ b/.changeset/heavy-chicken-find.md @@ -6,7 +6,7 @@ Allow using custom manifest location in the yarn plugin and version bump. The Backstage yarn plugin and version bump allows two new environment variables to configure custom manifest location: -- `BACKSTAGE_MANIFEST_BASE_URL`: The base URL for fetching the Backstage version +- `BACKSTAGE_VERSIONS_BASE_URL`: The base URL for fetching the Backstage version manifest. Defaults to `https://versions.backstage.io/v1/releases/VERSION/manifest.json`. Useful for running the plugin in environment without direct access to the internet, for example by using a mirror of the versions API or a proxy. diff --git a/packages/cli/src/modules/migrate/commands/versions/bump.test.ts b/packages/cli/src/modules/migrate/commands/versions/bump.test.ts index bea7a551a1..c045ae26e6 100644 --- a/packages/cli/src/modules/migrate/commands/versions/bump.test.ts +++ b/packages/cli/src/modules/migrate/commands/versions/bump.test.ts @@ -1061,18 +1061,19 @@ describe('environment variables', () => { beforeEach(() => { delete process.env.BACKSTAGE_MANIFEST_FILE; - delete process.env.BACKSTAGE_MANIFEST_BASE_URL; + process.env.BACKSTAGE_VERSIONS_BASE_URL = 'https://custom.example.com'; }); afterEach(() => { jest.resetAllMocks(); - delete process.env.BACKSTAGE_MANIFEST_FILE; - delete process.env.BACKSTAGE_MANIFEST_BASE_URL; }); - it('should use custom base URL when BACKSTAGE_MANIFEST_BASE_URL is set', async () => { - process.env.BACKSTAGE_MANIFEST_BASE_URL = 'https://custom.example.com'; + afterAll(() => { + delete process.env.BACKSTAGE_MANIFEST_FILE; + delete process.env.BACKSTAGE_VERSIONS_BASE_URL; + }); + it('should use custom base URL when BACKSTAGE_VERSIONS_BASE_URL is set', async () => { mockDir.setContent({ 'yarn.lock': lockfileMock, 'package.json': JSON.stringify({ @@ -1230,9 +1231,7 @@ describe('environment variables', () => { }); }); - it('should use custom base URL for yarn plugin when BACKSTAGE_MANIFEST_BASE_URL is set with yarn plugin', async () => { - process.env.BACKSTAGE_MANIFEST_BASE_URL = 'https://custom.example.com'; - + it('should use custom base URL for yarn plugin when BACKSTAGE_VERSIONS_BASE_URL is set with yarn plugin', async () => { mockDir.setContent({ '.yarnrc.yml': yarnRcMock, 'yarn.lock': lockfileMock, @@ -1331,8 +1330,6 @@ describe('environment variables', () => { }); it('should handle network errors when using custom base URL', async () => { - process.env.BACKSTAGE_MANIFEST_BASE_URL = 'https://custom.example.com'; - mockDir.setContent({ 'yarn.lock': lockfileMock, 'package.json': JSON.stringify({ diff --git a/packages/cli/src/modules/migrate/commands/versions/bump.ts b/packages/cli/src/modules/migrate/commands/versions/bump.ts index b4c21be58c..6bce65cb10 100644 --- a/packages/cli/src/modules/migrate/commands/versions/bump.ts +++ b/packages/cli/src/modules/migrate/commands/versions/bump.ts @@ -114,11 +114,11 @@ export default async (opts: OptionValues) => { if (opts.release === 'next') { const next = await getManifestByReleaseLine({ releaseLine: 'next', - versionsBaseUrl: env.BACKSTAGE_MANIFEST_BASE_URL, + versionsBaseUrl: env.BACKSTAGE_VERSIONS_BASE_URL, }); const main = await getManifestByReleaseLine({ releaseLine: 'main', - versionsBaseUrl: env.BACKSTAGE_MANIFEST_BASE_URL, + versionsBaseUrl: env.BACKSTAGE_VERSIONS_BASE_URL, }); // Prefer manifest with the latest release version releaseManifest = semver.gt(next.releaseVersion, main.releaseVersion) @@ -127,7 +127,7 @@ export default async (opts: OptionValues) => { } else { releaseManifest = await getManifestByReleaseLine({ releaseLine: opts.release, - versionsBaseUrl: env.BACKSTAGE_MANIFEST_BASE_URL, + versionsBaseUrl: env.BACKSTAGE_VERSIONS_BASE_URL, }); } findTargetVersion = createVersionFinder({ @@ -143,8 +143,8 @@ export default async (opts: OptionValues) => { ); console.log(); - const yarnPluginUrl = env.BACKSTAGE_MANIFEST_BASE_URL - ? `${env.BACKSTAGE_MANIFEST_BASE_URL}/v1/releases/${releaseManifest.releaseVersion}/yarn-plugin` + const yarnPluginUrl = env.BACKSTAGE_VERSIONS_BASE_URL + ? `${env.BACKSTAGE_VERSIONS_BASE_URL}/v1/releases/${releaseManifest.releaseVersion}/yarn-plugin` : `https://versions.backstage.io/v1/releases/${releaseManifest.releaseVersion}/yarn-plugin`; await run('yarn', ['plugin', 'import', yarnPluginUrl]); diff --git a/packages/yarn-plugin/README.md b/packages/yarn-plugin/README.md index fe90cebe7b..3249d4279c 100644 --- a/packages/yarn-plugin/README.md +++ b/packages/yarn-plugin/README.md @@ -29,7 +29,7 @@ backstage.json. The plugin functionality can be configured with environment variables: -- `BACKSTAGE_MANIFEST_BASE_URL` - The base URL for fetching the Backstage version +- `BACKSTAGE_VERSIONS_BASE_URL` - The base URL for fetching the Backstage version manifest. Defaults to `https://versions.backstage.io/v1/releases/VERSION/manifest.json`. Useful for running the plugin in environment without direct access to the internet, for example by using a mirror of the versions API or a proxy. diff --git a/packages/yarn-plugin/src/util/getPackageVersion.test.ts b/packages/yarn-plugin/src/util/getPackageVersion.test.ts index d093a8f3ad..9eca738da1 100644 --- a/packages/yarn-plugin/src/util/getPackageVersion.test.ts +++ b/packages/yarn-plugin/src/util/getPackageVersion.test.ts @@ -43,8 +43,6 @@ describe('getPackageVersion', () => { const mockConfiguration = {} as Configuration; beforeEach(() => { - jest.clearAllMocks(); - mockGetCurrentBackstageVersion.mockReturnValue('1.23.4'); mockStructUtils.stringifyIdent.mockImplementation( (descriptor: any) => @@ -59,6 +57,10 @@ describe('getPackageVersion', () => { })); }); + afterEach(() => { + jest.clearAllMocks(); + }); + describe('successful package resolution', () => { beforeEach(() => { mockHttpUtils.get.mockResolvedValue({ @@ -96,8 +98,8 @@ describe('getPackageVersion', () => { }); it('uses custom versionsBaseUrl from environment when provided', async () => { - const originalEnv = process.env.BACKSTAGE_MANIFEST_BASE_URL; - process.env.BACKSTAGE_MANIFEST_BASE_URL = 'https://custom.example.com'; + const originalEnv = process.env.BACKSTAGE_VERSIONS_BASE_URL; + process.env.BACKSTAGE_VERSIONS_BASE_URL = 'https://custom.example.com'; const descriptor = { scope: '@backstage', @@ -113,7 +115,7 @@ describe('getPackageVersion', () => { fetch: expect.any(Function), }); - process.env.BACKSTAGE_MANIFEST_BASE_URL = originalEnv; + process.env.BACKSTAGE_VERSIONS_BASE_URL = originalEnv; }); it('uses yarn httpUtils for fetching with proper response format', async () => { diff --git a/packages/yarn-plugin/src/util/getPackageVersion.ts b/packages/yarn-plugin/src/util/getPackageVersion.ts index ed1c1ee6d8..9ff7198c30 100644 --- a/packages/yarn-plugin/src/util/getPackageVersion.ts +++ b/packages/yarn-plugin/src/util/getPackageVersion.ts @@ -52,7 +52,7 @@ export const getPackageVersion = async ( ? await xfs.readJsonSync(manifestFile as PortablePath) : await getManifestByVersion({ version: backstageVersion, - versionsBaseUrl: env.BACKSTAGE_MANIFEST_BASE_URL, + versionsBaseUrl: env.BACKSTAGE_VERSIONS_BASE_URL, // We override the fetch function used inside getManifestByVersion with a // custom implementation that calls yarn's built-in `httpUtils` method // instead. This has a couple of benefits: From 024645e1ab98608413a4f10d683094fe48b6edd2 Mon Sep 17 00:00:00 2001 From: Hitoshi Kamezaki Date: Mon, 7 Jul 2025 10:26:42 +0900 Subject: [PATCH 025/244] Remove unused @octokit moudles from cli package - @octokit/graphql - @octokit/graphql-schema - @octokit/oauth-app Signed-off-by: Hitoshi Kamezaki --- .changeset/silent-mice-play.md | 9 ++++++ packages/cli/package.json | 3 -- yarn.lock | 51 ++-------------------------------- 3 files changed, 11 insertions(+), 52 deletions(-) create mode 100644 .changeset/silent-mice-play.md diff --git a/.changeset/silent-mice-play.md b/.changeset/silent-mice-play.md new file mode 100644 index 0000000000..aa14cf69e3 --- /dev/null +++ b/.changeset/silent-mice-play.md @@ -0,0 +1,9 @@ +--- +'@backstage/cli': patch +--- + +Remove unused @octokit modules from cli package + +- @octokit/graphql +- @octokit/graphql-schema +- @octokit/oauth-app diff --git a/packages/cli/package.json b/packages/cli/package.json index f50a5601eb..aad6eb410d 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -59,9 +59,6 @@ "@backstage/types": "workspace:^", "@manypkg/get-packages": "^1.1.3", "@module-federation/enhanced": "^0.9.0", - "@octokit/graphql": "^5.0.0", - "@octokit/graphql-schema": "^13.7.0", - "@octokit/oauth-app": "^4.2.0", "@octokit/request": "^8.0.0", "@rollup/plugin-commonjs": "^26.0.0", "@rollup/plugin-json": "^6.0.0", diff --git a/yarn.lock b/yarn.lock index e606b8246d..dac807ce19 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2854,9 +2854,6 @@ __metadata: "@backstage/types": "workspace:^" "@manypkg/get-packages": "npm:^1.1.3" "@module-federation/enhanced": "npm:^0.9.0" - "@octokit/graphql": "npm:^5.0.0" - "@octokit/graphql-schema": "npm:^13.7.0" - "@octokit/oauth-app": "npm:^4.2.0" "@octokit/request": "npm:^8.0.0" "@pmmmwh/react-refresh-webpack-plugin": "npm:^0.5.7" "@rollup/plugin-commonjs": "npm:^26.0.0" @@ -11867,16 +11864,6 @@ __metadata: languageName: node linkType: hard -"@octokit/auth-unauthenticated@npm:^3.0.0": - version: 3.0.0 - resolution: "@octokit/auth-unauthenticated@npm:3.0.0" - dependencies: - "@octokit/request-error": "npm:^2.1.0" - "@octokit/types": "npm:^6.0.3" - checksum: 10/3100d1f4a201ea4ca160c1f432121829ed77a3225aeb77c9d600e677dfdd1fa79bd14e6d24f51f6b10312ba40de31780148eb80bb096b7b33fc4b9c26c593526 - languageName: node - linkType: hard - "@octokit/auth-unauthenticated@npm:^5.0.0": version: 5.0.1 resolution: "@octokit/auth-unauthenticated@npm:5.0.1" @@ -11887,7 +11874,7 @@ __metadata: languageName: node linkType: hard -"@octokit/core@npm:^4.0.0, @octokit/core@npm:^4.2.1": +"@octokit/core@npm:^4.2.1": version: 4.2.4 resolution: "@octokit/core@npm:4.2.4" dependencies: @@ -11949,16 +11936,6 @@ __metadata: languageName: node linkType: hard -"@octokit/graphql-schema@npm:^13.7.0": - version: 13.10.0 - resolution: "@octokit/graphql-schema@npm:13.10.0" - dependencies: - graphql: "npm:^16.0.0" - graphql-tag: "npm:^2.10.3" - checksum: 10/c8714a9dc8f36d01e3db125e570a95030faeaf6c815811be2190ce288691bfcc5e939d161b33ef91b4c9fbca21663bace53d3eea2115a443de27a51b5dbfe2a4 - languageName: node - linkType: hard - "@octokit/graphql@npm:^5.0.0": version: 5.0.6 resolution: "@octokit/graphql@npm:5.0.6" @@ -11981,23 +11958,6 @@ __metadata: languageName: node linkType: hard -"@octokit/oauth-app@npm:^4.2.0": - version: 4.2.4 - resolution: "@octokit/oauth-app@npm:4.2.4" - dependencies: - "@octokit/auth-oauth-app": "npm:^5.0.0" - "@octokit/auth-oauth-user": "npm:^2.0.0" - "@octokit/auth-unauthenticated": "npm:^3.0.0" - "@octokit/core": "npm:^4.0.0" - "@octokit/oauth-authorization-url": "npm:^5.0.0" - "@octokit/oauth-methods": "npm:^2.0.0" - "@types/aws-lambda": "npm:^8.10.83" - fromentries: "npm:^1.3.1" - universal-user-agent: "npm:^6.0.0" - checksum: 10/1c9e48b56fb4cf3428b8967335b46cedf7740d27932ea394530d07deffa8c3bff5ceef8d14bf145b3bfc64ad1088f4ddf46ceca2a4c052f267c3faa12188ef14 - languageName: node - linkType: hard - "@octokit/oauth-app@npm:^6.0.0": version: 6.0.0 resolution: "@octokit/oauth-app@npm:6.0.0" @@ -30904,13 +30864,6 @@ __metadata: languageName: node linkType: hard -"fromentries@npm:^1.3.1": - version: 1.3.2 - resolution: "fromentries@npm:1.3.2" - checksum: 10/10d6e07d289db102c0c1eaf5c3e3fa55ddd6b50033d7de16d99a7cd89f1e1a302dfadb26457031f9bb5d2ed95a179aaf0396092dde5abcae06e8a2f0476826be - languageName: node - linkType: hard - "fs-constants@npm:^1.0.0": version: 1.0.0 resolution: "fs-constants@npm:1.0.0" @@ -31884,7 +31837,7 @@ __metadata: languageName: node linkType: hard -"graphql-tag@npm:^2.10.3, graphql-tag@npm:^2.12.6": +"graphql-tag@npm:^2.12.6": version: 2.12.6 resolution: "graphql-tag@npm:2.12.6" dependencies: From 99fcf986fee0d121ae1b786219fac5e0a2642c79 Mon Sep 17 00:00:00 2001 From: Hope Hadfield Date: Mon, 15 Sep 2025 16:19:57 -0400 Subject: [PATCH 026/244] Remove all unused luxon dependencies Signed-off-by: Hope Hadfield --- .changeset/warm-items-look.md | 17 +++++++++++++++++ .../catalog-backend-module-aws/knip-report.md | 12 ------------ plugins/catalog-backend-module-aws/package.json | 5 +---- .../catalog-backend-module-azure/knip-report.md | 5 ----- .../catalog-backend-module-azure/package.json | 1 - .../knip-report.md | 11 ----------- .../package.json | 2 -- .../knip-report.md | 11 ----------- .../package.json | 2 -- .../knip-report.md | 5 ----- .../catalog-backend-module-gerrit/package.json | 1 - .../knip-report.md | 5 ----- .../package.json | 3 +-- .../knip-report.md | 12 ------------ .../catalog-backend-module-github/package.json | 3 --- .../knip-report.md | 5 ----- .../package.json | 3 +-- .../knip-report.md | 5 ----- .../catalog-backend-module-gitlab/package.json | 1 - .../knip-report.md | 5 ----- .../catalog-backend-module-msgraph/package.json | 1 - .../knip-report.md | 5 ----- .../package.json | 1 - plugins/kubernetes-cluster/knip-report.md | 15 --------------- plugins/kubernetes-cluster/package.json | 6 ------ plugins/kubernetes/knip-report.md | 15 --------------- plugins/kubernetes/package.json | 13 +------------ 27 files changed, 21 insertions(+), 149 deletions(-) create mode 100644 .changeset/warm-items-look.md diff --git a/.changeset/warm-items-look.md b/.changeset/warm-items-look.md new file mode 100644 index 0000000000..b8a2abd61d --- /dev/null +++ b/.changeset/warm-items-look.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-catalog-backend-module-bitbucket-server': patch +'@backstage/plugin-catalog-backend-module-bitbucket-cloud': patch +'@backstage/plugin-catalog-backend-module-github-org': patch +'@backstage/plugin-catalog-backend-module-gitlab-org': patch +'@backstage/plugin-catalog-backend-module-puppetdb': patch +'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-catalog-backend-module-gerrit': patch +'@backstage/plugin-catalog-backend-module-github': patch +'@backstage/plugin-catalog-backend-module-gitlab': patch +'@backstage/plugin-catalog-backend-module-azure': patch +'@backstage/plugin-catalog-backend-module-aws': patch +'@backstage/plugin-kubernetes-cluster': patch +'@backstage/plugin-kubernetes': patch +--- + +Removed unused dependencies diff --git a/plugins/catalog-backend-module-aws/knip-report.md b/plugins/catalog-backend-module-aws/knip-report.md index ed7557334b..97d5b385fd 100644 --- a/plugins/catalog-backend-module-aws/knip-report.md +++ b/plugins/catalog-backend-module-aws/knip-report.md @@ -1,15 +1,3 @@ # Knip report -## Unused dependencies (2) - -| Name | Location | Severity | -| :---------------------------- | :----------- | :------- | -| @aws-sdk/credential-providers | plugins/catalog-backend-module-aws/package.json | error | -| winston | plugins/catalog-backend-module-aws/package.json | error | - -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-aws/package.json | error | diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 3f21de8eb1..0b29e2bda8 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -54,7 +54,6 @@ "@aws-sdk/client-eks": "^3.350.0", "@aws-sdk/client-organizations": "^3.350.0", "@aws-sdk/client-s3": "^3.350.0", - "@aws-sdk/credential-providers": "^3.350.0", "@aws-sdk/middleware-endpoint": "^3.347.0", "@aws-sdk/types": "^3.347.0", "@backstage/backend-defaults": "workspace:^", @@ -68,8 +67,7 @@ "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-kubernetes-common": "workspace:^", "p-limit": "^3.0.2", - "uuid": "^11.0.0", - "winston": "^3.2.1" + "uuid": "^11.0.0" }, "devDependencies": { "@aws-sdk/util-stream-node": "^3.350.0", @@ -77,7 +75,6 @@ "@backstage/cli": "workspace:^", "aws-sdk-client-mock": "^4.0.0", "aws-sdk-client-mock-jest": "^4.0.0", - "luxon": "^3.0.0", "yaml": "^2.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend-module-azure/knip-report.md b/plugins/catalog-backend-module-azure/knip-report.md index 622077aa40..97d5b385fd 100644 --- a/plugins/catalog-backend-module-azure/knip-report.md +++ b/plugins/catalog-backend-module-azure/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-azure/package.json | error | diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index 17c66699a5..0aadfcecfc 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -63,7 +63,6 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "luxon": "^3.0.0", "msw": "^1.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend-module-bitbucket-cloud/knip-report.md b/plugins/catalog-backend-module-bitbucket-cloud/knip-report.md index a6400f9cd2..97d5b385fd 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/knip-report.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/knip-report.md @@ -1,14 +1,3 @@ # Knip report -## Unused dependencies (1) - -| Name | Location | Severity | -| :------------------------ | :----------- | :------- | -| @backstage/catalog-client | plugins/catalog-backend-module-bitbucket-cloud/package.json | error | - -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-bitbucket-cloud/package.json | error | diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index 68dfbaa619..f5afab87d2 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -52,7 +52,6 @@ }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", - "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/integration": "workspace:^", @@ -66,7 +65,6 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-events-backend-test-utils": "workspace:^", - "luxon": "^3.0.0", "msw": "^1.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend-module-bitbucket-server/knip-report.md b/plugins/catalog-backend-module-bitbucket-server/knip-report.md index 067155bd06..97d5b385fd 100644 --- a/plugins/catalog-backend-module-bitbucket-server/knip-report.md +++ b/plugins/catalog-backend-module-bitbucket-server/knip-report.md @@ -1,14 +1,3 @@ # Knip report -## Unused dependencies (1) - -| Name | Location | Severity | -| :------------------------ | :----------- | :------- | -| @backstage/catalog-client | plugins/catalog-backend-module-bitbucket-server/package.json | error | - -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-bitbucket-server/package.json | error | diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index ce3ec49ae8..95b310eec1 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -47,7 +47,6 @@ }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", - "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", @@ -61,7 +60,6 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@backstage/plugin-events-backend-test-utils": "workspace:^", - "luxon": "^3.0.0", "msw": "^1.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend-module-gerrit/knip-report.md b/plugins/catalog-backend-module-gerrit/knip-report.md index 7a02c83e07..97d5b385fd 100644 --- a/plugins/catalog-backend-module-gerrit/knip-report.md +++ b/plugins/catalog-backend-module-gerrit/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-gerrit/package.json | error | diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 1c4d7e8aa7..ba6c981a41 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -61,7 +61,6 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/fs-extra": "^11.0.0", - "luxon": "^3.0.0", "msw": "^1.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend-module-github-org/knip-report.md b/plugins/catalog-backend-module-github-org/knip-report.md index d71302f8ae..97d5b385fd 100644 --- a/plugins/catalog-backend-module-github-org/knip-report.md +++ b/plugins/catalog-backend-module-github-org/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-github-org/package.json | error | diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index f9c1f516fb..a864ffe6e2 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -41,7 +41,6 @@ }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", - "@backstage/cli": "workspace:^", - "luxon": "^3.0.0" + "@backstage/cli": "workspace:^" } } diff --git a/plugins/catalog-backend-module-github/knip-report.md b/plugins/catalog-backend-module-github/knip-report.md index 35b39536c9..c9e8569b52 100644 --- a/plugins/catalog-backend-module-github/knip-report.md +++ b/plugins/catalog-backend-module-github/knip-report.md @@ -1,17 +1,5 @@ # Knip report -## Unused dependencies (2) - -| Name | Location | Severity | -| :-------------------------------- | :----------- | :------- | -| @backstage/plugin-catalog-backend | plugins/catalog-backend-module-github/package.json | error | -| @backstage/catalog-client | plugins/catalog-backend-module-github/package.json | error | - -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-github/package.json | error | ## Unlisted dependencies (4) diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index 5187103233..0a5075c3c9 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -52,11 +52,9 @@ }, "dependencies": { "@backstage/backend-plugin-api": "workspace:^", - "@backstage/catalog-client": "workspace:^", "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/integration": "workspace:^", - "@backstage/plugin-catalog-backend": "workspace:^", "@backstage/plugin-catalog-common": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", "@backstage/plugin-events-node": "workspace:^", @@ -73,7 +71,6 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", - "luxon": "^3.0.0", "msw": "^2.0.0", "type-fest": "^4.41.0" }, diff --git a/plugins/catalog-backend-module-gitlab-org/knip-report.md b/plugins/catalog-backend-module-gitlab-org/knip-report.md index 43328f5e48..97d5b385fd 100644 --- a/plugins/catalog-backend-module-gitlab-org/knip-report.md +++ b/plugins/catalog-backend-module-gitlab-org/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-gitlab-org/package.json | error | diff --git a/plugins/catalog-backend-module-gitlab-org/package.json b/plugins/catalog-backend-module-gitlab-org/package.json index 09f6ee7811..2ebcdf5472 100644 --- a/plugins/catalog-backend-module-gitlab-org/package.json +++ b/plugins/catalog-backend-module-gitlab-org/package.json @@ -41,7 +41,6 @@ "devDependencies": { "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", - "@backstage/plugin-events-backend-test-utils": "workspace:^", - "luxon": "^3.0.0" + "@backstage/plugin-events-backend-test-utils": "workspace:^" } } diff --git a/plugins/catalog-backend-module-gitlab/knip-report.md b/plugins/catalog-backend-module-gitlab/knip-report.md index 8c7b1cc0a0..97d5b385fd 100644 --- a/plugins/catalog-backend-module-gitlab/knip-report.md +++ b/plugins/catalog-backend-module-gitlab/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-gitlab/package.json | error | diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index c18be1028b..b14f6bb930 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -69,7 +69,6 @@ "@backstage/cli": "workspace:^", "@backstage/plugin-events-backend-test-utils": "workspace:^", "@types/lodash": "^4.14.151", - "luxon": "^3.0.0", "msw": "^1.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend-module-msgraph/knip-report.md b/plugins/catalog-backend-module-msgraph/knip-report.md index 1b4a6feaab..97d5b385fd 100644 --- a/plugins/catalog-backend-module-msgraph/knip-report.md +++ b/plugins/catalog-backend-module-msgraph/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused devDependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-msgraph/package.json | error | diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index f2f8a5d442..cb69f932f0 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -67,7 +67,6 @@ "@backstage/backend-test-utils": "workspace:^", "@backstage/cli": "workspace:^", "@types/lodash": "^4.14.151", - "luxon": "^3.0.0", "msw": "^1.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/catalog-backend-module-puppetdb/knip-report.md b/plugins/catalog-backend-module-puppetdb/knip-report.md index ac2ab908f0..97d5b385fd 100644 --- a/plugins/catalog-backend-module-puppetdb/knip-report.md +++ b/plugins/catalog-backend-module-puppetdb/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused dependencies (1) - -| Name | Location | Severity | -| :---- | :----------- | :------- | -| luxon | plugins/catalog-backend-module-puppetdb/package.json | error | diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index ced5df4773..68b5127056 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -56,7 +56,6 @@ "@backstage/plugin-catalog-node": "workspace:^", "@backstage/types": "workspace:^", "lodash": "^4.17.21", - "luxon": "^3.0.0", "uuid": "^11.0.0" }, "devDependencies": { diff --git a/plugins/kubernetes-cluster/knip-report.md b/plugins/kubernetes-cluster/knip-report.md index 55eba7a829..97d5b385fd 100644 --- a/plugins/kubernetes-cluster/knip-report.md +++ b/plugins/kubernetes-cluster/knip-report.md @@ -1,18 +1,3 @@ # Knip report -## Unused dependencies (5) - -| Name | Location | Severity | -| :---------------------- | :----------- | :------- | -| @kubernetes-models/base | plugins/kubernetes-cluster/package.json | error | -| cronstrue | plugins/kubernetes-cluster/package.json | error | -| js-yaml | plugins/kubernetes-cluster/package.json | error | -| lodash | plugins/kubernetes-cluster/package.json | error | -| luxon | plugins/kubernetes-cluster/package.json | error | - -## Unused devDependencies (1) - -| Name | Location | Severity | -| :------------------- | :----------- | :------- | -| @testing-library/dom | plugins/kubernetes-cluster/package.json | error | diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index e789c3edaf..49ec22c9c3 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -62,20 +62,14 @@ "@backstage/plugin-kubernetes-react": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", "@kubernetes-models/apimachinery": "^2.0.0", - "@kubernetes-models/base": "^5.0.0", "@material-ui/core": "^4.12.2", "@material-ui/lab": "4.0.0-alpha.61", - "cronstrue": "^2.2.0", - "js-yaml": "^4.0.0", "kubernetes-models": "^4.1.0", - "lodash": "^4.17.21", - "luxon": "^3.0.0", "react-use": "^17.2.4" }, "devDependencies": { "@backstage/cli": "workspace:^", "@backstage/test-utils": "workspace:^", - "@testing-library/dom": "^10.0.0", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^16.0.0", "@types/node": "^20.16.0", diff --git a/plugins/kubernetes/knip-report.md b/plugins/kubernetes/knip-report.md index 11b66acd1b..97d5b385fd 100644 --- a/plugins/kubernetes/knip-report.md +++ b/plugins/kubernetes/knip-report.md @@ -1,18 +1,3 @@ # Knip report -## Unused dependencies (11) - -| Name | Location | Severity | -| :------------------------------ | :----------- | :------- | -| @kubernetes-models/apimachinery | plugins/kubernetes/package.json | error | -| @kubernetes-models/base | plugins/kubernetes/package.json | error | -| @kubernetes/client-node | plugins/kubernetes/package.json | error | -| @xterm/addon-attach | plugins/kubernetes/package.json | error | -| kubernetes-models | plugins/kubernetes/package.json | error | -| @xterm/addon-fit | plugins/kubernetes/package.json | error | -| @xterm/xterm | plugins/kubernetes/package.json | error | -| cronstrue | plugins/kubernetes/package.json | error | -| js-yaml | plugins/kubernetes/package.json | error | -| lodash | plugins/kubernetes/package.json | error | -| luxon | plugins/kubernetes/package.json | error | diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index e9da7b47ec..d5bc9c0b88 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -67,18 +67,7 @@ "@backstage/plugin-kubernetes-common": "workspace:^", "@backstage/plugin-kubernetes-react": "workspace:^", "@backstage/plugin-permission-react": "workspace:^", - "@kubernetes-models/apimachinery": "^2.0.0", - "@kubernetes-models/base": "^5.0.0", - "@kubernetes/client-node": "1.1.2", - "@material-ui/core": "^4.12.2", - "@xterm/addon-attach": "^0.11.0", - "@xterm/addon-fit": "^0.10.0", - "@xterm/xterm": "^5.5.0", - "cronstrue": "^2.2.0", - "js-yaml": "^4.0.0", - "kubernetes-models": "^4.1.0", - "lodash": "^4.17.21", - "luxon": "^3.0.0" + "@material-ui/core": "^4.12.2" }, "devDependencies": { "@backstage/cli": "workspace:^", From fa589daef639b24884fc306e7c504fac8f9ed5dd Mon Sep 17 00:00:00 2001 From: Hope Hadfield Date: Wed, 17 Sep 2025 16:29:54 -0400 Subject: [PATCH 027/244] add yarn.lock Signed-off-by: Hope Hadfield --- yarn.lock | 36 +----------------------------------- 1 file changed, 1 insertion(+), 35 deletions(-) diff --git a/yarn.lock b/yarn.lock index e606b8246d..ebc7061499 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4332,7 +4332,6 @@ __metadata: "@aws-sdk/client-eks": "npm:^3.350.0" "@aws-sdk/client-organizations": "npm:^3.350.0" "@aws-sdk/client-s3": "npm:^3.350.0" - "@aws-sdk/credential-providers": "npm:^3.350.0" "@aws-sdk/middleware-endpoint": "npm:^3.347.0" "@aws-sdk/types": "npm:^3.347.0" "@aws-sdk/util-stream-node": "npm:^3.350.0" @@ -4350,10 +4349,8 @@ __metadata: "@backstage/plugin-kubernetes-common": "workspace:^" aws-sdk-client-mock: "npm:^4.0.0" aws-sdk-client-mock-jest: "npm:^4.0.0" - luxon: "npm:^3.0.0" p-limit: "npm:^3.0.2" uuid: "npm:^11.0.0" - winston: "npm:^3.2.1" yaml: "npm:^2.0.0" languageName: unknown linkType: soft @@ -4371,7 +4368,6 @@ __metadata: "@backstage/integration": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" - luxon: "npm:^3.0.0" msw: "npm:^1.0.0" uuid: "npm:^11.0.0" languageName: unknown @@ -4403,7 +4399,6 @@ __metadata: dependencies: "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" - "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -4413,7 +4408,6 @@ __metadata: "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-events-backend-test-utils": "workspace:^" "@backstage/plugin-events-node": "workspace:^" - luxon: "npm:^3.0.0" msw: "npm:^1.0.0" uuid: "npm:^11.0.0" languageName: unknown @@ -4425,7 +4419,6 @@ __metadata: dependencies: "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" - "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" @@ -4435,7 +4428,6 @@ __metadata: "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-events-backend-test-utils": "workspace:^" "@backstage/plugin-events-node": "workspace:^" - luxon: "npm:^3.0.0" msw: "npm:^1.0.0" uuid: "npm:^11.0.0" languageName: unknown @@ -4470,7 +4462,6 @@ __metadata: "@backstage/plugin-catalog-node": "workspace:^" "@types/fs-extra": "npm:^11.0.0" fs-extra: "npm:^11.2.0" - luxon: "npm:^3.0.0" msw: "npm:^1.0.0" p-limit: "npm:^3.1.0" uuid: "npm:^11.0.0" @@ -4505,7 +4496,6 @@ __metadata: "@backstage/plugin-catalog-backend-module-github": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-events-node": "workspace:^" - luxon: "npm:^3.0.0" languageName: unknown linkType: soft @@ -4515,12 +4505,10 @@ __metadata: dependencies: "@backstage/backend-plugin-api": "workspace:^" "@backstage/backend-test-utils": "workspace:^" - "@backstage/catalog-client": "workspace:^" "@backstage/catalog-model": "workspace:^" "@backstage/cli": "workspace:^" "@backstage/config": "workspace:^" "@backstage/integration": "workspace:^" - "@backstage/plugin-catalog-backend": "workspace:^" "@backstage/plugin-catalog-common": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-events-node": "workspace:^" @@ -4531,7 +4519,6 @@ __metadata: "@types/lodash": "npm:^4.14.151" git-url-parse: "npm:^15.0.0" lodash: "npm:^4.17.21" - luxon: "npm:^3.0.0" minimatch: "npm:^9.0.0" msw: "npm:^2.0.0" type-fest: "npm:^4.41.0" @@ -4550,7 +4537,6 @@ __metadata: "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-events-backend-test-utils": "workspace:^" "@backstage/plugin-events-node": "workspace:^" - luxon: "npm:^3.0.0" languageName: unknown linkType: soft @@ -4572,7 +4558,6 @@ __metadata: "@gitbeaker/rest": "npm:^40.0.3" "@types/lodash": "npm:^4.14.151" lodash: "npm:^4.17.21" - luxon: "npm:^3.0.0" msw: "npm:^1.0.0" node-fetch: "npm:^2.7.0" uuid: "npm:^11.0.0" @@ -4654,7 +4639,6 @@ __metadata: "@microsoft/microsoft-graph-types": "npm:^2.6.0" "@types/lodash": "npm:^4.14.151" lodash: "npm:^4.17.21" - luxon: "npm:^3.0.0" msw: "npm:^1.0.0" p-limit: "npm:^3.0.2" qs: "npm:^6.9.4" @@ -4694,7 +4678,6 @@ __metadata: "@backstage/types": "workspace:^" "@types/lodash": "npm:^4.14.151" lodash: "npm:^4.17.21" - luxon: "npm:^3.0.0" msw: "npm:^1.0.0" uuid: "npm:^11.0.0" languageName: unknown @@ -5533,19 +5516,13 @@ __metadata: "@backstage/plugin-permission-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@kubernetes-models/apimachinery": "npm:^2.0.0" - "@kubernetes-models/base": "npm:^5.0.0" "@material-ui/core": "npm:^4.12.2" "@material-ui/lab": "npm:4.0.0-alpha.61" - "@testing-library/dom": "npm:^10.0.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" "@types/node": "npm:^20.16.0" "@types/react": "npm:^18.0.0" - cronstrue: "npm:^2.2.0" - js-yaml: "npm:^4.0.0" kubernetes-models: "npm:^4.1.0" - lodash: "npm:^4.17.21" - luxon: "npm:^3.0.0" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" react-router-dom: "npm:^6.3.0" @@ -5660,22 +5637,11 @@ __metadata: "@backstage/plugin-kubernetes-react": "workspace:^" "@backstage/plugin-permission-react": "workspace:^" "@backstage/test-utils": "workspace:^" - "@kubernetes-models/apimachinery": "npm:^2.0.0" - "@kubernetes-models/base": "npm:^5.0.0" - "@kubernetes/client-node": "npm:1.1.2" "@material-ui/core": "npm:^4.12.2" "@testing-library/dom": "npm:^10.0.0" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" "@types/react": "npm:^18.0.0" - "@xterm/addon-attach": "npm:^0.11.0" - "@xterm/addon-fit": "npm:^0.10.0" - "@xterm/xterm": "npm:^5.5.0" - cronstrue: "npm:^2.2.0" - js-yaml: "npm:^4.0.0" - kubernetes-models: "npm:^4.1.0" - lodash: "npm:^4.17.21" - luxon: "npm:^3.0.0" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" react-router-dom: "npm:^6.3.0" @@ -26680,7 +26646,7 @@ __metadata: languageName: node linkType: hard -"cronstrue@npm:^2.2.0, cronstrue@npm:^2.32.0": +"cronstrue@npm:^2.32.0": version: 2.52.0 resolution: "cronstrue@npm:2.52.0" bin: From 02c67c58cfafd662968674b67f0f5f446bc05f54 Mon Sep 17 00:00:00 2001 From: TA31OU Date: Thu, 18 Sep 2025 08:51:01 +0200 Subject: [PATCH 028/244] Feedback Signed-off-by: TA31OU --- plugins/catalog-backend-module-gitea/package.json | 2 +- .../EntityRelationsGraph/DefaultRenderEdge.tsx | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx diff --git a/plugins/catalog-backend-module-gitea/package.json b/plugins/catalog-backend-module-gitea/package.json index 8389ee70ef..c30c6a7dd2 100644 --- a/plugins/catalog-backend-module-gitea/package.json +++ b/plugins/catalog-backend-module-gitea/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitea", - "version": "0.1.4-next.1", + "version": "0.1.4-next.0", "description": "The gitea backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx b/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx deleted file mode 100644 index 379ce77f52..0000000000 --- a/plugins/catalog-graph/src/components/EntityRelationsGraph/DefaultRenderEdge.tsx +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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. - */ From 0016e09b289ed438ef8944d9642d8a85023befb2 Mon Sep 17 00:00:00 2001 From: Brent Swisher Date: Fri, 19 Sep 2025 08:37:02 -0400 Subject: [PATCH 029/244] Update fetchDSN example tests to use it.each block Signed-off-by: Brent Swisher --- .../src/actions/fetchDSN.examples.test.ts | 150 ++++++++---------- 1 file changed, 63 insertions(+), 87 deletions(-) diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.test.ts b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.test.ts index 609a366408..0eed483cbe 100644 --- a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.test.ts +++ b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.examples.test.ts @@ -19,7 +19,6 @@ import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test- import { ConfigReader } from '@backstage/config'; import { ActionContext } from '@backstage/plugin-scaffolder-node'; import { JsonObject } from '@backstage/types'; -import { randomBytes } from 'crypto'; import { setupServer } from 'msw/node'; import { HttpResponse, http } from 'msw'; import { createSentryFetchDSNAction } from './fetchDSN'; @@ -37,8 +36,9 @@ describe('sentry:fetch:dsn action', () => { }, }), }); - - const getActionContext = (): ActionContext<{ + const getActionContext = ( + authToken: string | null, + ): ActionContext<{ organizationSlug: string; projectSlug: string; authToken?: string; @@ -47,9 +47,9 @@ describe('sentry:fetch:dsn action', () => { workspacePath: './dev/proj', logger: jest.createMockFromModule('winston'), input: { - organizationSlug: 'org', - projectSlug: 'project', - authToken: randomBytes(5).toString('hex'), + organizationSlug: 'my-org', + projectSlug: 'my-project', + ...(authToken ? { authToken } : {}), }, }); @@ -86,89 +86,65 @@ describe('sentry:fetch:dsn action', () => { }, ]; - it(`should ${examples[0].description}`, async () => { - expect.assertions(3); + it.each([ + { + templateExample: examples[0], + expectedToken: + 'a14711beb516e1e910d2ede554dc1bf725654ef3c75e5a9106de9aec13d5df96', + }, + { + templateExample: examples[1], + expectedToken: + 'b15711beb516e1e910d2ede554dc1bf725654ef3c75e5a9106de9aec13d4gf93', + }, + ])( + `should $templateExample.description`, + async ({ templateExample, expectedToken }) => { + expect.assertions(3); - let input; - try { - input = yaml.parse(examples[0].example).steps[0].input; - } catch (error) { - console.error('Failed to parse YAML:', error); - } + let input; + try { + input = yaml.parse(templateExample.example).steps[0].input; + } catch (error) { + console.error('Failed to parse YAML:', error); + } - const action = createSentryFetchDSNAction(createScaffolderConfig()); - const actionContext = getActionContext(); + const action = createSentryFetchDSNAction( + createScaffolderConfig({ + sentry: { + token: + 'b15711beb516e1e910d2ede554dc1bf725654ef3c75e5a9106de9aec13d4gf93', + }, + }), + ); + const actionContext = getActionContext(input.authToken); - worker.use( - http.get( - `https://sentry.io/api/0/projects/${input.organizationSlug}/${input.projectSlug}/keys/`, - async ({ request }) => { - expect(request.headers.get('Authorization')).toBe( - `Bearer a14711beb516e1e910d2ede554dc1bf725654ef3c75e5a9106de9aec13d5df96`, - ); - expect(request.headers.get('Content-Type')).toBe(`application/json`); - return HttpResponse.json(mockSentryKeysResponse, { status: 200 }); + worker.use( + http.get( + `https://sentry.io/api/0/projects/${input.organizationSlug}/${input.projectSlug}/keys/`, + async ({ request }) => { + expect(request.headers.get('Authorization')).toBe( + `Bearer ${expectedToken}`, + ); + expect(request.headers.get('Content-Type')).toBe( + `application/json`, + ); + return HttpResponse.json(mockSentryKeysResponse, { status: 200 }); + }, + ), + ); + + await action.handler({ + ...actionContext, + input: { + ...actionContext.input, + ...input, }, - ), - ); - - await action.handler({ - ...actionContext, - input: { - ...actionContext.input, - ...input, - }, - }); - expect(actionContext.output).toHaveBeenCalledWith( - 'dsn', - 'https://abcdef1234567890@sentry.io/67890', - ); - }); - - it(`should ${examples[1].description}`, async () => { - expect.assertions(3); - - let input; - try { - input = yaml.parse(examples[1].example).steps[0].input; - } catch (error) { - console.error('Failed to parse YAML:', error); - } - - const sentryScaffolderConfigToken = randomBytes(5).toString('hex'); - const action = createSentryFetchDSNAction( - createScaffolderConfig({ - sentry: { - token: sentryScaffolderConfigToken, - }, - }), - ); - const actionContext = getActionContext(); - actionContext.input.authToken = undefined; - - worker.use( - http.get( - `https://sentry.io/api/0/projects/${input.organizationSlug}/${input.projectSlug}/keys/`, - async ({ request }) => { - expect(request.headers.get('Authorization')).toBe( - `Bearer ${sentryScaffolderConfigToken}`, - ); - expect(request.headers.get('Content-Type')).toBe(`application/json`); - return HttpResponse.json(mockSentryKeysResponse, { status: 200 }); - }, - ), - ); - - await action.handler({ - ...actionContext, - input: { - ...actionContext.input, - ...input, - }, - }); - expect(actionContext.output).toHaveBeenCalledWith( - 'dsn', - 'https://abcdef1234567890@sentry.io/67890', - ); - }); + }); + expect(actionContext.output).toHaveBeenCalledWith( + 'dsn', + 'https://abcdef1234567890@sentry.io/67890', + ); + }, + ); }); From f5e09631a43afd659c30b318e1bef9a03bc18bd8 Mon Sep 17 00:00:00 2001 From: Hope Hadfield Date: Thu, 18 Sep 2025 11:15:16 -0400 Subject: [PATCH 030/244] Remove unused dependencies in notifications and scaffolder Signed-off-by: Hope Hadfield --- .changeset/shiny-candles-hide.md | 9 +++++++++ .../knip-report.md | 5 ----- .../package.json | 1 - plugins/notifications-backend/knip-report.md | 14 -------------- plugins/notifications-backend/package.json | 7 +------ plugins/notifications/knip-report.md | 13 ------------- plugins/notifications/package.json | 4 ---- .../knip-report.md | 5 ----- .../package.json | 3 +-- .../knip-report.md | 5 ----- .../scaffolder-backend-module-gitlab/package.json | 1 - yarn.lock | 12 ------------ 12 files changed, 11 insertions(+), 68 deletions(-) create mode 100644 .changeset/shiny-candles-hide.md diff --git a/.changeset/shiny-candles-hide.md b/.changeset/shiny-candles-hide.md new file mode 100644 index 0000000000..7ec4a8062e --- /dev/null +++ b/.changeset/shiny-candles-hide.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch +'@backstage/plugin-notifications-backend-module-email': patch +'@backstage/plugin-scaffolder-backend-module-gitlab': patch +'@backstage/plugin-notifications-backend': patch +'@backstage/plugin-notifications': patch +--- + +Removed unused dependencies diff --git a/plugins/notifications-backend-module-email/knip-report.md b/plugins/notifications-backend-module-email/knip-report.md index a36d75cae4..97d5b385fd 100644 --- a/plugins/notifications-backend-module-email/knip-report.md +++ b/plugins/notifications-backend-module-email/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused dependencies (1) - -| Name | Location | Severity | -| :------------- | :----------- | :------- | -| @aws-sdk/types | plugins/notifications-backend-module-email/package.json | error | diff --git a/plugins/notifications-backend-module-email/package.json b/plugins/notifications-backend-module-email/package.json index ac8682fe2d..37b0f4d64d 100644 --- a/plugins/notifications-backend-module-email/package.json +++ b/plugins/notifications-backend-module-email/package.json @@ -35,7 +35,6 @@ }, "dependencies": { "@aws-sdk/client-ses": "^3.550.0", - "@aws-sdk/types": "^3.347.0", "@azure/communication-email": "^1.0.0", "@azure/identity": "^4.0.0", "@backstage/backend-plugin-api": "workspace:^", diff --git a/plugins/notifications-backend/knip-report.md b/plugins/notifications-backend/knip-report.md index 3514fea30a..97d5b385fd 100644 --- a/plugins/notifications-backend/knip-report.md +++ b/plugins/notifications-backend/knip-report.md @@ -1,17 +1,3 @@ # Knip report -## Unused dependencies (4) - -| Name | Location | Severity | -| :---------------------------- | :----------- | :------- | -| @backstage/plugin-events-node | plugins/notifications-backend/package.json | error | -| @backstage/plugin-auth-node | plugins/notifications-backend/package.json | error | -| winston | plugins/notifications-backend/package.json | error | -| yn | plugins/notifications-backend/package.json | error | - -## Unused devDependencies (1) - -| Name | Location | Severity | -| :-- | :----------- | :------- | -| msw | plugins/notifications-backend/package.json | error | diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index 1a2c746409..975e2fec0a 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -43,9 +43,7 @@ "@backstage/catalog-model": "workspace:^", "@backstage/config": "workspace:^", "@backstage/errors": "workspace:^", - "@backstage/plugin-auth-node": "workspace:^", "@backstage/plugin-catalog-node": "workspace:^", - "@backstage/plugin-events-node": "workspace:^", "@backstage/plugin-notifications-common": "workspace:^", "@backstage/plugin-notifications-node": "workspace:^", "@backstage/plugin-signals-node": "workspace:^", @@ -54,9 +52,7 @@ "express-promise-router": "^4.1.0", "knex": "^3.0.0", "p-throttle": "^4.1.1", - "uuid": "^11.0.0", - "winston": "^3.2.1", - "yn": "^4.0.0" + "uuid": "^11.0.0" }, "devDependencies": { "@backstage/backend-defaults": "workspace:^", @@ -68,7 +64,6 @@ "@backstage/plugin-signals-backend": "workspace:^", "@types/express": "^4.17.6", "@types/supertest": "^2.0.8", - "msw": "^1.0.0", "supertest": "^7.0.0" }, "configSchema": "config.d.ts" diff --git a/plugins/notifications/knip-report.md b/plugins/notifications/knip-report.md index 6cd21cf3b8..97d5b385fd 100644 --- a/plugins/notifications/knip-report.md +++ b/plugins/notifications/knip-report.md @@ -1,16 +1,3 @@ # Knip report -## Unused dependencies (2) - -| Name | Location | Severity | -| :--------------- | :----------- | :------- | -| @backstage/types | plugins/notifications/package.json | error | -| @material-ui/lab | plugins/notifications/package.json | error | - -## Unused devDependencies (2) - -| Name | Location | Severity | -| :-------------------------- | :----------- | :------- | -| @testing-library/user-event | plugins/notifications/package.json | error | -| @backstage/core-app-api | plugins/notifications/package.json | error | diff --git a/plugins/notifications/package.json b/plugins/notifications/package.json index e6d66a5ec7..cbc06d242e 100644 --- a/plugins/notifications/package.json +++ b/plugins/notifications/package.json @@ -59,10 +59,8 @@ "@backstage/plugin-notifications-common": "workspace:^", "@backstage/plugin-signals-react": "workspace:^", "@backstage/theme": "workspace:^", - "@backstage/types": "workspace:^", "@material-ui/core": "^4.9.13", "@material-ui/icons": "^4.9.1", - "@material-ui/lab": "^4.0.0-alpha.61", "lodash": "^4.17.21", "material-ui-confirm": "^3.0.12", "notistack": "^3.0.1", @@ -71,13 +69,11 @@ }, "devDependencies": { "@backstage/cli": "workspace:^", - "@backstage/core-app-api": "workspace:^", "@backstage/dev-utils": "workspace:^", "@backstage/plugin-signals": "workspace:^", "@backstage/test-utils": "workspace:^", "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^16.0.0", - "@testing-library/user-event": "^14.0.0", "@types/react": "^18.0.0", "msw": "^1.0.0", "react": "^18.0.2", diff --git a/plugins/scaffolder-backend-module-bitbucket-server/knip-report.md b/plugins/scaffolder-backend-module-bitbucket-server/knip-report.md index 0dd672d03d..97d5b385fd 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/knip-report.md +++ b/plugins/scaffolder-backend-module-bitbucket-server/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused dependencies (1) - -| Name | Location | Severity | -| :-- | :----------- | :------- | -| zod | plugins/scaffolder-backend-module-bitbucket-server/package.json | error | diff --git a/plugins/scaffolder-backend-module-bitbucket-server/package.json b/plugins/scaffolder-backend-module-bitbucket-server/package.json index 452653afb7..c980146970 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-server/package.json @@ -48,8 +48,7 @@ "@backstage/integration": "workspace:^", "@backstage/plugin-scaffolder-node": "workspace:^", "fs-extra": "^11.2.0", - "yaml": "^2.0.0", - "zod": "^3.22.4" + "yaml": "^2.0.0" }, "devDependencies": { "@backstage/backend-test-utils": "workspace:^", diff --git a/plugins/scaffolder-backend-module-gitlab/knip-report.md b/plugins/scaffolder-backend-module-gitlab/knip-report.md index 3e1fc873d4..97d5b385fd 100644 --- a/plugins/scaffolder-backend-module-gitlab/knip-report.md +++ b/plugins/scaffolder-backend-module-gitlab/knip-report.md @@ -1,8 +1,3 @@ # Knip report -## Unused dependencies (1) - -| Name | Location | Severity | -| :------ | :----------- | :------- | -| winston | plugins/scaffolder-backend-module-gitlab/package.json | error | diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index f8194a434c..c1fb8024e9 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -53,7 +53,6 @@ "@gitbeaker/requester-utils": "^41.2.0", "@gitbeaker/rest": "^41.2.0", "luxon": "^3.0.0", - "winston": "^3.2.1", "yaml": "^2.0.0", "zod": "^3.22.4" }, diff --git a/yarn.lock b/yarn.lock index 483bd8e5b8..d0948f8474 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5715,7 +5715,6 @@ __metadata: resolution: "@backstage/plugin-notifications-backend-module-email@workspace:plugins/notifications-backend-module-email" dependencies: "@aws-sdk/client-ses": "npm:^3.550.0" - "@aws-sdk/types": "npm:^3.347.0" "@azure/communication-email": "npm:^1.0.0" "@azure/identity": "npm:^4.0.0" "@backstage/backend-plugin-api": "workspace:^" @@ -5775,10 +5774,8 @@ __metadata: "@backstage/errors": "workspace:^" "@backstage/plugin-auth-backend": "workspace:^" "@backstage/plugin-auth-backend-module-guest-provider": "workspace:^" - "@backstage/plugin-auth-node": "workspace:^" "@backstage/plugin-catalog-node": "workspace:^" "@backstage/plugin-events-backend": "workspace:^" - "@backstage/plugin-events-node": "workspace:^" "@backstage/plugin-notifications-common": "workspace:^" "@backstage/plugin-notifications-node": "workspace:^" "@backstage/plugin-signals-backend": "workspace:^" @@ -5789,12 +5786,9 @@ __metadata: express: "npm:^4.17.1" express-promise-router: "npm:^4.1.0" knex: "npm:^3.0.0" - msw: "npm:^1.0.0" p-throttle: "npm:^4.1.1" supertest: "npm:^7.0.0" uuid: "npm:^11.0.0" - winston: "npm:^3.2.1" - yn: "npm:^4.0.0" languageName: unknown linkType: soft @@ -5832,7 +5826,6 @@ __metadata: resolution: "@backstage/plugin-notifications@workspace:plugins/notifications" dependencies: "@backstage/cli": "workspace:^" - "@backstage/core-app-api": "workspace:^" "@backstage/core-compat-api": "workspace:^" "@backstage/core-components": "workspace:^" "@backstage/core-plugin-api": "workspace:^" @@ -5844,13 +5837,10 @@ __metadata: "@backstage/plugin-signals-react": "workspace:^" "@backstage/test-utils": "workspace:^" "@backstage/theme": "workspace:^" - "@backstage/types": "workspace:^" "@material-ui/core": "npm:^4.9.13" "@material-ui/icons": "npm:^4.9.1" - "@material-ui/lab": "npm:^4.0.0-alpha.61" "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" - "@testing-library/user-event": "npm:^14.0.0" "@types/react": "npm:^18.0.0" lodash: "npm:^4.17.21" material-ui-confirm: "npm:^3.0.12" @@ -6147,7 +6137,6 @@ __metadata: fs-extra: "npm:^11.2.0" msw: "npm:^1.0.0" yaml: "npm:^2.0.0" - zod: "npm:^3.22.4" languageName: unknown linkType: soft @@ -6307,7 +6296,6 @@ __metadata: "@gitbeaker/requester-utils": "npm:^41.2.0" "@gitbeaker/rest": "npm:^41.2.0" luxon: "npm:^3.0.0" - winston: "npm:^3.2.1" yaml: "npm:^2.0.0" zod: "npm:^3.22.4" languageName: unknown From 9acc1d6c9474b224664118888c643b1e358abe3d Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Tue, 23 Sep 2025 16:36:42 +0100 Subject: [PATCH 031/244] Adding show/hide visibility and clear action icons to BUI TextField Signed-off-by: Hermione Bird --- .changeset/eighty-cows-care.md | 5 ++ packages/ui/css/styles.css | 25 ++++++++ .../components/TextField/TextField.styles.css | 23 +++++++ .../ui/src/components/TextField/TextField.tsx | 64 ++++++++++++++++++- packages/ui/src/components/TextField/types.ts | 10 +++ packages/ui/src/utils/componentDefinitions.ts | 1 + 6 files changed, 127 insertions(+), 1 deletion(-) create mode 100644 .changeset/eighty-cows-care.md diff --git a/.changeset/eighty-cows-care.md b/.changeset/eighty-cows-care.md new file mode 100644 index 0000000000..fc0a5c48bc --- /dev/null +++ b/.changeset/eighty-cows-care.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Added show/hide visibility and clear action icons to TextField diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index 8aa99175b3..e9bc5a289f 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -10451,6 +10451,31 @@ } } +.bui-InputAction { + position: absolute; + display: flex; + flex-direction: row; + right: var(--bui-space-3); + top: 50%; + transform: translateY(-50%); + color: var(--bui-fg-primary); + flex-shrink: 0; + /* To animate the icon when the input is collapsed */ + transition: right 0.2s ease-in-out; + + &[data-size='small'], + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + &[data-size='medium'], + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } +} + .bui-InputIcon { left: var(--bui-space-3); margin-right: var(--bui-space-1); diff --git a/packages/ui/src/components/TextField/TextField.styles.css b/packages/ui/src/components/TextField/TextField.styles.css index 792d5d85c9..77b39396e1 100644 --- a/packages/ui/src/components/TextField/TextField.styles.css +++ b/packages/ui/src/components/TextField/TextField.styles.css @@ -116,3 +116,26 @@ border: 1px solid var(--bui-border-disabled); } } + +.bui-InputAction { + position: absolute; + right: var(--bui-space-3); + top: 50%; + transform: translateY(-50%); + color: var(--bui-fg-primary); + flex-shrink: 0; + /* To animate the icon when the input is collapsed */ + transition: right 0.2s ease-in-out; + + &[data-size='small'], + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + &[data-size='medium'], + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } +} diff --git a/packages/ui/src/components/TextField/TextField.tsx b/packages/ui/src/components/TextField/TextField.tsx index 2756c3c85f..748dd4655a 100644 --- a/packages/ui/src/components/TextField/TextField.tsx +++ b/packages/ui/src/components/TextField/TextField.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { forwardRef, useEffect } from 'react'; +import { forwardRef, useEffect, useState } from 'react'; import { Input, TextField as AriaTextField } from 'react-aria-components'; import clsx from 'clsx'; import { FieldLabel } from '../FieldLabel'; @@ -22,6 +22,8 @@ import { FieldError } from '../FieldError'; import type { TextFieldProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { Icon } from '../Icon'; +import { ButtonIcon } from '../ButtonIcon'; /** @public */ export const TextField = forwardRef( @@ -34,6 +36,8 @@ export const TextField = forwardRef( secondaryLabel, description, isRequired, + enableVisibility, + isClearable, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, placeholder, @@ -56,6 +60,30 @@ export const TextField = forwardRef( const secondaryLabelText = secondaryLabel || (isRequired ? 'Required' : null); + // Manage value for clearable behavior, supporting both controlled and uncontrolled usage + const { + value: controlledValue, + defaultValue, + onChange, + isDisabled, + } = rest as any; + const [uncontrolledValue, setUncontrolledValue] = useState( + defaultValue ?? '', + ); + const effectiveValue = + controlledValue !== undefined ? controlledValue : uncontrolledValue; + const handleChange = (value: string) => { + if (controlledValue === undefined) setUncontrolledValue(value); + onChange?.(value); + }; + + // Manage secret visibility toggle + const [isVisible, setIsVisible] = useState(false); + const showClear = Boolean( + isClearable && effectiveValue && effectiveValue.length > 0, + ); + const showSecretToggle = Boolean(enableVisibility); + return ( ( aria-label={ariaLabel} aria-labelledby={ariaLabelledBy} {...rest} + value={effectiveValue} + onChange={handleChange} ref={ref} > ( {icon} )} + {(showClear || showSecretToggle) && ( +
+ {showSecretToggle && ( + setIsVisible(v => !v)} + icon={} + /> + )} + {showClear && ( + { + if (controlledValue === undefined) { + setUncontrolledValue(''); + } + onChange?.(''); + }} + icon={} + /> + )} +
+ )} diff --git a/packages/ui/src/components/TextField/types.ts b/packages/ui/src/components/TextField/types.ts index 75a5c68aaa..d64be41050 100644 --- a/packages/ui/src/components/TextField/types.ts +++ b/packages/ui/src/components/TextField/types.ts @@ -38,4 +38,14 @@ export interface TextFieldProps * Text to display in the input when it has no value */ placeholder?: string; + + /** + * Displays icon to toggle between showing and hiding the input value + */ + enableVisibility?: boolean; + + /** + * Displays a clear button when there is content in the input + */ + isClearable?: boolean; } diff --git a/packages/ui/src/utils/componentDefinitions.ts b/packages/ui/src/utils/componentDefinitions.ts index 5a0e8bdc1a..bf01a0dc63 100644 --- a/packages/ui/src/utils/componentDefinitions.ts +++ b/packages/ui/src/utils/componentDefinitions.ts @@ -286,6 +286,7 @@ export const componentDefinitions = { inputWrapper: 'bui-InputWrapper', input: 'bui-Input', inputIcon: 'bui-InputIcon', + inputAction: 'bui-InputAction', }, dataAttributes: { invalid: [true, false] as const, From d144d916c8b43f5954b3aefe426289325de75c83 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Tue, 23 Sep 2025 17:39:22 +0100 Subject: [PATCH 032/244] reduce right spacing Signed-off-by: Hermione Bird --- packages/ui/css/styles.css | 2 +- packages/ui/src/components/TextField/TextField.styles.css | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index e9bc5a289f..1ea7d73bf7 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -10455,7 +10455,7 @@ position: absolute; display: flex; flex-direction: row; - right: var(--bui-space-3); + right: var(--bui-space-1); top: 50%; transform: translateY(-50%); color: var(--bui-fg-primary); diff --git a/packages/ui/src/components/TextField/TextField.styles.css b/packages/ui/src/components/TextField/TextField.styles.css index 77b39396e1..c5765bf8ac 100644 --- a/packages/ui/src/components/TextField/TextField.styles.css +++ b/packages/ui/src/components/TextField/TextField.styles.css @@ -119,7 +119,7 @@ .bui-InputAction { position: absolute; - right: var(--bui-space-3); + right: var(--bui-space-1); top: 50%; transform: translateY(-50%); color: var(--bui-fg-primary); From 8192e82be1184d08e5b3811de8f6296c4c691111 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Tue, 23 Sep 2025 18:12:41 +0100 Subject: [PATCH 033/244] remove clear action Signed-off-by: Hermione Bird --- .../ui/src/components/TextField/TextField.tsx | 57 +++---------------- 1 file changed, 8 insertions(+), 49 deletions(-) diff --git a/packages/ui/src/components/TextField/TextField.tsx b/packages/ui/src/components/TextField/TextField.tsx index 748dd4655a..c4fc81f029 100644 --- a/packages/ui/src/components/TextField/TextField.tsx +++ b/packages/ui/src/components/TextField/TextField.tsx @@ -37,7 +37,6 @@ export const TextField = forwardRef( description, isRequired, enableVisibility, - isClearable, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, placeholder, @@ -60,28 +59,8 @@ export const TextField = forwardRef( const secondaryLabelText = secondaryLabel || (isRequired ? 'Required' : null); - // Manage value for clearable behavior, supporting both controlled and uncontrolled usage - const { - value: controlledValue, - defaultValue, - onChange, - isDisabled, - } = rest as any; - const [uncontrolledValue, setUncontrolledValue] = useState( - defaultValue ?? '', - ); - const effectiveValue = - controlledValue !== undefined ? controlledValue : uncontrolledValue; - const handleChange = (value: string) => { - if (controlledValue === undefined) setUncontrolledValue(value); - onChange?.(value); - }; - // Manage secret visibility toggle const [isVisible, setIsVisible] = useState(false); - const showClear = Boolean( - isClearable && effectiveValue && effectiveValue.length > 0, - ); const showSecretToggle = Boolean(enableVisibility); return ( @@ -91,8 +70,6 @@ export const TextField = forwardRef( aria-label={ariaLabel} aria-labelledby={ariaLabelledBy} {...rest} - value={effectiveValue} - onChange={handleChange} ref={ref} > ( {icon} )} - {(showClear || showSecretToggle) && ( + {showSecretToggle && (
- {showSecretToggle && ( - setIsVisible(v => !v)} - icon={} - /> - )} - {showClear && ( - { - if (controlledValue === undefined) { - setUncontrolledValue(''); - } - onChange?.(''); - }} - icon={} - /> - )} + setIsVisible(v => !v)} + icon={} + />
)} Date: Tue, 23 Sep 2025 11:58:54 -0400 Subject: [PATCH 034/244] Implement AbortController request cancellation for search. Signed-off-by: Sydney Achinger --- .changeset/ripe-yaks-brake.md | 6 + plugins/search-react/report.api.md | 14 +- plugins/search-react/src/api.ts | 10 +- .../SearchAutocomplete.test.tsx | 68 +++++--- .../components/SearchBar/SearchBar.test.tsx | 12 ++ .../SearchFilter/SearchFilter.test.tsx | 8 + .../SearchPagination.test.tsx | 12 ++ .../src/context/SearchContext.test.tsx | 151 +++++++++++------- .../src/context/SearchContext.tsx | 36 ++++- plugins/search/src/apis.test.ts | 17 +- plugins/search/src/apis.ts | 9 +- .../HomePageSearchBar.test.tsx | 3 + .../SearchModal/SearchModal.test.tsx | 21 ++- .../SearchType/SearchType.Accordion.test.tsx | 34 ++-- .../SearchType/SearchType.Accordion.tsx | 36 ++++- .../components/SearchType/SearchType.test.tsx | 13 +- 16 files changed, 322 insertions(+), 128 deletions(-) create mode 100644 .changeset/ripe-yaks-brake.md diff --git a/.changeset/ripe-yaks-brake.md b/.changeset/ripe-yaks-brake.md new file mode 100644 index 0000000000..953d0f3192 --- /dev/null +++ b/.changeset/ripe-yaks-brake.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-search-react': patch +'@backstage/plugin-search': patch +--- + +Implement AbortController request cancellation in SearchBar to prevent overlapping search requests. This change ensures that when users type quickly, previous search requests are properly canceled before new ones start. diff --git a/plugins/search-react/report.api.md b/plugins/search-react/report.api.md index f0ec6030fd..6c9a1cd09d 100644 --- a/plugins/search-react/report.api.md +++ b/plugins/search-react/report.api.md @@ -93,13 +93,23 @@ export class MockSearchApi implements SearchApi { // (undocumented) mockedResults?: SearchResultSet | undefined; // (undocumented) - query(): Promise; + query( + _query: SearchQuery, + _options?: { + signal?: AbortSignal; + }, + ): Promise; } // @public (undocumented) export interface SearchApi { // (undocumented) - query(query: SearchQuery): Promise; + query( + query: SearchQuery, + options?: { + signal?: AbortSignal; + }, + ): Promise; } // @public (undocumented) diff --git a/plugins/search-react/src/api.ts b/plugins/search-react/src/api.ts index 24a247a641..61da8a3d77 100644 --- a/plugins/search-react/src/api.ts +++ b/plugins/search-react/src/api.ts @@ -28,7 +28,10 @@ export const searchApiRef = createApiRef({ * @public */ export interface SearchApi { - query(query: SearchQuery): Promise; + query( + query: SearchQuery, + options?: { signal?: AbortSignal }, + ): Promise; } /** @@ -39,7 +42,10 @@ export interface SearchApi { export class MockSearchApi implements SearchApi { constructor(public mockedResults?: SearchResultSet) {} - query(): Promise { + query( + _query: SearchQuery, + _options?: { signal?: AbortSignal }, + ): Promise { return Promise.resolve(this.mockedResults || { results: [] }); } } diff --git a/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.test.tsx b/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.test.tsx index 173d6c3450..36757dafff 100644 --- a/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.test.tsx +++ b/plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.test.tsx @@ -95,12 +95,17 @@ describe('SearchAutocomplete', () => { ); await waitFor(() => { - expect(query).toHaveBeenCalledWith({ - filters: {}, - pageCursor: undefined, - term: options[0], - types: [], - }); + expect(query).toHaveBeenCalledWith( + { + filters: {}, + pageCursor: undefined, + term: options[0], + types: [], + }, + { + signal: expect.any(AbortSignal), + }, + ); }); }); @@ -117,23 +122,33 @@ describe('SearchAutocomplete', () => { ); await waitFor(() => { - expect(query).toHaveBeenCalledWith({ - filters: {}, - pageCursor: undefined, - term: options[0], - types: [], - }); + expect(query).toHaveBeenCalledWith( + { + filters: {}, + pageCursor: undefined, + term: options[0], + types: [], + }, + { + signal: expect.any(AbortSignal), + }, + ); }); await userEvent.click(screen.getByLabelText('Clear')); await waitFor(() => { - expect(query).toHaveBeenCalledWith({ - filters: {}, - pageCursor: undefined, - term: '', - types: [], - }); + expect(query).toHaveBeenCalledWith( + { + filters: {}, + pageCursor: undefined, + term: '', + types: [], + }, + { + signal: expect.any(AbortSignal), + }, + ); }); }); @@ -154,12 +169,17 @@ describe('SearchAutocomplete', () => { await userEvent.click(screen.getByText(options[0])); await waitFor(() => { - expect(query).toHaveBeenCalledWith({ - filters: {}, - pageCursor: undefined, - term: options[0], - types: [], - }); + expect(query).toHaveBeenCalledWith( + { + filters: {}, + pageCursor: undefined, + term: options[0], + types: [], + }, + { + signal: expect.any(AbortSignal), + }, + ); }); }); diff --git a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx index 54889792db..977f413f97 100644 --- a/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx +++ b/plugins/search-react/src/components/SearchBar/SearchBar.test.tsx @@ -171,6 +171,9 @@ describe('SearchBar', () => { expect(searchApiMock.query).toHaveBeenLastCalledWith( expect.objectContaining({ term: value }), + { + signal: expect.any(AbortSignal), + }, ); jest.runAllTimers(); @@ -203,6 +206,9 @@ describe('SearchBar', () => { expect(searchApiMock.query).toHaveBeenLastCalledWith( expect.objectContaining({ term: '' }), + { + signal: expect.any(AbortSignal), + }, ); }); @@ -254,6 +260,9 @@ describe('SearchBar', () => { await waitFor(() => expect(searchApiMock.query).not.toHaveBeenLastCalledWith( expect.objectContaining({ term: value }), + expect.objectContaining({ + signal: expect.any(AbortSignal), + }), ), ); @@ -265,6 +274,9 @@ describe('SearchBar', () => { expect(searchApiMock.query).toHaveBeenLastCalledWith( expect.objectContaining({ term: value }), + { + signal: expect.any(AbortSignal), + }, ); jest.runAllTimers(); diff --git a/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx b/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx index d8d3b75aa2..7191b842d3 100644 --- a/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx +++ b/plugins/search-react/src/components/SearchFilter/SearchFilter.test.tsx @@ -178,6 +178,7 @@ describe('SearchFilter', () => { await waitFor(() => { expect(searchApiMock.query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: { field: [values[0]] } }), + { signal: expect.any(Object) }, ); }); @@ -186,6 +187,7 @@ describe('SearchFilter', () => { await waitFor(() => { expect(searchApiMock.query).toHaveBeenLastCalledWith( expect.objectContaining({ filters: {} }), + { signal: expect.any(Object) }, ); }); }); @@ -217,6 +219,7 @@ describe('SearchFilter', () => { expect.objectContaining({ filters: { ...filters, field: [values[0]] }, }), + { signal: expect.any(Object) }, ); }); @@ -225,6 +228,7 @@ describe('SearchFilter', () => { await waitFor(() => { expect(searchApiMock.query).toHaveBeenLastCalledWith( expect.objectContaining({ filters }), + { signal: expect.any(Object) }, ); }); }); @@ -421,6 +425,7 @@ describe('SearchFilter', () => { expect.objectContaining({ filters: { [name]: values[0] }, }), + { signal: expect.any(AbortSignal) }, ); }); @@ -437,6 +442,7 @@ describe('SearchFilter', () => { expect.objectContaining({ filters: {}, }), + { signal: expect.any(AbortSignal) }, ); }); }); @@ -479,6 +485,7 @@ describe('SearchFilter', () => { expect.objectContaining({ filters: { ...filters, [name]: values[0] }, }), + { signal: expect.any(AbortSignal) }, ); }); @@ -493,6 +500,7 @@ describe('SearchFilter', () => { await waitFor(() => { expect(searchApiMock.query).toHaveBeenLastCalledWith( expect.objectContaining({ filters }), + { signal: expect.any(AbortSignal) }, ); }); }); diff --git a/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx b/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx index d601caadd9..e482dc3a75 100644 --- a/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx +++ b/plugins/search-react/src/components/SearchPagination/SearchPagination.test.tsx @@ -197,6 +197,9 @@ describe('SearchPagination', () => { expect.objectContaining({ pageLimit: 10, }), + { + signal: expect.any(AbortSignal), + }, ); }); @@ -229,6 +232,9 @@ describe('SearchPagination', () => { expect.objectContaining({ pageCursor: 'Mg==', // page: 2 }), + { + signal: expect.any(AbortSignal), + }, ); await userEvent.click(screen.getByLabelText('Previous page')); @@ -239,6 +245,9 @@ describe('SearchPagination', () => { expect.objectContaining({ pageCursor: 'MQ==', // page: 1 }), + { + signal: expect.any(AbortSignal), + }, ); }); @@ -271,6 +280,9 @@ describe('SearchPagination', () => { pageCursor: undefined, pageLimit: 10, }), + { + signal: expect.any(AbortSignal), + }, ); }); }); diff --git a/plugins/search-react/src/context/SearchContext.test.tsx b/plugins/search-react/src/context/SearchContext.test.tsx index f604183c7f..cbdf684b70 100644 --- a/plugins/search-react/src/context/SearchContext.test.tsx +++ b/plugins/search-react/src/context/SearchContext.test.tsx @@ -264,11 +264,14 @@ describe('SearchContext', () => { result.current.setTerm(term); }); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - term, - types: ['*'], - filters: {}, - }); + expect(searchApiMock.query).toHaveBeenLastCalledWith( + { + term, + types: ['*'], + filters: {}, + }, + { signal: expect.any(AbortSignal) }, + ); }); it('When types is set', async () => { @@ -286,11 +289,14 @@ describe('SearchContext', () => { result.current.setTypes(types); }); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - types, - term: '', - filters: {}, - }); + expect(searchApiMock.query).toHaveBeenLastCalledWith( + { + types, + term: '', + filters: {}, + }, + { signal: expect.any(AbortSignal) }, + ); }); it('When filters are set', async () => { @@ -308,11 +314,14 @@ describe('SearchContext', () => { result.current.setFilters(filters); }); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - filters, - term: '', - types: ['*'], - }); + expect(searchApiMock.query).toHaveBeenLastCalledWith( + { + filters, + term: '', + types: ['*'], + }, + { signal: expect.any(AbortSignal) }, + ); }); it('When page limit is set', async () => { @@ -330,12 +339,15 @@ describe('SearchContext', () => { result.current.setPageLimit(pageLimit); }); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - pageLimit, - term: '', - types: ['*'], - filters: {}, - }); + expect(searchApiMock.query).toHaveBeenLastCalledWith( + { + pageLimit, + term: '', + types: ['*'], + filters: {}, + }, + { signal: expect.any(AbortSignal) }, + ); }); it('When page cursor is set', async () => { @@ -353,12 +365,15 @@ describe('SearchContext', () => { result.current.setPageCursor(pageCursor); }); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - pageCursor, - term: '', - types: ['*'], - filters: {}, - }); + expect(searchApiMock.query).toHaveBeenLastCalledWith( + { + pageCursor, + term: '', + types: ['*'], + filters: {}, + }, + { signal: expect.any(AbortSignal) }, + ); }); it('provides function for fetch the next page', async () => { @@ -382,12 +397,15 @@ describe('SearchContext', () => { result.current.fetchNextPage!(); }); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - term: '', - types: ['*'], - filters: {}, - pageCursor: 'NEXT', - }); + expect(searchApiMock.query).toHaveBeenLastCalledWith( + { + term: '', + types: ['*'], + filters: {}, + pageCursor: 'NEXT', + }, + { signal: expect.any(AbortSignal) }, + ); }); it('provides function for fetch the previous page', async () => { @@ -410,12 +428,15 @@ describe('SearchContext', () => { result.current.fetchPreviousPage!(); }); - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - term: '', - types: ['*'], - filters: {}, - pageCursor: 'PREVIOUS', - }); + expect(searchApiMock.query).toHaveBeenLastCalledWith( + { + term: '', + types: ['*'], + filters: {}, + pageCursor: 'PREVIOUS', + }, + { signal: expect.any(AbortSignal) }, + ); }); }); @@ -456,11 +477,14 @@ describe('SearchContext', () => { }); await waitFor(() => { - expect(searchApiMock.query).toHaveBeenCalledWith({ - term: '', - types: ['*'], - filters: {}, - }); + expect(searchApiMock.query).toHaveBeenCalledWith( + { + term: '', + types: ['*'], + filters: {}, + }, + { signal: expect.any(AbortSignal) }, + ); expect(analyticsApiMock.captureEvent).not.toHaveBeenCalled(); }); @@ -470,11 +494,14 @@ describe('SearchContext', () => { }); await waitFor(() => { - expect(searchApiMock.query).toHaveBeenCalledWith({ - term: 'eva', - types: ['*'], - filters: {}, - }); + expect(searchApiMock.query).toHaveBeenCalledWith( + { + term: 'eva', + types: ['*'], + filters: {}, + }, + { signal: expect.any(AbortSignal) }, + ); expect(analyticsApiMock.captureEvent).toHaveBeenCalledWith({ action: 'search', subject: 'eva', @@ -493,11 +520,14 @@ describe('SearchContext', () => { }); await waitFor(() => { - expect(searchApiMock.query).toHaveBeenCalledWith({ - term: 'eva.m', - types: ['*'], - filters: {}, - }); + expect(searchApiMock.query).toHaveBeenCalledWith( + { + term: 'eva.m', + types: ['*'], + filters: {}, + }, + { signal: expect.any(AbortSignal) }, + ); expect(analyticsApiMock.captureEvent).toHaveBeenCalledWith({ action: 'search', subject: 'eva.m', @@ -531,11 +561,14 @@ describe('SearchContext', () => { }); await waitFor(() => { - expect(searchApiMock.query).toHaveBeenLastCalledWith({ - term: 'term', - types: ['*'], - filters: {}, - }); + expect(searchApiMock.query).toHaveBeenLastCalledWith( + { + term: 'term', + types: ['*'], + filters: {}, + }, + { signal: expect.any(AbortSignal) }, + ); expect(analyticsApiMock.captureEvent).toHaveBeenCalledWith({ action: 'search', subject: 'term', diff --git a/plugins/search-react/src/context/SearchContext.tsx b/plugins/search-react/src/context/SearchContext.tsx index 3bd29c881a..ba06010789 100644 --- a/plugins/search-react/src/context/SearchContext.tsx +++ b/plugins/search-react/src/context/SearchContext.tsx @@ -23,6 +23,7 @@ import { useCallback, useContext, useEffect, + useRef, useState, } from 'react'; import useAsync, { AsyncState } from 'react-use/esm/useAsync'; @@ -132,15 +133,28 @@ const useSearchContextValue = ( const prevTerm = usePrevious(term); const prevFilters = usePrevious(filters); + const abortControllerRef = useRef(null); const result = useAsync(async () => { - const resultSet = await searchApi.query({ - term, - types, - filters, - pageLimit, - pageCursor, - }); + // Here we cancel the previous request before making a new one + if (abortControllerRef.current) { + abortControllerRef.current.abort(); + } + + const controller = new AbortController(); + abortControllerRef.current = controller; + + const resultSet = await searchApi.query( + { + term, + types, + filters, + pageLimit, + pageCursor, + }, + { signal: controller.signal }, + ); + if (term) { analytics.captureEvent('search', term, { value: resultSet.numberOfResults, @@ -162,6 +176,14 @@ const useSearchContextValue = ( setPageCursor(result.value?.previousPageCursor); }, [result.value?.previousPageCursor]); + useEffect(() => { + return () => { + if (abortControllerRef.current) { + abortControllerRef.current.abort(); + } + }; + }, []); + useEffect(() => { // Any time a term is reset, we want to start from page 0. // Only reset the term if it has been modified by the user at least once, the initial state must not reset the term. diff --git a/plugins/search/src/apis.test.ts b/plugins/search/src/apis.test.ts index 15745d2e68..1bb245dc9f 100644 --- a/plugins/search/src/apis.test.ts +++ b/plugins/search/src/apis.test.ts @@ -52,10 +52,19 @@ describe('apis', () => { identityApi.getCredentials.mockResolvedValue({}); await client.query(query); expect(getBaseUrl).toHaveBeenLastCalledWith('search'); - expect(mockFetch).toHaveBeenLastCalledWith( - `${baseUrl}/query?term=`, - undefined, - ); + expect(mockFetch).toHaveBeenLastCalledWith(`${baseUrl}/query?term=`, { + signal: undefined, + }); + }); + + it('Fetch is called with abort signal when provided', async () => { + identityApi.getCredentials.mockResolvedValue({}); + const abortController = new AbortController(); + await client.query(query, { signal: abortController.signal }); + expect(getBaseUrl).toHaveBeenLastCalledWith('search'); + expect(mockFetch).toHaveBeenLastCalledWith(`${baseUrl}/query?term=`, { + signal: abortController.signal, + }); }); it('Resolves JSON from fetch response', async () => { diff --git a/plugins/search/src/apis.ts b/plugins/search/src/apis.ts index b56d88a22c..03e6b6d1d4 100644 --- a/plugins/search/src/apis.ts +++ b/plugins/search/src/apis.ts @@ -30,12 +30,17 @@ export class SearchClient implements SearchApi { this.fetchApi = options.fetchApi; } - async query(query: SearchQuery): Promise { + async query( + query: SearchQuery, + options?: { signal?: AbortSignal }, + ): Promise { const queryString = qs.stringify(query); const url = `${await this.discoveryApi.getBaseUrl( 'search', )}/query?${queryString}`; - const response = await this.fetchApi.fetch(url); + const response = await this.fetchApi.fetch(url, { + signal: options?.signal, + }); if (!response.ok) { throw await ResponseError.fromResponse(response); diff --git a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx index 37b7c13665..e7c47b7d30 100644 --- a/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx +++ b/plugins/search/src/components/HomePageComponent/HomePageSearchBar.test.tsx @@ -48,6 +48,9 @@ describe('', () => { expect(searchApiMock.query).toHaveBeenCalledWith( expect.objectContaining({ term: '' }), + { + signal: expect.any(AbortSignal), + }, ); await userEvent.type(screen.getByLabelText('Search'), 'term{enter}'); diff --git a/plugins/search/src/components/SearchModal/SearchModal.test.tsx b/plugins/search/src/components/SearchModal/SearchModal.test.tsx index c404f54e06..8d8e1bb9b9 100644 --- a/plugins/search/src/components/SearchModal/SearchModal.test.tsx +++ b/plugins/search/src/components/SearchModal/SearchModal.test.tsx @@ -88,7 +88,9 @@ describe('SearchModal', () => { ); expect(screen.getByRole('dialog')).toBeInTheDocument(); - expect(searchApiMock.query).toHaveBeenCalledWith(initialState); + expect(searchApiMock.query).toHaveBeenCalledWith(initialState, { + signal: expect.any(AbortSignal), + }); }); it('Should create a local search context if a parent is not defined', async () => { @@ -104,12 +106,15 @@ describe('SearchModal', () => { ); expect(screen.getByRole('dialog')).toBeInTheDocument(); - expect(searchApiMock.query).toHaveBeenCalledWith({ - term: '', - filters: {}, - types: [], - pageCursor: undefined, - }); + expect(searchApiMock.query).toHaveBeenCalledWith( + { + term: '', + filters: {}, + types: [], + pageCursor: undefined, + }, + { signal: expect.any(AbortSignal) }, + ); }); it('Should render a custom Modal correctly', async () => { @@ -200,6 +205,7 @@ describe('SearchModal', () => { expect(searchApiMock.query).toHaveBeenCalledWith( expect.objectContaining({ term: 'term' }), + { signal: expect.any(AbortSignal) }, ); const input = screen.getByLabelText('Search'); @@ -232,6 +238,7 @@ describe('SearchModal', () => { expect(searchApiMock.query).toHaveBeenCalledWith( expect.objectContaining({ term: 'term' }), + { signal: expect.any(AbortSignal) }, ); const fullResultsBtn = screen.getByRole('button', { diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx index 1245ceed5a..a0dd2976e6 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.test.tsx @@ -157,18 +157,28 @@ describe('SearchType.Accordion', () => {
, ); - expect(searchApiMock.query).toHaveBeenCalledWith({ - term: 'abc', - types: [], - filters: { foo: 'bar' }, - pageLimit: 0, - }); - expect(searchApiMock.query).toHaveBeenCalledWith({ - term: 'abc', - types: [expectedType.value], - filters: {}, - pageLimit: 0, - }); + expect(searchApiMock.query).toHaveBeenCalledWith( + { + term: 'abc', + types: [], + filters: { foo: 'bar' }, + pageLimit: 0, + }, + { + signal: expect.any(AbortSignal), + }, + ); + expect(searchApiMock.query).toHaveBeenCalledWith( + { + term: 'abc', + types: [expectedType.value], + filters: {}, + pageLimit: 0, + }, + { + signal: expect.any(AbortSignal), + }, + ); await waitFor(() => { const countLabels = getAllByText('1234 results'); expect(countLabels.length).toEqual(2); diff --git a/plugins/search/src/components/SearchType/SearchType.Accordion.tsx b/plugins/search/src/components/SearchType/SearchType.Accordion.tsx index 65c96b1e60..8168418ed2 100644 --- a/plugins/search/src/components/SearchType/SearchType.Accordion.tsx +++ b/plugins/search/src/components/SearchType/SearchType.Accordion.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { cloneElement, Fragment, useEffect, useState } from 'react'; +import { cloneElement, Fragment, useEffect, useRef, useState } from 'react'; import { useApi } from '@backstage/core-plugin-api'; import { searchApiRef, useSearch } from '@backstage/plugin-search-react'; import Accordion from '@material-ui/core/Accordion'; @@ -86,6 +86,7 @@ export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { const [expanded, setExpanded] = useState(true); const { defaultValue, name, showCounts, types: givenTypes } = props; const { t } = useTranslationRef(searchTranslationRef); + const abortControllerRef = useRef(null); const toggleExpanded = () => setExpanded(prevState => !prevState); const handleClick = (type: string) => { @@ -117,18 +118,29 @@ export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { if (!showCounts) { return {}; } + // Here we cancel the previous requests before making a new one + // All requests are made with a new AbortController signal + if (abortControllerRef.current) { + abortControllerRef.current.abort(); + } + + const controller = new AbortController(); + abortControllerRef.current = controller; const counts = await Promise.all( definedTypes .map(type => type.value) .map(async type => { - const { numberOfResults } = await searchApi.query({ - term, - types: type ? [type] : [], - filters: - types.includes(type) || (!types.length && !type) ? filters : {}, - pageLimit: 0, - }); + const { numberOfResults } = await searchApi.query( + { + term, + types: type ? [type] : [], + filters: + types.includes(type) || (!types.length && !type) ? filters : {}, + pageLimit: 0, + }, + { signal: controller.signal }, + ); return [ type, @@ -145,6 +157,14 @@ export const SearchTypeAccordion = (props: SearchTypeAccordionProps) => { return Object.fromEntries(counts); }, [filters, showCounts, term, types]); + useEffect(() => { + return () => { + if (abortControllerRef.current) { + abortControllerRef.current.abort(); + } + }; + }, []); + return ( diff --git a/plugins/search/src/components/SearchType/SearchType.test.tsx b/plugins/search/src/components/SearchType/SearchType.test.tsx index 231463c9bf..e62ac19fee 100644 --- a/plugins/search/src/components/SearchType/SearchType.test.tsx +++ b/plugins/search/src/components/SearchType/SearchType.test.tsx @@ -192,6 +192,9 @@ describe('SearchType', () => { expect.objectContaining({ types: [values[0]], }), + { + signal: expect.any(AbortSignal), + }, ); }); @@ -240,6 +243,9 @@ describe('SearchType', () => { expect.objectContaining({ types: [...typeValues, values[0]], }), + { + signal: expect.any(AbortSignal), + }, ); }); @@ -253,7 +259,12 @@ describe('SearchType', () => { await waitFor(() => { expect(searchApiMock.query).toHaveBeenLastCalledWith( - expect.objectContaining([]), + expect.objectContaining({ + types: typeValues, + }), + { + signal: expect.any(AbortSignal), + }, ); }); }); From e02473eeb39d4c48b4bbada88a9c67a6cd726232 Mon Sep 17 00:00:00 2001 From: Sydney Achinger Date: Tue, 23 Sep 2025 16:15:43 -0400 Subject: [PATCH 035/244] Update test Signed-off-by: Sydney Achinger --- .../search/components/TechDocsSearch.test.tsx | 92 +++++++++++-------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/plugins/techdocs/src/search/components/TechDocsSearch.test.tsx b/plugins/techdocs/src/search/components/TechDocsSearch.test.tsx index f7e67e12cf..c140e830ad 100644 --- a/plugins/techdocs/src/search/components/TechDocsSearch.test.tsx +++ b/plugins/techdocs/src/search/components/TechDocsSearch.test.tsx @@ -84,16 +84,21 @@ it('should trigger query when autocomplete input changed', async () => { ); await singleResult; - expect(querySpy).toHaveBeenCalledWith({ - filters: { - kind: 'Testable', - name: 'test', - namespace: 'testspace', + expect(querySpy).toHaveBeenCalledWith( + { + filters: { + kind: 'Testable', + name: 'test', + namespace: 'testspace', + }, + pageCursor: '', + term: '', + types: ['techdocs'], }, - pageCursor: '', - term: '', - types: ['techdocs'], - }); + { + signal: expect.any(AbortSignal), + }, + ); const autocomplete = screen.getByTestId('techdocs-search-bar'); const input = within(autocomplete).getByRole('textbox'); @@ -105,16 +110,21 @@ it('should trigger query when autocomplete input changed', async () => { await singleResult; await waitFor(() => - expect(querySpy).toHaveBeenCalledWith({ - filters: { - kind: 'Testable', - name: 'test', - namespace: 'testspace', + expect(querySpy).toHaveBeenCalledWith( + { + filters: { + kind: 'Testable', + name: 'test', + namespace: 'testspace', + }, + pageCursor: '', + term: 'asdf', + types: ['techdocs'], }, - pageCursor: '', - term: 'asdf', - types: ['techdocs'], - }), + { + signal: expect.any(AbortSignal), + }, + ), ); }); @@ -144,16 +154,21 @@ it('should update filter values when a new entityName is provided', async () => await renderInTestApp(); await singleResult; - expect(querySpy).toHaveBeenCalledWith({ - filters: { - kind: 'Testable', - name: 'test', - namespace: 'testspace', + expect(querySpy).toHaveBeenCalledWith( + { + filters: { + kind: 'Testable', + name: 'test', + namespace: 'testspace', + }, + pageCursor: '', + term: '', + types: ['techdocs'], }, - pageCursor: '', - term: '', - types: ['techdocs'], - }); + { + signal: expect.any(AbortSignal), + }, + ); const button = screen.getByText('Update Entity'); act(() => { @@ -162,15 +177,20 @@ it('should update filter values when a new entityName is provided', async () => await singleResult; await waitFor(() => - expect(querySpy).toHaveBeenCalledWith({ - filters: { - kind: 'TestableDiff', - name: 'test-diff', - namespace: 'testspace-diff', + expect(querySpy).toHaveBeenCalledWith( + { + filters: { + kind: 'TestableDiff', + name: 'test-diff', + namespace: 'testspace-diff', + }, + pageCursor: '', + term: '', + types: ['techdocs'], }, - pageCursor: '', - term: '', - types: ['techdocs'], - }), + { + signal: expect.any(AbortSignal), + }, + ), ); }); From 482df90524e6c665d3e053dc07c9b67cfcdb4724 Mon Sep 17 00:00:00 2001 From: Sydney Achinger <78113809+squid-ney@users.noreply.github.com> Date: Tue, 23 Sep 2025 15:53:07 -0400 Subject: [PATCH 036/244] Update changeset Signed-off-by: Sydney Achinger <78113809+squid-ney@users.noreply.github.com> Signed-off-by: Sydney Achinger --- .changeset/ripe-yaks-brake.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/ripe-yaks-brake.md b/.changeset/ripe-yaks-brake.md index 953d0f3192..3b3097011b 100644 --- a/.changeset/ripe-yaks-brake.md +++ b/.changeset/ripe-yaks-brake.md @@ -3,4 +3,4 @@ '@backstage/plugin-search': patch --- -Implement AbortController request cancellation in SearchBar to prevent overlapping search requests. This change ensures that when users type quickly, previous search requests are properly canceled before new ones start. +Implemented AbortController request cancellation for overlapping search requests. This change ensures that when users type quickly, previous search requests are properly canceled before new ones start. From c9f3c47c7e15431e4f664dca77e24b7ba589d2a5 Mon Sep 17 00:00:00 2001 From: birdhb Date: Wed, 24 Sep 2025 16:40:39 +0100 Subject: [PATCH 037/244] Update eighty-cows-care.md Signed-off-by: birdhb --- .changeset/eighty-cows-care.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eighty-cows-care.md b/.changeset/eighty-cows-care.md index fc0a5c48bc..f3eed821ec 100644 --- a/.changeset/eighty-cows-care.md +++ b/.changeset/eighty-cows-care.md @@ -2,4 +2,4 @@ '@backstage/ui': patch --- -Added show/hide visibility and clear action icons to TextField +Added PasswordField to BUI with default show/hide visibilty on text input From b58a488eff432b5e8e275dd130551bc86cae4d74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 25 Sep 2025 10:20:05 +0200 Subject: [PATCH 038/244] fix(bui): fix button link internal routing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../src/components/ButtonLink/ButtonLink.tsx | 57 +++++++++++++++---- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/packages/ui/src/components/ButtonLink/ButtonLink.tsx b/packages/ui/src/components/ButtonLink/ButtonLink.tsx index 153643a530..b5b5ab208d 100644 --- a/packages/ui/src/components/ButtonLink/ButtonLink.tsx +++ b/packages/ui/src/components/ButtonLink/ButtonLink.tsx @@ -16,13 +16,16 @@ import clsx from 'clsx'; import { forwardRef, Ref } from 'react'; -import { Link as RALink } from 'react-aria-components'; +import { Link as RALink, RouterProvider } from 'react-aria-components'; +import { useNavigate, useHref } from 'react-router-dom'; import type { ButtonLinkProps } from './types'; import { useStyles } from '../../hooks/useStyles'; +import { isExternalLink } from '../../utils/isExternalLink'; /** @public */ export const ButtonLink = forwardRef( (props: ButtonLinkProps, ref: Ref) => { + const navigate = useNavigate(); const { size = 'small', variant = 'primary', @@ -30,6 +33,7 @@ export const ButtonLink = forwardRef( iconEnd, children, className, + href, ...rest } = props; @@ -40,17 +44,48 @@ export const ButtonLink = forwardRef( const { classNames: classNamesButtonLink } = useStyles('ButtonLink'); + const isExternal = isExternalLink(href); + + // If it's an external link, render RALink without RouterProvider + if (isExternal) { + return ( + + {iconStart} + {children} + {iconEnd} + + ); + } + + // For internal links, use RouterProvider return ( - - {iconStart} - {children} - {iconEnd} - + + + {iconStart} + {children} + {iconEnd} + + ); }, ); From d6db35b521c19bcb63025877d4d6659c6bee6ea9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 25 Sep 2025 11:51:53 +0200 Subject: [PATCH 039/244] fix(bui): add MemoryRouter to ButtonLink stories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../src/components/ButtonLink/ButtonLink.stories.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/components/ButtonLink/ButtonLink.stories.tsx b/packages/ui/src/components/ButtonLink/ButtonLink.stories.tsx index b4667f017b..f032af318c 100644 --- a/packages/ui/src/components/ButtonLink/ButtonLink.stories.tsx +++ b/packages/ui/src/components/ButtonLink/ButtonLink.stories.tsx @@ -14,15 +14,23 @@ * limitations under the License. */ -import type { Meta, StoryObj } from '@storybook/react-vite'; +import type { Meta, StoryFn, StoryObj } from '@storybook/react-vite'; import { ButtonLink } from './ButtonLink'; import { Flex } from '../Flex'; import { Text } from '../Text'; import { Icon } from '../Icon'; +import { MemoryRouter } from 'react-router-dom'; const meta = { title: 'Backstage UI/ButtonLink', component: ButtonLink, + decorators: [ + (Story: StoryFn) => ( + + + + ), + ], argTypes: { size: { control: 'select', From 25ada301cf61e9dd2ce3bdfa6cd36814d75341f3 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Wed, 24 Sep 2025 16:39:22 +0100 Subject: [PATCH 040/244] add PasswordField to BUI, remove additional props from TextField Signed-off-by: Hermione Bird --- packages/ui/css/styles.css | 8 + .../PasswordField/PasswordField.stories.tsx | 148 ++++++++++++++++++ .../PasswordField/PasswordField.styles.css | 141 +++++++++++++++++ .../PasswordField/PasswordField.tsx | 116 ++++++++++++++ .../ui/src/components/PasswordField/index.ts | 18 +++ .../ui/src/components/PasswordField/types.ts | 56 +++++++ .../components/TextField/TextField.styles.css | 23 --- .../ui/src/components/TextField/TextField.tsx | 23 +-- packages/ui/src/components/TextField/types.ts | 10 -- packages/ui/src/css/components.css | 1 + packages/ui/src/utils/componentDefinitions.ts | 13 ++ 11 files changed, 502 insertions(+), 55 deletions(-) create mode 100644 packages/ui/src/components/PasswordField/PasswordField.stories.tsx create mode 100644 packages/ui/src/components/PasswordField/PasswordField.styles.css create mode 100644 packages/ui/src/components/PasswordField/PasswordField.tsx create mode 100644 packages/ui/src/components/PasswordField/index.ts create mode 100644 packages/ui/src/components/PasswordField/types.ts diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index 1ea7d73bf7..2816ed7e8f 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -10431,6 +10431,14 @@ display: flex; } +.bui-PasswordField { + font-family: var(--bui-font-regular); + flex-direction: column; + flex-shrink: 0; + width: 100%; + display: flex; +} + .bui-InputWrapper { position: relative; diff --git a/packages/ui/src/components/PasswordField/PasswordField.stories.tsx b/packages/ui/src/components/PasswordField/PasswordField.stories.tsx new file mode 100644 index 0000000000..b89f891430 --- /dev/null +++ b/packages/ui/src/components/PasswordField/PasswordField.stories.tsx @@ -0,0 +1,148 @@ +/* + * 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-vite'; +import { PasswordField } from './PasswordField'; +import { Form } from 'react-aria-components'; +import { Icon } from '../Icon'; +import { Flex } from '../Flex'; +import { FieldLabel } from '../FieldLabel'; + +const meta = { + title: 'Backstage UI/PasswordField', + component: PasswordField, + argTypes: { + isRequired: { + control: 'boolean', + }, + icon: { + control: 'object', + }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + name: 'secret', + placeholder: 'Enter a secret', + 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, + }, + render: WithIcon.render, +}; + +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/ui/src/components/PasswordField/PasswordField.styles.css b/packages/ui/src/components/PasswordField/PasswordField.styles.css new file mode 100644 index 0000000000..e4d0d2f792 --- /dev/null +++ b/packages/ui/src/components/PasswordField/PasswordField.styles.css @@ -0,0 +1,141 @@ +/* + * 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. + */ + +.bui-PasswordField { + display: flex; + flex-direction: column; + font-family: var(--bui-font-regular); + width: 100%; + flex-shrink: 0; +} + +.bui-InputWrapper { + position: relative; + + &[data-size='small'] .bui-Input { + height: 2rem; + } + + &[data-size='medium'] .bui-Input { + height: 2.5rem; + } + + &[data-size='small'] .bui-Input[data-icon] { + padding-left: var(--bui-space-8); + } + + &[data-size='medium'] .bui-Input[data-icon] { + padding-left: var(--bui-space-9); + } +} + +.bui-InputIcon { + position: absolute; + left: var(--bui-space-3); + top: 50%; + transform: translateY(-50%); + margin-right: var(--bui-space-1); + color: var(--bui-fg-primary); + flex-shrink: 0; + pointer-events: none; + /* To animate the icon when the input is collapsed */ + transition: left 0.2s ease-in-out; + + &[data-size='small'], + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + &[data-size='medium'], + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } +} + +.bui-Input { + display: flex; + align-items: center; + padding: 0 var(--bui-space-3); + border-radius: var(--bui-radius-2); + border: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; + width: 100%; + height: 100%; + cursor: inherit; + + &::-webkit-search-cancel-button, + &::-webkit-search-decoration { + -webkit-appearance: none; + } + + &::placeholder { + color: var(--bui-fg-secondary); + } + + &[data-focused] { + outline-color: var(--bui-border-pressed); + outline-width: 0px; + } + + &[data-hovered] { + border-color: var(--bui-border-hover); + } + + &[data-focused] { + border-color: var(--bui-border-pressed); + outline-width: 0px; + } + + &[data-invalid] { + border-color: var(--bui-fg-danger); + } + + &[data-disabled] { + opacity: 0.5; + cursor: not-allowed; + border: 1px solid var(--bui-border-disabled); + } +} + +.bui-InputAction { + position: absolute; + right: var(--bui-space-1); + top: 50%; + transform: translateY(-50%); + color: var(--bui-fg-primary); + flex-shrink: 0; + /* To animate the icon when the input is collapsed */ + transition: right 0.2s ease-in-out; + + &[data-size='small'], + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + &[data-size='medium'], + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } +} diff --git a/packages/ui/src/components/PasswordField/PasswordField.tsx b/packages/ui/src/components/PasswordField/PasswordField.tsx new file mode 100644 index 0000000000..a43f30e41e --- /dev/null +++ b/packages/ui/src/components/PasswordField/PasswordField.tsx @@ -0,0 +1,116 @@ +/* + * 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, useState } from 'react'; +import { Input, TextField as AriaTextField } from 'react-aria-components'; +import clsx from 'clsx'; +import { FieldLabel } from '../FieldLabel'; +import { FieldError } from '../FieldError'; + +import type { PasswordFieldProps } from './types'; +import { useStyles } from '../../hooks/useStyles'; +import { Icon } from '../Icon'; +import { ButtonIcon } from '../ButtonIcon'; + +/** @public */ +export const PasswordField = forwardRef( + (props, ref) => { + const { + className, + icon, + size = 'small', + label, + secondaryLabel, + tertiaryLabel, + description, + isRequired, + tone, + message, + 'aria-label': ariaLabel, + 'aria-labelledby': ariaLabelledBy, + placeholder, + ...rest + } = props; + + useEffect(() => { + if (!label && !ariaLabel && !ariaLabelledBy) { + console.warn( + 'PasswordField requires either a visible label, aria-label, or aria-labelledby for accessibility', + ); + } + }, [label, ariaLabel, ariaLabelledBy]); + + const { classNames, dataAttributes } = useStyles('PasswordField', { + size, + }); + + // If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required. + const secondaryLabelText = + secondaryLabel || (isRequired ? 'Required' : null); + + // Manage secret visibility toggle + const [isVisible, setIsVisible] = useState(false); + + return ( + + +
+ {icon && ( + + )} +
+ setIsVisible(v => !v)} + icon={} + /> +
+ +
+ +
+ ); + }, +); + +PasswordField.displayName = 'PasswordField'; diff --git a/packages/ui/src/components/PasswordField/index.ts b/packages/ui/src/components/PasswordField/index.ts new file mode 100644 index 0000000000..df7874e1c2 --- /dev/null +++ b/packages/ui/src/components/PasswordField/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 './PasswordField'; +export * from './types'; diff --git a/packages/ui/src/components/PasswordField/types.ts b/packages/ui/src/components/PasswordField/types.ts new file mode 100644 index 0000000000..f1f5066955 --- /dev/null +++ b/packages/ui/src/components/PasswordField/types.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 type { TextFieldProps as AriaTextFieldProps } from 'react-aria-components'; +import { ReactNode } from 'react'; +import type { Breakpoint } from '../../types'; +import type { FieldLabelProps } from '../FieldLabel/types'; + +/** @public */ +export interface PasswordFieldProps + extends AriaTextFieldProps, + Omit { + /** + * An icon to render before the input + */ + icon?: ReactNode; + + /** + * The size of the password field + * @defaultValue 'medium' + */ + size?: 'small' | 'medium' | Partial>; + + /** + * Text to display in the input when it has no value + */ + placeholder?: string; + + /** + * A tertiary label to display on the right side of the field label + */ + tertiaryLabel?: string; + + /** + * The visual tone of the message below the field, if any + */ + tone?: 'positive' | 'critical' | 'neutral' | 'caution'; + + /** + * A message to display below the field, such as validation feedback + */ + message?: string; +} diff --git a/packages/ui/src/components/TextField/TextField.styles.css b/packages/ui/src/components/TextField/TextField.styles.css index c5765bf8ac..792d5d85c9 100644 --- a/packages/ui/src/components/TextField/TextField.styles.css +++ b/packages/ui/src/components/TextField/TextField.styles.css @@ -116,26 +116,3 @@ border: 1px solid var(--bui-border-disabled); } } - -.bui-InputAction { - position: absolute; - right: var(--bui-space-1); - top: 50%; - transform: translateY(-50%); - color: var(--bui-fg-primary); - flex-shrink: 0; - /* To animate the icon when the input is collapsed */ - transition: right 0.2s ease-in-out; - - &[data-size='small'], - &[data-size='small'] svg { - width: 1rem; - height: 1rem; - } - - &[data-size='medium'], - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; - } -} diff --git a/packages/ui/src/components/TextField/TextField.tsx b/packages/ui/src/components/TextField/TextField.tsx index c4fc81f029..2756c3c85f 100644 --- a/packages/ui/src/components/TextField/TextField.tsx +++ b/packages/ui/src/components/TextField/TextField.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { forwardRef, useEffect, useState } from 'react'; +import { forwardRef, useEffect } from 'react'; import { Input, TextField as AriaTextField } from 'react-aria-components'; import clsx from 'clsx'; import { FieldLabel } from '../FieldLabel'; @@ -22,8 +22,6 @@ import { FieldError } from '../FieldError'; import type { TextFieldProps } from './types'; import { useStyles } from '../../hooks/useStyles'; -import { Icon } from '../Icon'; -import { ButtonIcon } from '../ButtonIcon'; /** @public */ export const TextField = forwardRef( @@ -36,7 +34,6 @@ export const TextField = forwardRef( secondaryLabel, description, isRequired, - enableVisibility, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, placeholder, @@ -59,10 +56,6 @@ export const TextField = forwardRef( const secondaryLabelText = secondaryLabel || (isRequired ? 'Required' : null); - // Manage secret visibility toggle - const [isVisible, setIsVisible] = useState(false); - const showSecretToggle = Boolean(enableVisibility); - return ( ( {icon} )} - {showSecretToggle && ( -
- setIsVisible(v => !v)} - icon={} - /> -
- )} diff --git a/packages/ui/src/components/TextField/types.ts b/packages/ui/src/components/TextField/types.ts index d64be41050..75a5c68aaa 100644 --- a/packages/ui/src/components/TextField/types.ts +++ b/packages/ui/src/components/TextField/types.ts @@ -38,14 +38,4 @@ export interface TextFieldProps * Text to display in the input when it has no value */ placeholder?: string; - - /** - * Displays icon to toggle between showing and hiding the input value - */ - enableVisibility?: boolean; - - /** - * Displays a clear button when there is content in the input - */ - isClearable?: boolean; } diff --git a/packages/ui/src/css/components.css b/packages/ui/src/css/components.css index 8aa81a8217..97dec3603f 100644 --- a/packages/ui/src/css/components.css +++ b/packages/ui/src/css/components.css @@ -39,6 +39,7 @@ @import '../components/TagGroup/TagGroup.styles.css'; @import '../components/Text/styles.css'; @import '../components/TextField/TextField.styles.css'; +@import '../components/TextField/PasswordField.styles.css'; @import '../components/SearchField/SearchField.styles.css'; @import '../components/Skeleton/Skeleton.styles.css'; @import '../components/Tooltip/Tooltip.styles.css'; diff --git a/packages/ui/src/utils/componentDefinitions.ts b/packages/ui/src/utils/componentDefinitions.ts index bf01a0dc63..f67ee781dc 100644 --- a/packages/ui/src/utils/componentDefinitions.ts +++ b/packages/ui/src/utils/componentDefinitions.ts @@ -293,6 +293,19 @@ export const componentDefinitions = { disabled: [true, false] as const, }, }, + PasswordField: { + classNames: { + root: 'bui-PasswordField', + inputWrapper: 'bui-InputWrapper', + input: 'bui-Input', + inputIcon: 'bui-InputIcon', + inputAction: 'bui-InputAction', + }, + dataAttributes: { + invalid: [true, false] as const, + disabled: [true, false] as const, + }, + }, Tooltip: { classNames: { tooltip: 'bui-Tooltip', From bd68474c8014fe479aca081829e5f1dd4ba23241 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Thu, 25 Sep 2025 10:46:15 +0100 Subject: [PATCH 041/244] Deprecate types search and password from TextField Signed-off-by: Hermione Bird --- .../ui/src/components/TextField/TextField.tsx | 14 ++++++++++++++ packages/ui/src/components/TextField/types.ts | 16 ++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/packages/ui/src/components/TextField/TextField.tsx b/packages/ui/src/components/TextField/TextField.tsx index 2756c3c85f..f44295e247 100644 --- a/packages/ui/src/components/TextField/TextField.tsx +++ b/packages/ui/src/components/TextField/TextField.tsx @@ -48,6 +48,20 @@ export const TextField = forwardRef( } }, [label, ariaLabel, ariaLabelledBy]); + useEffect(() => { + const inputType = (props as { type?: string }).type; + if (inputType === 'search') { + console.warn( + 'TextField type="search" is deprecated. Use SearchField instead.', + ); + } + if (inputType === 'password') { + console.warn( + 'TextField type="password" is deprecated. Use PasswordField instead.', + ); + } + }, [props]); + const { classNames, dataAttributes } = useStyles('TextField', { size, }); diff --git a/packages/ui/src/components/TextField/types.ts b/packages/ui/src/components/TextField/types.ts index 75a5c68aaa..0c34634e2d 100644 --- a/packages/ui/src/components/TextField/types.ts +++ b/packages/ui/src/components/TextField/types.ts @@ -23,6 +23,22 @@ import type { FieldLabelProps } from '../FieldLabel/types'; export interface TextFieldProps extends AriaTextFieldProps, Omit { + /** + * The HTML input type for the text field + * + * @remarks + * The values 'search' and 'password' are deprecated. Use `SearchField` for + * search inputs and `PasswordField` for password inputs. + */ + type?: + | 'text' + | 'email' + | 'tel' + | 'url' + /** @deprecated Use `SearchField` instead */ + | 'search' + /** @deprecated Use `PasswordField` instead */ + | 'password'; /** * An icon to render before the input */ From ed5829bc30b8867e7aab4e2b8c3a0338d3ab7c22 Mon Sep 17 00:00:00 2001 From: birdhb Date: Thu, 25 Sep 2025 11:09:44 +0100 Subject: [PATCH 042/244] Update eighty-cows-care.md Signed-off-by: birdhb --- .changeset/eighty-cows-care.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eighty-cows-care.md b/.changeset/eighty-cows-care.md index f3eed821ec..8fd5c0adb0 100644 --- a/.changeset/eighty-cows-care.md +++ b/.changeset/eighty-cows-care.md @@ -2,4 +2,4 @@ '@backstage/ui': patch --- -Added PasswordField to BUI with default show/hide visibilty on text input +Added PasswordField to BUI with default show/hide visibility on text input From 6d67d79072a40e3baac569318ff0e024ba5a5621 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Thu, 25 Sep 2025 11:16:49 +0100 Subject: [PATCH 043/244] Fix stylesheet import Signed-off-by: Hermione Bird --- packages/ui/src/css/components.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/css/components.css b/packages/ui/src/css/components.css index 97dec3603f..9696425431 100644 --- a/packages/ui/src/css/components.css +++ b/packages/ui/src/css/components.css @@ -39,7 +39,7 @@ @import '../components/TagGroup/TagGroup.styles.css'; @import '../components/Text/styles.css'; @import '../components/TextField/TextField.styles.css'; -@import '../components/TextField/PasswordField.styles.css'; +@import '../components/PasswordField/PasswordField.styles.css'; @import '../components/SearchField/SearchField.styles.css'; @import '../components/Skeleton/Skeleton.styles.css'; @import '../components/Tooltip/Tooltip.styles.css'; From 7f436b46e1aa3c8c95e91d9fd84df0f7c431cf19 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Thu, 25 Sep 2025 11:22:00 +0100 Subject: [PATCH 044/244] remove unecessary props Signed-off-by: Hermione Bird --- .../components/PasswordField/PasswordField.tsx | 3 --- packages/ui/src/components/PasswordField/types.ts | 15 --------------- 2 files changed, 18 deletions(-) diff --git a/packages/ui/src/components/PasswordField/PasswordField.tsx b/packages/ui/src/components/PasswordField/PasswordField.tsx index a43f30e41e..46b907c010 100644 --- a/packages/ui/src/components/PasswordField/PasswordField.tsx +++ b/packages/ui/src/components/PasswordField/PasswordField.tsx @@ -34,11 +34,8 @@ export const PasswordField = forwardRef( size = 'small', label, secondaryLabel, - tertiaryLabel, description, isRequired, - tone, - message, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, placeholder, diff --git a/packages/ui/src/components/PasswordField/types.ts b/packages/ui/src/components/PasswordField/types.ts index f1f5066955..8af9a6134c 100644 --- a/packages/ui/src/components/PasswordField/types.ts +++ b/packages/ui/src/components/PasswordField/types.ts @@ -38,19 +38,4 @@ export interface PasswordFieldProps * Text to display in the input when it has no value */ placeholder?: string; - - /** - * A tertiary label to display on the right side of the field label - */ - tertiaryLabel?: string; - - /** - * The visual tone of the message below the field, if any - */ - tone?: 'positive' | 'critical' | 'neutral' | 'caution'; - - /** - * A message to display below the field, such as validation feedback - */ - message?: string; } From 1bb69243494d1ac4edbaf3e107a8e4861a7d184a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 25 Sep 2025 17:11:34 +0200 Subject: [PATCH 045/244] fix: remove default selection of tab for tabs that have href defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../ui/src/components/Tabs/Tabs.stories.tsx | 57 +++++++++++++++++++ packages/ui/src/components/Tabs/Tabs.tsx | 15 ++++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/components/Tabs/Tabs.stories.tsx b/packages/ui/src/components/Tabs/Tabs.stories.tsx index cbfe3d8562..c818d0fe4b 100644 --- a/packages/ui/src/components/Tabs/Tabs.stories.tsx +++ b/packages/ui/src/components/Tabs/Tabs.stories.tsx @@ -455,3 +455,60 @@ export const RootPathMatching: Story = { ), }; + +export const AutoSelectionOfTabs: Story = { + args: { + children: '', + }, + render: () => ( + +
+ + Current URL: /random-page + + + {/* Without hrefs */} + + {' '} + Case 1: Without hrefs + + + + Settings + Preferences + Advanced + + + Settings content - React Aria manages this selection + + + Preferences content - works normally + + + Advanced content - local state only + + + + {/* With hrefs */} + + {' '} + Case 2: With hrefs By default no selection is shown + because the URL doesn't match any tab's href.{' '} + + + + + Catalog + + + Create + + + Docs + + + +
+
+ ), +}; diff --git a/packages/ui/src/components/Tabs/Tabs.tsx b/packages/ui/src/components/Tabs/Tabs.tsx index dacb355fc9..371de4ef41 100644 --- a/packages/ui/src/components/Tabs/Tabs.tsx +++ b/packages/ui/src/components/Tabs/Tabs.tsx @@ -115,9 +115,22 @@ export const Tabs = (props: TabsProps) => { } } } + + //No route matches - check if all tabs have hrefs (pure navigation) + const allTabsHaveHref = tabListChildren.every( + child => isValidElement(child) && child.props.href, + ); + + if (allTabsHaveHref) { + // Pure navigation tabs, no route match + return null; + } else { + // Mixed tabs or pure local state + return undefined; + } } } - return null; + return undefined; })(); if (!children) return null; From 68412799e4ed1971677165d9a3c92a3e1285206b Mon Sep 17 00:00:00 2001 From: Marley Date: Fri, 26 Sep 2025 08:03:15 +0100 Subject: [PATCH 046/244] fix: JSON filter syntax in catalog-customization.md Removed unnecessary braces from JSON filter example. Signed-off-by: Marley --- docs/features/software-catalog/catalog-customization.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 1ef865039f..2ed4b34822 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -571,10 +571,8 @@ Finally, entity predicates also support value operators that can be used in plac ```json { "filter": { - { - "kind": "component", - "spec.type": { "$in": ["service", "website"] } - }, + "kind": "component", + "spec.type": { "$in": ["service", "website"] } } } ``` From b78dc1154cc7bf35197b2cf8645f213ffc049411 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Fri, 26 Sep 2025 11:42:09 +0100 Subject: [PATCH 047/244] add page to docs-ui, fix aria labels, compatibility with one password icons, create custom button Signed-off-by: Hermione Bird --- docs-ui/public/theme-backstage.css | 2 +- docs-ui/src/app/page.mdx | 5 + .../src/content/components/password-field.mdx | 64 ++++ .../components/password-field.props.ts | 43 +++ docs-ui/src/snippets/stories-snippets.tsx | 3 + docs-ui/src/utils/changelog.ts | 3 +- docs-ui/src/utils/data.ts | 5 + packages/ui/css/styles.css | 343 +++++++++++------- packages/ui/report.api.md | 12 + .../PasswordField/PasswordField.styles.css | 131 ++----- .../PasswordField/PasswordField.tsx | 43 ++- .../ui/src/components/TextField/TextField.tsx | 14 - packages/ui/src/components/TextField/types.ts | 12 +- packages/ui/src/utils/componentDefinitions.ts | 5 +- 14 files changed, 400 insertions(+), 285 deletions(-) create mode 100644 docs-ui/src/content/components/password-field.mdx create mode 100644 docs-ui/src/content/components/password-field.props.ts diff --git a/docs-ui/public/theme-backstage.css b/docs-ui/public/theme-backstage.css index 98b0f62b47..69cd0dbd31 100644 --- a/docs-ui/public/theme-backstage.css +++ b/docs-ui/public/theme-backstage.css @@ -1,2 +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}}.bui-p{padding:var(--p)}.bui-p-0\.5{padding:var(--bui-space-0_5)}.bui-p-1{padding:var(--bui-space-1)}.bui-p-1\.5{padding:var(--bui-space-1_5)}.bui-p-2{padding:var(--bui-space-2)}.bui-p-3{padding:var(--bui-space-3)}.bui-p-4{padding:var(--bui-space-4)}.bui-p-5{padding:var(--bui-space-5)}.bui-p-6{padding:var(--bui-space-6)}.bui-p-7{padding:var(--bui-space-7)}.bui-p-8{padding:var(--bui-space-8)}.bui-p-9{padding:var(--bui-space-9)}.bui-p-10{padding:var(--bui-space-10)}.bui-p-11{padding:var(--bui-space-11)}.bui-p-12{padding:var(--bui-space-12)}.bui-p-13{padding:var(--bui-space-13)}.bui-p-14{padding:var(--bui-space-14)}@media (width>=640px){.xs\:bui-p{padding:var(--p-xs)}.xs\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xs\:bui-p-1{padding:var(--bui-space-1)}.xs\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xs\:bui-p-2{padding:var(--bui-space-2)}.xs\:bui-p-3{padding:var(--bui-space-3)}.xs\:bui-p-4{padding:var(--bui-space-4)}.xs\:bui-p-5{padding:var(--bui-space-5)}.xs\:bui-p-6{padding:var(--bui-space-6)}.xs\:bui-p-7{padding:var(--bui-space-7)}.xs\:bui-p-8{padding:var(--bui-space-8)}.xs\:bui-p-9{padding:var(--bui-space-9)}.xs\:bui-p-10{padding:var(--bui-space-10)}.xs\:bui-p-11{padding:var(--bui-space-11)}.xs\:bui-p-12{padding:var(--bui-space-12)}.xs\:bui-p-13{padding:var(--bui-space-13)}.xs\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-p{padding:var(--p-sm)}.sm\:bui-p-0\.5{padding:var(--bui-space-0_5)}.sm\:bui-p-1{padding:var(--bui-space-1)}.sm\:bui-p-1\.5{padding:var(--bui-space-1_5)}.sm\:bui-p-2{padding:var(--bui-space-2)}.sm\:bui-p-3{padding:var(--bui-space-3)}.sm\:bui-p-4{padding:var(--bui-space-4)}.sm\:bui-p-5{padding:var(--bui-space-5)}.sm\:bui-p-6{padding:var(--bui-space-6)}.sm\:bui-p-7{padding:var(--bui-space-7)}.sm\:bui-p-8{padding:var(--bui-space-8)}.sm\:bui-p-9{padding:var(--bui-space-9)}.sm\:bui-p-10{padding:var(--bui-space-10)}.sm\:bui-p-11{padding:var(--bui-space-11)}.sm\:bui-p-12{padding:var(--bui-space-12)}.sm\:bui-p-13{padding:var(--bui-space-13)}.sm\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-p{padding:var(--p-md)}.md\:bui-p-0\.5{padding:var(--bui-space-0_5)}.md\:bui-p-1{padding:var(--bui-space-1)}.md\:bui-p-1\.5{padding:var(--bui-space-1_5)}.md\:bui-p-2{padding:var(--bui-space-2)}.md\:bui-p-3{padding:var(--bui-space-3)}.md\:bui-p-4{padding:var(--bui-space-4)}.md\:bui-p-5{padding:var(--bui-space-5)}.md\:bui-p-6{padding:var(--bui-space-6)}.md\:bui-p-7{padding:var(--bui-space-7)}.md\:bui-p-8{padding:var(--bui-space-8)}.md\:bui-p-9{padding:var(--bui-space-9)}.md\:bui-p-10{padding:var(--bui-space-10)}.md\:bui-p-11{padding:var(--bui-space-11)}.md\:bui-p-12{padding:var(--bui-space-12)}.md\:bui-p-13{padding:var(--bui-space-13)}.md\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-p{padding:var(--p-lg)}.lg\:bui-p-0\.5{padding:var(--bui-space-0_5)}.lg\:bui-p-1{padding:var(--bui-space-1)}.lg\:bui-p-1\.5{padding:var(--bui-space-1_5)}.lg\:bui-p-2{padding:var(--bui-space-2)}.lg\:bui-p-3{padding:var(--bui-space-3)}.lg\:bui-p-4{padding:var(--bui-space-4)}.lg\:bui-p-5{padding:var(--bui-space-5)}.lg\:bui-p-6{padding:var(--bui-space-6)}.lg\:bui-p-7{padding:var(--bui-space-7)}.lg\:bui-p-8{padding:var(--bui-space-8)}.lg\:bui-p-9{padding:var(--bui-space-9)}.lg\:bui-p-10{padding:var(--bui-space-10)}.lg\:bui-p-11{padding:var(--bui-space-11)}.lg\:bui-p-12{padding:var(--bui-space-12)}.lg\:bui-p-13{padding:var(--bui-space-13)}.lg\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-p{padding:var(--p-xl)}.xl\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xl\:bui-p-1{padding:var(--bui-space-1)}.xl\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xl\:bui-p-2{padding:var(--bui-space-2)}.xl\:bui-p-3{padding:var(--bui-space-3)}.xl\:bui-p-4{padding:var(--bui-space-4)}.xl\:bui-p-5{padding:var(--bui-space-5)}.xl\:bui-p-6{padding:var(--bui-space-6)}.xl\:bui-p-7{padding:var(--bui-space-7)}.xl\:bui-p-8{padding:var(--bui-space-8)}.xl\:bui-p-9{padding:var(--bui-space-9)}.xl\:bui-p-10{padding:var(--bui-space-10)}.xl\:bui-p-11{padding:var(--bui-space-11)}.xl\:bui-p-12{padding:var(--bui-space-12)}.xl\:bui-p-13{padding:var(--bui-space-13)}.xl\:bui-p-14{padding:var(--bui-space-14)}}.bui-pl{padding-left:var(--pl)}.bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.bui-pl-1{padding-left:var(--bui-space-1)}.bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.bui-pl-2{padding-left:var(--bui-space-2)}.bui-pl-3{padding-left:var(--bui-space-3)}.bui-pl-4{padding-left:var(--bui-space-4)}.bui-pl-5{padding-left:var(--bui-space-5)}.bui-pl-6{padding-left:var(--bui-space-6)}.bui-pl-7{padding-left:var(--bui-space-7)}.bui-pl-8{padding-left:var(--bui-space-8)}.bui-pl-9{padding-left:var(--bui-space-9)}.bui-pl-10{padding-left:var(--bui-space-10)}.bui-pl-11{padding-left:var(--bui-space-11)}.bui-pl-12{padding-left:var(--bui-space-12)}.bui-pl-13{padding-left:var(--bui-space-13)}.bui-pl-14{padding-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pl{padding-left:var(--pl-xs)}.xs\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xs\:bui-pl-1{padding-left:var(--bui-space-1)}.xs\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xs\:bui-pl-2{padding-left:var(--bui-space-2)}.xs\:bui-pl-3{padding-left:var(--bui-space-3)}.xs\:bui-pl-4{padding-left:var(--bui-space-4)}.xs\:bui-pl-5{padding-left:var(--bui-space-5)}.xs\:bui-pl-6{padding-left:var(--bui-space-6)}.xs\:bui-pl-7{padding-left:var(--bui-space-7)}.xs\:bui-pl-8{padding-left:var(--bui-space-8)}.xs\:bui-pl-9{padding-left:var(--bui-space-9)}.xs\:bui-pl-10{padding-left:var(--bui-space-10)}.xs\:bui-pl-11{padding-left:var(--bui-space-11)}.xs\:bui-pl-12{padding-left:var(--bui-space-12)}.xs\:bui-pl-13{padding-left:var(--bui-space-13)}.xs\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pl{padding-left:var(--pl-sm)}.sm\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.sm\:bui-pl-1{padding-left:var(--bui-space-1)}.sm\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.sm\:bui-pl-2{padding-left:var(--bui-space-2)}.sm\:bui-pl-3{padding-left:var(--bui-space-3)}.sm\:bui-pl-4{padding-left:var(--bui-space-4)}.sm\:bui-pl-5{padding-left:var(--bui-space-5)}.sm\:bui-pl-6{padding-left:var(--bui-space-6)}.sm\:bui-pl-7{padding-left:var(--bui-space-7)}.sm\:bui-pl-8{padding-left:var(--bui-space-8)}.sm\:bui-pl-9{padding-left:var(--bui-space-9)}.sm\:bui-pl-10{padding-left:var(--bui-space-10)}.sm\:bui-pl-11{padding-left:var(--bui-space-11)}.sm\:bui-pl-12{padding-left:var(--bui-space-12)}.sm\:bui-pl-13{padding-left:var(--bui-space-13)}.sm\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pl{padding-left:var(--pl-md)}.md\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.md\:bui-pl-1{padding-left:var(--bui-space-1)}.md\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.md\:bui-pl-2{padding-left:var(--bui-space-2)}.md\:bui-pl-3{padding-left:var(--bui-space-3)}.md\:bui-pl-4{padding-left:var(--bui-space-4)}.md\:bui-pl-5{padding-left:var(--bui-space-5)}.md\:bui-pl-6{padding-left:var(--bui-space-6)}.md\:bui-pl-7{padding-left:var(--bui-space-7)}.md\:bui-pl-8{padding-left:var(--bui-space-8)}.md\:bui-pl-9{padding-left:var(--bui-space-9)}.md\:bui-pl-10{padding-left:var(--bui-space-10)}.md\:bui-pl-11{padding-left:var(--bui-space-11)}.md\:bui-pl-12{padding-left:var(--bui-space-12)}.md\:bui-pl-13{padding-left:var(--bui-space-13)}.md\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pl{padding-left:var(--pl-lg)}.lg\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.lg\:bui-pl-1{padding-left:var(--bui-space-1)}.lg\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.lg\:bui-pl-2{padding-left:var(--bui-space-2)}.lg\:bui-pl-3{padding-left:var(--bui-space-3)}.lg\:bui-pl-4{padding-left:var(--bui-space-4)}.lg\:bui-pl-5{padding-left:var(--bui-space-5)}.lg\:bui-pl-6{padding-left:var(--bui-space-6)}.lg\:bui-pl-7{padding-left:var(--bui-space-7)}.lg\:bui-pl-8{padding-left:var(--bui-space-8)}.lg\:bui-pl-9{padding-left:var(--bui-space-9)}.lg\:bui-pl-10{padding-left:var(--bui-space-10)}.lg\:bui-pl-11{padding-left:var(--bui-space-11)}.lg\:bui-pl-12{padding-left:var(--bui-space-12)}.lg\:bui-pl-13{padding-left:var(--bui-space-13)}.lg\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pl{padding-left:var(--pl-xl)}.xl\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xl\:bui-pl-1{padding-left:var(--bui-space-1)}.xl\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xl\:bui-pl-2{padding-left:var(--bui-space-2)}.xl\:bui-pl-3{padding-left:var(--bui-space-3)}.xl\:bui-pl-4{padding-left:var(--bui-space-4)}.xl\:bui-pl-5{padding-left:var(--bui-space-5)}.xl\:bui-pl-6{padding-left:var(--bui-space-6)}.xl\:bui-pl-7{padding-left:var(--bui-space-7)}.xl\:bui-pl-8{padding-left:var(--bui-space-8)}.xl\:bui-pl-9{padding-left:var(--bui-space-9)}.xl\:bui-pl-10{padding-left:var(--bui-space-10)}.xl\:bui-pl-11{padding-left:var(--bui-space-11)}.xl\:bui-pl-12{padding-left:var(--bui-space-12)}.xl\:bui-pl-13{padding-left:var(--bui-space-13)}.xl\:bui-pl-14{padding-left:var(--bui-space-14)}}.bui-pr{padding-right:var(--pr)}.bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.bui-pr-1{padding-right:var(--bui-space-1)}.bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.bui-pr-2{padding-right:var(--bui-space-2)}.bui-pr-3{padding-right:var(--bui-space-3)}.bui-pr-4{padding-right:var(--bui-space-4)}.bui-pr-5{padding-right:var(--bui-space-5)}.bui-pr-6{padding-right:var(--bui-space-6)}.bui-pr-7{padding-right:var(--bui-space-7)}.bui-pr-8{padding-right:var(--bui-space-8)}.bui-pr-9{padding-right:var(--bui-space-9)}.bui-pr-10{padding-right:var(--bui-space-10)}.bui-pr-11{padding-right:var(--bui-space-11)}.bui-pr-12{padding-right:var(--bui-space-12)}.bui-pr-13{padding-right:var(--bui-space-13)}.bui-pr-14{padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pr{padding-right:var(--pr-xs)}.xs\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xs\:bui-pr-1{padding-right:var(--bui-space-1)}.xs\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xs\:bui-pr-2{padding-right:var(--bui-space-2)}.xs\:bui-pr-3{padding-right:var(--bui-space-3)}.xs\:bui-pr-4{padding-right:var(--bui-space-4)}.xs\:bui-pr-5{padding-right:var(--bui-space-5)}.xs\:bui-pr-6{padding-right:var(--bui-space-6)}.xs\:bui-pr-7{padding-right:var(--bui-space-7)}.xs\:bui-pr-8{padding-right:var(--bui-space-8)}.xs\:bui-pr-9{padding-right:var(--bui-space-9)}.xs\:bui-pr-10{padding-right:var(--bui-space-10)}.xs\:bui-pr-11{padding-right:var(--bui-space-11)}.xs\:bui-pr-12{padding-right:var(--bui-space-12)}.xs\:bui-pr-13{padding-right:var(--bui-space-13)}.xs\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pr{padding-right:var(--pr-sm)}.sm\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.sm\:bui-pr-1{padding-right:var(--bui-space-1)}.sm\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.sm\:bui-pr-2{padding-right:var(--bui-space-2)}.sm\:bui-pr-3{padding-right:var(--bui-space-3)}.sm\:bui-pr-4{padding-right:var(--bui-space-4)}.sm\:bui-pr-5{padding-right:var(--bui-space-5)}.sm\:bui-pr-6{padding-right:var(--bui-space-6)}.sm\:bui-pr-7{padding-right:var(--bui-space-7)}.sm\:bui-pr-8{padding-right:var(--bui-space-8)}.sm\:bui-pr-9{padding-right:var(--bui-space-9)}.sm\:bui-pr-10{padding-right:var(--bui-space-10)}.sm\:bui-pr-11{padding-right:var(--bui-space-11)}.sm\:bui-pr-12{padding-right:var(--bui-space-12)}.sm\:bui-pr-13{padding-right:var(--bui-space-13)}.sm\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pr{padding-right:var(--pr-md)}.md\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.md\:bui-pr-1{padding-right:var(--bui-space-1)}.md\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.md\:bui-pr-2{padding-right:var(--bui-space-2)}.md\:bui-pr-3{padding-right:var(--bui-space-3)}.md\:bui-pr-4{padding-right:var(--bui-space-4)}.md\:bui-pr-5{padding-right:var(--bui-space-5)}.md\:bui-pr-6{padding-right:var(--bui-space-6)}.md\:bui-pr-7{padding-right:var(--bui-space-7)}.md\:bui-pr-8{padding-right:var(--bui-space-8)}.md\:bui-pr-9{padding-right:var(--bui-space-9)}.md\:bui-pr-10{padding-right:var(--bui-space-10)}.md\:bui-pr-11{padding-right:var(--bui-space-11)}.md\:bui-pr-12{padding-right:var(--bui-space-12)}.md\:bui-pr-13{padding-right:var(--bui-space-13)}.md\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pr{padding-right:var(--pr-lg)}.lg\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.lg\:bui-pr-1{padding-right:var(--bui-space-1)}.lg\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.lg\:bui-pr-2{padding-right:var(--bui-space-2)}.lg\:bui-pr-3{padding-right:var(--bui-space-3)}.lg\:bui-pr-4{padding-right:var(--bui-space-4)}.lg\:bui-pr-5{padding-right:var(--bui-space-5)}.lg\:bui-pr-6{padding-right:var(--bui-space-6)}.lg\:bui-pr-7{padding-right:var(--bui-space-7)}.lg\:bui-pr-8{padding-right:var(--bui-space-8)}.lg\:bui-pr-9{padding-right:var(--bui-space-9)}.lg\:bui-pr-10{padding-right:var(--bui-space-10)}.lg\:bui-pr-11{padding-right:var(--bui-space-11)}.lg\:bui-pr-12{padding-right:var(--bui-space-12)}.lg\:bui-pr-13{padding-right:var(--bui-space-13)}.lg\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pr{padding-right:var(--pr-xl)}.xl\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xl\:bui-pr-1{padding-right:var(--bui-space-1)}.xl\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xl\:bui-pr-2{padding-right:var(--bui-space-2)}.xl\:bui-pr-3{padding-right:var(--bui-space-3)}.xl\:bui-pr-4{padding-right:var(--bui-space-4)}.xl\:bui-pr-5{padding-right:var(--bui-space-5)}.xl\:bui-pr-6{padding-right:var(--bui-space-6)}.xl\:bui-pr-7{padding-right:var(--bui-space-7)}.xl\:bui-pr-8{padding-right:var(--bui-space-8)}.xl\:bui-pr-9{padding-right:var(--bui-space-9)}.xl\:bui-pr-10{padding-right:var(--bui-space-10)}.xl\:bui-pr-11{padding-right:var(--bui-space-11)}.xl\:bui-pr-12{padding-right:var(--bui-space-12)}.xl\:bui-pr-13{padding-right:var(--bui-space-13)}.xl\:bui-pr-14{padding-right:var(--bui-space-14)}}.bui-pt{padding-top:var(--pt)}.bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.bui-pt-1{padding-top:var(--bui-space-1)}.bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.bui-pt-2{padding-top:var(--bui-space-2)}.bui-pt-3{padding-top:var(--bui-space-3)}.bui-pt-4{padding-top:var(--bui-space-4)}.bui-pt-5{padding-top:var(--bui-space-5)}.bui-pt-6{padding-top:var(--bui-space-6)}.bui-pt-7{padding-top:var(--bui-space-7)}.bui-pt-8{padding-top:var(--bui-space-8)}.bui-pt-9{padding-top:var(--bui-space-9)}.bui-pt-10{padding-top:var(--bui-space-10)}.bui-pt-11{padding-top:var(--bui-space-11)}.bui-pt-12{padding-top:var(--bui-space-12)}.bui-pt-13{padding-top:var(--bui-space-13)}.bui-pt-14{padding-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pt{padding-top:var(--pt-xs)}.xs\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xs\:bui-pt-1{padding-top:var(--bui-space-1)}.xs\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xs\:bui-pt-2{padding-top:var(--bui-space-2)}.xs\:bui-pt-3{padding-top:var(--bui-space-3)}.xs\:bui-pt-4{padding-top:var(--bui-space-4)}.xs\:bui-pt-5{padding-top:var(--bui-space-5)}.xs\:bui-pt-6{padding-top:var(--bui-space-6)}.xs\:bui-pt-7{padding-top:var(--bui-space-7)}.xs\:bui-pt-8{padding-top:var(--bui-space-8)}.xs\:bui-pt-9{padding-top:var(--bui-space-9)}.xs\:bui-pt-10{padding-top:var(--bui-space-10)}.xs\:bui-pt-11{padding-top:var(--bui-space-11)}.xs\:bui-pt-12{padding-top:var(--bui-space-12)}.xs\:bui-pt-13{padding-top:var(--bui-space-13)}.xs\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pt{padding-top:var(--pt-sm)}.sm\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.sm\:bui-pt-1{padding-top:var(--bui-space-1)}.sm\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.sm\:bui-pt-2{padding-top:var(--bui-space-2)}.sm\:bui-pt-3{padding-top:var(--bui-space-3)}.sm\:bui-pt-4{padding-top:var(--bui-space-4)}.sm\:bui-pt-5{padding-top:var(--bui-space-5)}.sm\:bui-pt-6{padding-top:var(--bui-space-6)}.sm\:bui-pt-7{padding-top:var(--bui-space-7)}.sm\:bui-pt-8{padding-top:var(--bui-space-8)}.sm\:bui-pt-9{padding-top:var(--bui-space-9)}.sm\:bui-pt-10{padding-top:var(--bui-space-10)}.sm\:bui-pt-11{padding-top:var(--bui-space-11)}.sm\:bui-pt-12{padding-top:var(--bui-space-12)}.sm\:bui-pt-13{padding-top:var(--bui-space-13)}.sm\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pt{padding-top:var(--pt-md)}.md\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.md\:bui-pt-1{padding-top:var(--bui-space-1)}.md\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.md\:bui-pt-2{padding-top:var(--bui-space-2)}.md\:bui-pt-3{padding-top:var(--bui-space-3)}.md\:bui-pt-4{padding-top:var(--bui-space-4)}.md\:bui-pt-5{padding-top:var(--bui-space-5)}.md\:bui-pt-6{padding-top:var(--bui-space-6)}.md\:bui-pt-7{padding-top:var(--bui-space-7)}.md\:bui-pt-8{padding-top:var(--bui-space-8)}.md\:bui-pt-9{padding-top:var(--bui-space-9)}.md\:bui-pt-10{padding-top:var(--bui-space-10)}.md\:bui-pt-11{padding-top:var(--bui-space-11)}.md\:bui-pt-12{padding-top:var(--bui-space-12)}.md\:bui-pt-13{padding-top:var(--bui-space-13)}.md\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pt{padding-top:var(--pt-lg)}.lg\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.lg\:bui-pt-1{padding-top:var(--bui-space-1)}.lg\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.lg\:bui-pt-2{padding-top:var(--bui-space-2)}.lg\:bui-pt-3{padding-top:var(--bui-space-3)}.lg\:bui-pt-4{padding-top:var(--bui-space-4)}.lg\:bui-pt-5{padding-top:var(--bui-space-5)}.lg\:bui-pt-6{padding-top:var(--bui-space-6)}.lg\:bui-pt-7{padding-top:var(--bui-space-7)}.lg\:bui-pt-8{padding-top:var(--bui-space-8)}.lg\:bui-pt-9{padding-top:var(--bui-space-9)}.lg\:bui-pt-10{padding-top:var(--bui-space-10)}.lg\:bui-pt-11{padding-top:var(--bui-space-11)}.lg\:bui-pt-12{padding-top:var(--bui-space-12)}.lg\:bui-pt-13{padding-top:var(--bui-space-13)}.lg\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pt{padding-top:var(--pt-xl)}.xl\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xl\:bui-pt-1{padding-top:var(--bui-space-1)}.xl\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xl\:bui-pt-2{padding-top:var(--bui-space-2)}.xl\:bui-pt-3{padding-top:var(--bui-space-3)}.xl\:bui-pt-4{padding-top:var(--bui-space-4)}.xl\:bui-pt-5{padding-top:var(--bui-space-5)}.xl\:bui-pt-6{padding-top:var(--bui-space-6)}.xl\:bui-pt-7{padding-top:var(--bui-space-7)}.xl\:bui-pt-8{padding-top:var(--bui-space-8)}.xl\:bui-pt-9{padding-top:var(--bui-space-9)}.xl\:bui-pt-10{padding-top:var(--bui-space-10)}.xl\:bui-pt-11{padding-top:var(--bui-space-11)}.xl\:bui-pt-12{padding-top:var(--bui-space-12)}.xl\:bui-pt-13{padding-top:var(--bui-space-13)}.xl\:bui-pt-14{padding-top:var(--bui-space-14)}}.bui-pb{padding-bottom:var(--pb)}.bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.bui-pb-1{padding-bottom:var(--bui-space-1)}.bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.bui-pb-2{padding-bottom:var(--bui-space-2)}.bui-pb-3{padding-bottom:var(--bui-space-3)}.bui-pb-4{padding-bottom:var(--bui-space-4)}.bui-pb-5{padding-bottom:var(--bui-space-5)}.bui-pb-6{padding-bottom:var(--bui-space-6)}.bui-pb-7{padding-bottom:var(--bui-space-7)}.bui-pb-8{padding-bottom:var(--bui-space-8)}.bui-pb-9{padding-bottom:var(--bui-space-9)}.bui-pb-10{padding-bottom:var(--bui-space-10)}.bui-pb-11{padding-bottom:var(--bui-space-11)}.bui-pb-12{padding-bottom:var(--bui-space-12)}.bui-pb-13{padding-bottom:var(--bui-space-13)}.bui-pb-14{padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pb{padding-bottom:var(--pb-xs)}.xs\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xs\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xs\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xs\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xs\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xs\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xs\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xs\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xs\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xs\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xs\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xs\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xs\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xs\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xs\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xs\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pb{padding-bottom:var(--pb-sm)}.sm\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.sm\:bui-pb-1{padding-bottom:var(--bui-space-1)}.sm\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.sm\:bui-pb-2{padding-bottom:var(--bui-space-2)}.sm\:bui-pb-3{padding-bottom:var(--bui-space-3)}.sm\:bui-pb-4{padding-bottom:var(--bui-space-4)}.sm\:bui-pb-5{padding-bottom:var(--bui-space-5)}.sm\:bui-pb-6{padding-bottom:var(--bui-space-6)}.sm\:bui-pb-7{padding-bottom:var(--bui-space-7)}.sm\:bui-pb-8{padding-bottom:var(--bui-space-8)}.sm\:bui-pb-9{padding-bottom:var(--bui-space-9)}.sm\:bui-pb-10{padding-bottom:var(--bui-space-10)}.sm\:bui-pb-11{padding-bottom:var(--bui-space-11)}.sm\:bui-pb-12{padding-bottom:var(--bui-space-12)}.sm\:bui-pb-13{padding-bottom:var(--bui-space-13)}.sm\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pb{padding-bottom:var(--pb-md)}.md\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.md\:bui-pb-1{padding-bottom:var(--bui-space-1)}.md\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.md\:bui-pb-2{padding-bottom:var(--bui-space-2)}.md\:bui-pb-3{padding-bottom:var(--bui-space-3)}.md\:bui-pb-4{padding-bottom:var(--bui-space-4)}.md\:bui-pb-5{padding-bottom:var(--bui-space-5)}.md\:bui-pb-6{padding-bottom:var(--bui-space-6)}.md\:bui-pb-7{padding-bottom:var(--bui-space-7)}.md\:bui-pb-8{padding-bottom:var(--bui-space-8)}.md\:bui-pb-9{padding-bottom:var(--bui-space-9)}.md\:bui-pb-10{padding-bottom:var(--bui-space-10)}.md\:bui-pb-11{padding-bottom:var(--bui-space-11)}.md\:bui-pb-12{padding-bottom:var(--bui-space-12)}.md\:bui-pb-13{padding-bottom:var(--bui-space-13)}.md\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pb{padding-bottom:var(--pb-lg)}.lg\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.lg\:bui-pb-1{padding-bottom:var(--bui-space-1)}.lg\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.lg\:bui-pb-2{padding-bottom:var(--bui-space-2)}.lg\:bui-pb-3{padding-bottom:var(--bui-space-3)}.lg\:bui-pb-4{padding-bottom:var(--bui-space-4)}.lg\:bui-pb-5{padding-bottom:var(--bui-space-5)}.lg\:bui-pb-6{padding-bottom:var(--bui-space-6)}.lg\:bui-pb-7{padding-bottom:var(--bui-space-7)}.lg\:bui-pb-8{padding-bottom:var(--bui-space-8)}.lg\:bui-pb-9{padding-bottom:var(--bui-space-9)}.lg\:bui-pb-10{padding-bottom:var(--bui-space-10)}.lg\:bui-pb-11{padding-bottom:var(--bui-space-11)}.lg\:bui-pb-12{padding-bottom:var(--bui-space-12)}.lg\:bui-pb-13{padding-bottom:var(--bui-space-13)}.lg\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pb{padding-bottom:var(--pb-xl)}.xl\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xl\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xl\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xl\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xl\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xl\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xl\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xl\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xl\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xl\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xl\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xl\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xl\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xl\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xl\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xl\:bui-pb-14{padding-bottom:var(--bui-space-14)}}.bui-py{padding-top:var(--py);padding-bottom:var(--py)}.bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-py{padding-top:var(--py-xs);padding-bottom:var(--py-xs)}.xs\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xs\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xs\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xs\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xs\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xs\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xs\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xs\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xs\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xs\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xs\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xs\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xs\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xs\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xs\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xs\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-py{padding-top:var(--py-sm);padding-bottom:var(--py-sm)}.sm\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.sm\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.sm\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.sm\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.sm\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.sm\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.sm\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.sm\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.sm\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.sm\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.sm\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.sm\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.sm\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.sm\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.sm\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.sm\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-py{padding-top:var(--py-md);padding-bottom:var(--py-md)}.md\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.md\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.md\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.md\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.md\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.md\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.md\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.md\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.md\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.md\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.md\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.md\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.md\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.md\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.md\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.md\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-py{padding-top:var(--py-lg);padding-bottom:var(--py-lg)}.lg\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.lg\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.lg\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.lg\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.lg\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.lg\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.lg\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.lg\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.lg\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.lg\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.lg\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.lg\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.lg\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.lg\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.lg\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.lg\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-py{padding-top:var(--py-xl);padding-bottom:var(--py-xl)}.xl\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xl\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xl\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xl\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xl\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xl\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xl\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xl\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xl\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xl\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xl\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xl\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xl\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xl\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xl\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xl\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}.bui-px{padding-left:var(--px);padding-right:var(--px)}.bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-px{padding-left:var(--px-xs);padding-right:var(--px-xs)}.xs\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xs\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xs\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xs\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xs\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xs\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xs\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xs\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xs\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xs\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xs\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xs\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xs\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xs\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xs\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xs\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-px{padding-left:var(--px-sm);padding-right:var(--px-sm)}.sm\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.sm\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.sm\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.sm\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.sm\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.sm\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.sm\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.sm\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.sm\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.sm\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.sm\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.sm\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.sm\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.sm\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.sm\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.sm\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-px{padding-left:var(--px-md);padding-right:var(--px-md)}.md\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.md\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.md\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.md\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.md\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.md\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.md\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.md\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.md\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.md\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.md\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.md\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.md\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.md\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.md\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.md\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-px{padding-left:var(--px-lg);padding-right:var(--px-lg)}.lg\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.lg\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.lg\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.lg\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.lg\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.lg\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.lg\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.lg\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.lg\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.lg\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.lg\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.lg\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.lg\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.lg\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.lg\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.lg\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-px{padding-left:var(--px-xl);padding-right:var(--px-xl)}.xl\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xl\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xl\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xl\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xl\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xl\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xl\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xl\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xl\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xl\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xl\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xl\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xl\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xl\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xl\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xl\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}.bui-m{margin:var(--m)}.bui-m-0\.5{margin:var(--bui-space-0_5)}.bui-m-1{margin:var(--bui-space-1)}.bui-m-1\.5{margin:var(--bui-space-1_5)}.bui-m-2{margin:var(--bui-space-2)}.bui-m-3{margin:var(--bui-space-3)}.bui-m-4{margin:var(--bui-space-4)}.bui-m-5{margin:var(--bui-space-5)}.bui-m-6{margin:var(--bui-space-6)}.bui-m-7{margin:var(--bui-space-7)}.bui-m-8{margin:var(--bui-space-8)}.bui-m-9{margin:var(--bui-space-9)}.bui-m-10{margin:var(--bui-space-10)}.bui-m-11{margin:var(--bui-space-11)}.bui-m-12{margin:var(--bui-space-12)}.bui-m-13{margin:var(--bui-space-13)}.bui-m-14{margin:var(--bui-space-14)}@media (width>=640px){.xs\:bui-m{margin:var(--p-xs)}.xs\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xs\:bui-m-1{margin:var(--bui-space-1)}.xs\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xs\:bui-m-2{margin:var(--bui-space-2)}.xs\:bui-m-3{margin:var(--bui-space-3)}.xs\:bui-m-4{margin:var(--bui-space-4)}.xs\:bui-m-5{margin:var(--bui-space-5)}.xs\:bui-m-6{margin:var(--bui-space-6)}.xs\:bui-m-7{margin:var(--bui-space-7)}.xs\:bui-m-8{margin:var(--bui-space-8)}.xs\:bui-m-9{margin:var(--bui-space-9)}.xs\:bui-m-10{margin:var(--bui-space-10)}.xs\:bui-m-11{margin:var(--bui-space-11)}.xs\:bui-m-12{margin:var(--bui-space-12)}.xs\:bui-m-13{margin:var(--bui-space-13)}.xs\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-m{margin:var(--p-sm)}.sm\:bui-m-0\.5{margin:var(--bui-space-0_5)}.sm\:bui-m-1{margin:var(--bui-space-1)}.sm\:bui-m-1\.5{margin:var(--bui-space-1_5)}.sm\:bui-m-2{margin:var(--bui-space-2)}.sm\:bui-m-3{margin:var(--bui-space-3)}.sm\:bui-m-4{margin:var(--bui-space-4)}.sm\:bui-m-5{margin:var(--bui-space-5)}.sm\:bui-m-6{margin:var(--bui-space-6)}.sm\:bui-m-7{margin:var(--bui-space-7)}.sm\:bui-m-8{margin:var(--bui-space-8)}.sm\:bui-m-9{margin:var(--bui-space-9)}.sm\:bui-m-10{margin:var(--bui-space-10)}.sm\:bui-m-11{margin:var(--bui-space-11)}.sm\:bui-m-12{margin:var(--bui-space-12)}.sm\:bui-m-13{margin:var(--bui-space-13)}.sm\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-m{margin:var(--p-md)}.md\:bui-m-0\.5{margin:var(--bui-space-0_5)}.md\:bui-m-1{margin:var(--bui-space-1)}.md\:bui-m-1\.5{margin:var(--bui-space-1_5)}.md\:bui-m-2{margin:var(--bui-space-2)}.md\:bui-m-3{margin:var(--bui-space-3)}.md\:bui-m-4{margin:var(--bui-space-4)}.md\:bui-m-5{margin:var(--bui-space-5)}.md\:bui-m-6{margin:var(--bui-space-6)}.md\:bui-m-7{margin:var(--bui-space-7)}.md\:bui-m-8{margin:var(--bui-space-8)}.md\:bui-m-9{margin:var(--bui-space-9)}.md\:bui-m-10{margin:var(--bui-space-10)}.md\:bui-m-11{margin:var(--bui-space-11)}.md\:bui-m-12{margin:var(--bui-space-12)}.md\:bui-m-13{margin:var(--bui-space-13)}.md\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-m{margin:var(--p-lg)}.lg\:bui-m-0\.5{margin:var(--bui-space-0_5)}.lg\:bui-m-1{margin:var(--bui-space-1)}.lg\:bui-m-1\.5{margin:var(--bui-space-1_5)}.lg\:bui-m-2{margin:var(--bui-space-2)}.lg\:bui-m-3{margin:var(--bui-space-3)}.lg\:bui-m-4{margin:var(--bui-space-4)}.lg\:bui-m-5{margin:var(--bui-space-5)}.lg\:bui-m-6{margin:var(--bui-space-6)}.lg\:bui-m-7{margin:var(--bui-space-7)}.lg\:bui-m-8{margin:var(--bui-space-8)}.lg\:bui-m-9{margin:var(--bui-space-9)}.lg\:bui-m-10{margin:var(--bui-space-10)}.lg\:bui-m-11{margin:var(--bui-space-11)}.lg\:bui-m-12{margin:var(--bui-space-12)}.lg\:bui-m-13{margin:var(--bui-space-13)}.lg\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-m{margin:var(--p-xl)}.xl\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xl\:bui-m-1{margin:var(--bui-space-1)}.xl\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xl\:bui-m-2{margin:var(--bui-space-2)}.xl\:bui-m-3{margin:var(--bui-space-3)}.xl\:bui-m-4{margin:var(--bui-space-4)}.xl\:bui-m-5{margin:var(--bui-space-5)}.xl\:bui-m-6{margin:var(--bui-space-6)}.xl\:bui-m-7{margin:var(--bui-space-7)}.xl\:bui-m-8{margin:var(--bui-space-8)}.xl\:bui-m-9{margin:var(--bui-space-9)}.xl\:bui-m-10{margin:var(--bui-space-10)}.xl\:bui-m-11{margin:var(--bui-space-11)}.xl\:bui-m-12{margin:var(--bui-space-12)}.xl\:bui-m-13{margin:var(--bui-space-13)}.xl\:bui-m-14{margin:var(--bui-space-14)}}.bui-ml{margin-left:var(--ml)}.bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.bui-ml-1{margin-left:var(--bui-space-1)}.bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.bui-ml-2{margin-left:var(--bui-space-2)}.bui-ml-3{margin-left:var(--bui-space-3)}.bui-ml-4{margin-left:var(--bui-space-4)}.bui-ml-5{margin-left:var(--bui-space-5)}.bui-ml-6{margin-left:var(--bui-space-6)}.bui-ml-7{margin-left:var(--bui-space-7)}.bui-ml-8{margin-left:var(--bui-space-8)}.bui-ml-9{margin-left:var(--bui-space-9)}.bui-ml-10{margin-left:var(--bui-space-10)}.bui-ml-11{margin-left:var(--bui-space-11)}.bui-ml-12{margin-left:var(--bui-space-12)}.bui-ml-13{margin-left:var(--bui-space-13)}.bui-ml-14{margin-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-ml{margin-left:var(--pl-xs)}.xs\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xs\:bui-ml-1{margin-left:var(--bui-space-1)}.xs\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xs\:bui-ml-2{margin-left:var(--bui-space-2)}.xs\:bui-ml-3{margin-left:var(--bui-space-3)}.xs\:bui-ml-4{margin-left:var(--bui-space-4)}.xs\:bui-ml-5{margin-left:var(--bui-space-5)}.xs\:bui-ml-6{margin-left:var(--bui-space-6)}.xs\:bui-ml-7{margin-left:var(--bui-space-7)}.xs\:bui-ml-8{margin-left:var(--bui-space-8)}.xs\:bui-ml-9{margin-left:var(--bui-space-9)}.xs\:bui-ml-10{margin-left:var(--bui-space-10)}.xs\:bui-ml-11{margin-left:var(--bui-space-11)}.xs\:bui-ml-12{margin-left:var(--bui-space-12)}.xs\:bui-ml-13{margin-left:var(--bui-space-13)}.xs\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-ml{margin-left:var(--pl-sm)}.sm\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.sm\:bui-ml-1{margin-left:var(--bui-space-1)}.sm\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.sm\:bui-ml-2{margin-left:var(--bui-space-2)}.sm\:bui-ml-3{margin-left:var(--bui-space-3)}.sm\:bui-ml-4{margin-left:var(--bui-space-4)}.sm\:bui-ml-5{margin-left:var(--bui-space-5)}.sm\:bui-ml-6{margin-left:var(--bui-space-6)}.sm\:bui-ml-7{margin-left:var(--bui-space-7)}.sm\:bui-ml-8{margin-left:var(--bui-space-8)}.sm\:bui-ml-9{margin-left:var(--bui-space-9)}.sm\:bui-ml-10{margin-left:var(--bui-space-10)}.sm\:bui-ml-11{margin-left:var(--bui-space-11)}.sm\:bui-ml-12{margin-left:var(--bui-space-12)}.sm\:bui-ml-13{margin-left:var(--bui-space-13)}.sm\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-ml{margin-left:var(--pl-md)}.md\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.md\:bui-ml-1{margin-left:var(--bui-space-1)}.md\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.md\:bui-ml-2{margin-left:var(--bui-space-2)}.md\:bui-ml-3{margin-left:var(--bui-space-3)}.md\:bui-ml-4{margin-left:var(--bui-space-4)}.md\:bui-ml-5{margin-left:var(--bui-space-5)}.md\:bui-ml-6{margin-left:var(--bui-space-6)}.md\:bui-ml-7{margin-left:var(--bui-space-7)}.md\:bui-ml-8{margin-left:var(--bui-space-8)}.md\:bui-ml-9{margin-left:var(--bui-space-9)}.md\:bui-ml-10{margin-left:var(--bui-space-10)}.md\:bui-ml-11{margin-left:var(--bui-space-11)}.md\:bui-ml-12{margin-left:var(--bui-space-12)}.md\:bui-ml-13{margin-left:var(--bui-space-13)}.md\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-ml{margin-left:var(--pl-lg)}.lg\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.lg\:bui-ml-1{margin-left:var(--bui-space-1)}.lg\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.lg\:bui-ml-2{margin-left:var(--bui-space-2)}.lg\:bui-ml-3{margin-left:var(--bui-space-3)}.lg\:bui-ml-4{margin-left:var(--bui-space-4)}.lg\:bui-ml-5{margin-left:var(--bui-space-5)}.lg\:bui-ml-6{margin-left:var(--bui-space-6)}.lg\:bui-ml-7{margin-left:var(--bui-space-7)}.lg\:bui-ml-8{margin-left:var(--bui-space-8)}.lg\:bui-ml-9{margin-left:var(--bui-space-9)}.lg\:bui-ml-10{margin-left:var(--bui-space-10)}.lg\:bui-ml-11{margin-left:var(--bui-space-11)}.lg\:bui-ml-12{margin-left:var(--bui-space-12)}.lg\:bui-ml-13{margin-left:var(--bui-space-13)}.lg\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-ml{margin-left:var(--pl-xl)}.xl\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xl\:bui-ml-1{margin-left:var(--bui-space-1)}.xl\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xl\:bui-ml-2{margin-left:var(--bui-space-2)}.xl\:bui-ml-3{margin-left:var(--bui-space-3)}.xl\:bui-ml-4{margin-left:var(--bui-space-4)}.xl\:bui-ml-5{margin-left:var(--bui-space-5)}.xl\:bui-ml-6{margin-left:var(--bui-space-6)}.xl\:bui-ml-7{margin-left:var(--bui-space-7)}.xl\:bui-ml-8{margin-left:var(--bui-space-8)}.xl\:bui-ml-9{margin-left:var(--bui-space-9)}.xl\:bui-ml-10{margin-left:var(--bui-space-10)}.xl\:bui-ml-11{margin-left:var(--bui-space-11)}.xl\:bui-ml-12{margin-left:var(--bui-space-12)}.xl\:bui-ml-13{margin-left:var(--bui-space-13)}.xl\:bui-ml-14{margin-left:var(--bui-space-14)}}.bui-mr{margin-right:var(--mr)}.bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.bui-mr-1{margin-right:var(--bui-space-1)}.bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.bui-mr-2{margin-right:var(--bui-space-2)}.bui-mr-3{margin-right:var(--bui-space-3)}.bui-mr-4{margin-right:var(--bui-space-4)}.bui-mr-5{margin-right:var(--bui-space-5)}.bui-mr-6{margin-right:var(--bui-space-6)}.bui-mr-7{margin-right:var(--bui-space-7)}.bui-mr-8{margin-right:var(--bui-space-8)}.bui-mr-9{margin-right:var(--bui-space-9)}.bui-mr-10{margin-right:var(--bui-space-10)}.bui-mr-11{margin-right:var(--bui-space-11)}.bui-mr-12{margin-right:var(--bui-space-12)}.bui-mr-13{margin-right:var(--bui-space-13)}.bui-mr-14{margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mr{margin-right:var(--pr-xs)}.xs\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xs\:bui-mr-1{margin-right:var(--bui-space-1)}.xs\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xs\:bui-mr-2{margin-right:var(--bui-space-2)}.xs\:bui-mr-3{margin-right:var(--bui-space-3)}.xs\:bui-mr-4{margin-right:var(--bui-space-4)}.xs\:bui-mr-5{margin-right:var(--bui-space-5)}.xs\:bui-mr-6{margin-right:var(--bui-space-6)}.xs\:bui-mr-7{margin-right:var(--bui-space-7)}.xs\:bui-mr-8{margin-right:var(--bui-space-8)}.xs\:bui-mr-9{margin-right:var(--bui-space-9)}.xs\:bui-mr-10{margin-right:var(--bui-space-10)}.xs\:bui-mr-11{margin-right:var(--bui-space-11)}.xs\:bui-mr-12{margin-right:var(--bui-space-12)}.xs\:bui-mr-13{margin-right:var(--bui-space-13)}.xs\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mr{margin-right:var(--pr-sm)}.sm\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.sm\:bui-mr-1{margin-right:var(--bui-space-1)}.sm\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.sm\:bui-mr-2{margin-right:var(--bui-space-2)}.sm\:bui-mr-3{margin-right:var(--bui-space-3)}.sm\:bui-mr-4{margin-right:var(--bui-space-4)}.sm\:bui-mr-5{margin-right:var(--bui-space-5)}.sm\:bui-mr-6{margin-right:var(--bui-space-6)}.sm\:bui-mr-7{margin-right:var(--bui-space-7)}.sm\:bui-mr-8{margin-right:var(--bui-space-8)}.sm\:bui-mr-9{margin-right:var(--bui-space-9)}.sm\:bui-mr-10{margin-right:var(--bui-space-10)}.sm\:bui-mr-11{margin-right:var(--bui-space-11)}.sm\:bui-mr-12{margin-right:var(--bui-space-12)}.sm\:bui-mr-13{margin-right:var(--bui-space-13)}.sm\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mr{margin-right:var(--pr-md)}.md\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.md\:bui-mr-1{margin-right:var(--bui-space-1)}.md\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.md\:bui-mr-2{margin-right:var(--bui-space-2)}.md\:bui-mr-3{margin-right:var(--bui-space-3)}.md\:bui-mr-4{margin-right:var(--bui-space-4)}.md\:bui-mr-5{margin-right:var(--bui-space-5)}.md\:bui-mr-6{margin-right:var(--bui-space-6)}.md\:bui-mr-7{margin-right:var(--bui-space-7)}.md\:bui-mr-8{margin-right:var(--bui-space-8)}.md\:bui-mr-9{margin-right:var(--bui-space-9)}.md\:bui-mr-10{margin-right:var(--bui-space-10)}.md\:bui-mr-11{margin-right:var(--bui-space-11)}.md\:bui-mr-12{margin-right:var(--bui-space-12)}.md\:bui-mr-13{margin-right:var(--bui-space-13)}.md\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mr{margin-right:var(--pr-lg)}.lg\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.lg\:bui-mr-1{margin-right:var(--bui-space-1)}.lg\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.lg\:bui-mr-2{margin-right:var(--bui-space-2)}.lg\:bui-mr-3{margin-right:var(--bui-space-3)}.lg\:bui-mr-4{margin-right:var(--bui-space-4)}.lg\:bui-mr-5{margin-right:var(--bui-space-5)}.lg\:bui-mr-6{margin-right:var(--bui-space-6)}.lg\:bui-mr-7{margin-right:var(--bui-space-7)}.lg\:bui-mr-8{margin-right:var(--bui-space-8)}.lg\:bui-mr-9{margin-right:var(--bui-space-9)}.lg\:bui-mr-10{margin-right:var(--bui-space-10)}.lg\:bui-mr-11{margin-right:var(--bui-space-11)}.lg\:bui-mr-12{margin-right:var(--bui-space-12)}.lg\:bui-mr-13{margin-right:var(--bui-space-13)}.lg\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mr{margin-right:var(--pr-xl)}.xl\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xl\:bui-mr-1{margin-right:var(--bui-space-1)}.xl\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xl\:bui-mr-2{margin-right:var(--bui-space-2)}.xl\:bui-mr-3{margin-right:var(--bui-space-3)}.xl\:bui-mr-4{margin-right:var(--bui-space-4)}.xl\:bui-mr-5{margin-right:var(--bui-space-5)}.xl\:bui-mr-6{margin-right:var(--bui-space-6)}.xl\:bui-mr-7{margin-right:var(--bui-space-7)}.xl\:bui-mr-8{margin-right:var(--bui-space-8)}.xl\:bui-mr-9{margin-right:var(--bui-space-9)}.xl\:bui-mr-10{margin-right:var(--bui-space-10)}.xl\:bui-mr-11{margin-right:var(--bui-space-11)}.xl\:bui-mr-12{margin-right:var(--bui-space-12)}.xl\:bui-mr-13{margin-right:var(--bui-space-13)}.xl\:bui-mr-14{margin-right:var(--bui-space-14)}}.bui-mt{margin-top:var(--mt)}.bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.bui-mt-1{margin-top:var(--bui-space-1)}.bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.bui-mt-2{margin-top:var(--bui-space-2)}.bui-mt-3{margin-top:var(--bui-space-3)}.bui-mt-4{margin-top:var(--bui-space-4)}.bui-mt-5{margin-top:var(--bui-space-5)}.bui-mt-6{margin-top:var(--bui-space-6)}.bui-mt-7{margin-top:var(--bui-space-7)}.bui-mt-8{margin-top:var(--bui-space-8)}.bui-mt-9{margin-top:var(--bui-space-9)}.bui-mt-10{margin-top:var(--bui-space-10)}.bui-mt-11{margin-top:var(--bui-space-11)}.bui-mt-12{margin-top:var(--bui-space-12)}.bui-mt-13{margin-top:var(--bui-space-13)}.bui-mt-14{margin-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mt{margin-top:var(--pt-xs)}.xs\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xs\:bui-mt-1{margin-top:var(--bui-space-1)}.xs\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xs\:bui-mt-2{margin-top:var(--bui-space-2)}.xs\:bui-mt-3{margin-top:var(--bui-space-3)}.xs\:bui-mt-4{margin-top:var(--bui-space-4)}.xs\:bui-mt-5{margin-top:var(--bui-space-5)}.xs\:bui-mt-6{margin-top:var(--bui-space-6)}.xs\:bui-mt-7{margin-top:var(--bui-space-7)}.xs\:bui-mt-8{margin-top:var(--bui-space-8)}.xs\:bui-mt-9{margin-top:var(--bui-space-9)}.xs\:bui-mt-10{margin-top:var(--bui-space-10)}.xs\:bui-mt-11{margin-top:var(--bui-space-11)}.xs\:bui-mt-12{margin-top:var(--bui-space-12)}.xs\:bui-mt-13{margin-top:var(--bui-space-13)}.xs\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mt{margin-top:var(--pt-sm)}.sm\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.sm\:bui-mt-1{margin-top:var(--bui-space-1)}.sm\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.sm\:bui-mt-2{margin-top:var(--bui-space-2)}.sm\:bui-mt-3{margin-top:var(--bui-space-3)}.sm\:bui-mt-4{margin-top:var(--bui-space-4)}.sm\:bui-mt-5{margin-top:var(--bui-space-5)}.sm\:bui-mt-6{margin-top:var(--bui-space-6)}.sm\:bui-mt-7{margin-top:var(--bui-space-7)}.sm\:bui-mt-8{margin-top:var(--bui-space-8)}.sm\:bui-mt-9{margin-top:var(--bui-space-9)}.sm\:bui-mt-10{margin-top:var(--bui-space-10)}.sm\:bui-mt-11{margin-top:var(--bui-space-11)}.sm\:bui-mt-12{margin-top:var(--bui-space-12)}.sm\:bui-mt-13{margin-top:var(--bui-space-13)}.sm\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mt{margin-top:var(--pt-md)}.md\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.md\:bui-mt-1{margin-top:var(--bui-space-1)}.md\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.md\:bui-mt-2{margin-top:var(--bui-space-2)}.md\:bui-mt-3{margin-top:var(--bui-space-3)}.md\:bui-mt-4{margin-top:var(--bui-space-4)}.md\:bui-mt-5{margin-top:var(--bui-space-5)}.md\:bui-mt-6{margin-top:var(--bui-space-6)}.md\:bui-mt-7{margin-top:var(--bui-space-7)}.md\:bui-mt-8{margin-top:var(--bui-space-8)}.md\:bui-mt-9{margin-top:var(--bui-space-9)}.md\:bui-mt-10{margin-top:var(--bui-space-10)}.md\:bui-mt-11{margin-top:var(--bui-space-11)}.md\:bui-mt-12{margin-top:var(--bui-space-12)}.md\:bui-mt-13{margin-top:var(--bui-space-13)}.md\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mt{margin-top:var(--pt-lg)}.lg\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.lg\:bui-mt-1{margin-top:var(--bui-space-1)}.lg\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.lg\:bui-mt-2{margin-top:var(--bui-space-2)}.lg\:bui-mt-3{margin-top:var(--bui-space-3)}.lg\:bui-mt-4{margin-top:var(--bui-space-4)}.lg\:bui-mt-5{margin-top:var(--bui-space-5)}.lg\:bui-mt-6{margin-top:var(--bui-space-6)}.lg\:bui-mt-7{margin-top:var(--bui-space-7)}.lg\:bui-mt-8{margin-top:var(--bui-space-8)}.lg\:bui-mt-9{margin-top:var(--bui-space-9)}.lg\:bui-mt-10{margin-top:var(--bui-space-10)}.lg\:bui-mt-11{margin-top:var(--bui-space-11)}.lg\:bui-mt-12{margin-top:var(--bui-space-12)}.lg\:bui-mt-13{margin-top:var(--bui-space-13)}.lg\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mt{margin-top:var(--pt-xl)}.xl\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xl\:bui-mt-1{margin-top:var(--bui-space-1)}.xl\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xl\:bui-mt-2{margin-top:var(--bui-space-2)}.xl\:bui-mt-3{margin-top:var(--bui-space-3)}.xl\:bui-mt-4{margin-top:var(--bui-space-4)}.xl\:bui-mt-5{margin-top:var(--bui-space-5)}.xl\:bui-mt-6{margin-top:var(--bui-space-6)}.xl\:bui-mt-7{margin-top:var(--bui-space-7)}.xl\:bui-mt-8{margin-top:var(--bui-space-8)}.xl\:bui-mt-9{margin-top:var(--bui-space-9)}.xl\:bui-mt-10{margin-top:var(--bui-space-10)}.xl\:bui-mt-11{margin-top:var(--bui-space-11)}.xl\:bui-mt-12{margin-top:var(--bui-space-12)}.xl\:bui-mt-13{margin-top:var(--bui-space-13)}.xl\:bui-mt-14{margin-top:var(--bui-space-14)}}.bui-mb{margin-bottom:var(--mb)}.bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.bui-mb-1{margin-bottom:var(--bui-space-1)}.bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.bui-mb-2{margin-bottom:var(--bui-space-2)}.bui-mb-3{margin-bottom:var(--bui-space-3)}.bui-mb-4{margin-bottom:var(--bui-space-4)}.bui-mb-5{margin-bottom:var(--bui-space-5)}.bui-mb-6{margin-bottom:var(--bui-space-6)}.bui-mb-7{margin-bottom:var(--bui-space-7)}.bui-mb-8{margin-bottom:var(--bui-space-8)}.bui-mb-9{margin-bottom:var(--bui-space-9)}.bui-mb-10{margin-bottom:var(--bui-space-10)}.bui-mb-11{margin-bottom:var(--bui-space-11)}.bui-mb-12{margin-bottom:var(--bui-space-12)}.bui-mb-13{margin-bottom:var(--bui-space-13)}.bui-mb-14{margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mb{margin-bottom:var(--pb-xs)}.xs\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xs\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xs\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xs\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xs\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xs\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xs\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xs\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xs\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xs\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xs\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xs\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xs\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xs\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xs\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xs\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mb{margin-bottom:var(--pb-sm)}.sm\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.sm\:bui-mb-1{margin-bottom:var(--bui-space-1)}.sm\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.sm\:bui-mb-2{margin-bottom:var(--bui-space-2)}.sm\:bui-mb-3{margin-bottom:var(--bui-space-3)}.sm\:bui-mb-4{margin-bottom:var(--bui-space-4)}.sm\:bui-mb-5{margin-bottom:var(--bui-space-5)}.sm\:bui-mb-6{margin-bottom:var(--bui-space-6)}.sm\:bui-mb-7{margin-bottom:var(--bui-space-7)}.sm\:bui-mb-8{margin-bottom:var(--bui-space-8)}.sm\:bui-mb-9{margin-bottom:var(--bui-space-9)}.sm\:bui-mb-10{margin-bottom:var(--bui-space-10)}.sm\:bui-mb-11{margin-bottom:var(--bui-space-11)}.sm\:bui-mb-12{margin-bottom:var(--bui-space-12)}.sm\:bui-mb-13{margin-bottom:var(--bui-space-13)}.sm\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mb{margin-bottom:var(--pb-md)}.md\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.md\:bui-mb-1{margin-bottom:var(--bui-space-1)}.md\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.md\:bui-mb-2{margin-bottom:var(--bui-space-2)}.md\:bui-mb-3{margin-bottom:var(--bui-space-3)}.md\:bui-mb-4{margin-bottom:var(--bui-space-4)}.md\:bui-mb-5{margin-bottom:var(--bui-space-5)}.md\:bui-mb-6{margin-bottom:var(--bui-space-6)}.md\:bui-mb-7{margin-bottom:var(--bui-space-7)}.md\:bui-mb-8{margin-bottom:var(--bui-space-8)}.md\:bui-mb-9{margin-bottom:var(--bui-space-9)}.md\:bui-mb-10{margin-bottom:var(--bui-space-10)}.md\:bui-mb-11{margin-bottom:var(--bui-space-11)}.md\:bui-mb-12{margin-bottom:var(--bui-space-12)}.md\:bui-mb-13{margin-bottom:var(--bui-space-13)}.md\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mb{margin-bottom:var(--pb-lg)}.lg\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.lg\:bui-mb-1{margin-bottom:var(--bui-space-1)}.lg\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.lg\:bui-mb-2{margin-bottom:var(--bui-space-2)}.lg\:bui-mb-3{margin-bottom:var(--bui-space-3)}.lg\:bui-mb-4{margin-bottom:var(--bui-space-4)}.lg\:bui-mb-5{margin-bottom:var(--bui-space-5)}.lg\:bui-mb-6{margin-bottom:var(--bui-space-6)}.lg\:bui-mb-7{margin-bottom:var(--bui-space-7)}.lg\:bui-mb-8{margin-bottom:var(--bui-space-8)}.lg\:bui-mb-9{margin-bottom:var(--bui-space-9)}.lg\:bui-mb-10{margin-bottom:var(--bui-space-10)}.lg\:bui-mb-11{margin-bottom:var(--bui-space-11)}.lg\:bui-mb-12{margin-bottom:var(--bui-space-12)}.lg\:bui-mb-13{margin-bottom:var(--bui-space-13)}.lg\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mb{margin-bottom:var(--pb-xl)}.xl\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xl\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xl\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xl\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xl\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xl\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xl\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xl\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xl\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xl\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xl\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xl\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xl\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xl\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xl\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xl\:bui-mb-14{margin-bottom:var(--bui-space-14)}}.bui-my{margin-top:var(--my);margin-bottom:var(--my)}.bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-my{margin-top:var(--py-xs);margin-bottom:var(--py-xs)}.xs\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xs\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xs\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xs\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xs\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xs\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xs\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xs\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xs\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xs\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xs\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xs\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xs\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xs\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xs\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xs\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-my{margin-top:var(--py-sm);margin-bottom:var(--py-sm)}.sm\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.sm\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.sm\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.sm\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.sm\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.sm\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.sm\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.sm\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.sm\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.sm\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.sm\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.sm\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.sm\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.sm\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.sm\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.sm\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-my{margin-top:var(--py-md);margin-bottom:var(--py-md)}.md\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.md\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.md\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.md\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.md\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.md\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.md\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.md\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.md\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.md\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.md\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.md\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.md\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.md\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.md\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.md\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-my{margin-top:var(--py-lg);margin-bottom:var(--py-lg)}.lg\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.lg\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.lg\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.lg\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.lg\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.lg\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.lg\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.lg\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.lg\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.lg\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.lg\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.lg\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.lg\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.lg\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.lg\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.lg\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-my{margin-top:var(--py-xl);margin-bottom:var(--py-xl)}.xl\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xl\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xl\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xl\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xl\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xl\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xl\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xl\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xl\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xl\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xl\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xl\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xl\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xl\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xl\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xl\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}.bui-mx{margin-left:var(--mx);margin-right:var(--mx)}.bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mx{margin-left:var(--px-xs);margin-right:var(--px-xs)}.xs\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xs\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xs\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xs\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xs\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xs\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xs\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xs\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xs\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xs\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xs\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xs\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xs\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xs\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xs\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xs\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mx{margin-left:var(--px-sm);margin-right:var(--px-sm)}.sm\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.sm\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.sm\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.sm\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.sm\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.sm\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.sm\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.sm\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.sm\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.sm\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.sm\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.sm\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.sm\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.sm\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.sm\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.sm\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mx{margin-left:var(--px-md);margin-right:var(--px-md)}.md\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.md\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.md\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.md\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.md\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.md\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.md\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.md\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.md\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.md\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.md\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.md\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.md\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.md\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.md\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.md\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mx{margin-left:var(--px-lg);margin-right:var(--px-lg)}.lg\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.lg\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.lg\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.lg\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.lg\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.lg\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.lg\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.lg\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.lg\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.lg\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.lg\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.lg\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.lg\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.lg\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.lg\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.lg\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mx{margin-left:var(--px-xl);margin-right:var(--px-xl)}.xl\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xl\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xl\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xl\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xl\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xl\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xl\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xl\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xl\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xl\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xl\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xl\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xl\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xl\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xl\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xl\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}.bui-display-none{display:none}.bui-display-inline{display:inline}.bui-display-inline-block{display:inline-block}.bui-display-block{display:block}@media (width>=640px){.xs\:bui-display-none{display:none}.xs\:bui-display-inline{display:inline}.xs\:bui-display-inline-block{display:inline-block}.xs\:bui-display-block{display:block}}@media (width>=768px){.sm\:bui-display-none{display:none}.sm\:bui-display-inline{display:inline}.sm\:bui-display-inline-block{display:inline-block}.sm\:bui-display-block{display:block}}@media (width>=1024px){.md\:bui-display-none{display:none}.md\:bui-display-inline{display:inline}.md\:bui-display-inline-block{display:inline-block}.md\:bui-display-block{display:block}}@media (width>=1280px){.lg\:bui-display-none{display:none}.lg\:bui-display-inline{display:inline}.lg\:bui-display-inline-block{display:inline-block}.lg\:bui-display-block{display:block}}@media (width>=1536px){.xl\:bui-display-none{display:none}.xl\:bui-display-inline{display:inline}.xl\:bui-display-inline-block{display:inline-block}.xl\:bui-display-block{display:block}}.bui-w{width:var(--width)}.bui-min-w{min-width:var(--min-width)}.bui-max-w{max-width:var(--max-width)}@media (width>=640px){.xs\:bui-w{width:var(--width)}.xs\:bui-min-w{min-width:var(--min-width)}.xs\:bui-max-w{max-width:var(--max-width)}}@media (width>=768px){.sm\:bui-w{width:var(--width)}.sm\:bui-min-w{min-width:var(--min-width)}.sm\:bui-max-w{max-width:var(--max-width)}}@media (width>=1024px){.md\:bui-w{width:var(--width)}.md\:bui-min-w{min-width:var(--min-width)}.md\:bui-max-w{max-width:var(--max-width)}}@media (width>=1280px){.lg\:bui-w{width:var(--width)}.lg\:bui-min-w{min-width:var(--min-width)}.lg\:bui-max-w{max-width:var(--max-width)}}@media (width>=1536px){.xl\:bui-w{width:var(--width)}.xl\:bui-min-w{min-width:var(--min-width)}.xl\:bui-max-w{max-width:var(--max-width)}}.bui-h{height:var(--height)}.bui-min-h{min-height:var(--min-height)}.bui-max-h{max-height:var(--max-height)}@media (width>=640px){.xs\:bui-h{height:var(--height)}.xs\:bui-min-h{min-height:var(--min-height)}.xs\:bui-max-h{max-height:var(--max-height)}}@media (width>=768px){.sm\:bui-h{height:var(--height)}.sm\:bui-min-h{min-height:var(--min-height)}.sm\:bui-max-h{max-height:var(--max-height)}}@media (width>=1024px){.md\:bui-h{height:var(--height)}.md\:bui-min-h{min-height:var(--min-height)}.md\:bui-max-h{max-height:var(--max-height)}}@media (width>=1280px){.lg\:bui-h{height:var(--height)}.lg\:bui-min-h{min-height:var(--min-height)}.lg\:bui-max-h{max-height:var(--max-height)}}@media (width>=1536px){.xl\:bui-h{height:var(--height)}.xl\:bui-min-h{min-height:var(--min-height)}.xl\:bui-max-h{max-height:var(--max-height)}}.bui-position-absolute{position:absolute}.bui-position-fixed{position:fixed}.bui-position-sticky{position:sticky}.bui-position-relative{position:relative}.bui-position-static{position:static}@media (width>=640px){.xs\:bui-position-absolute{position:absolute}.xs\:bui-position-fixed{position:fixed}.xs\:bui-position-sticky{position:sticky}.xs\:bui-position-relative{position:relative}.xs\:bui-position-static{position:static}}@media (width>=768px){.sm\:bui-position-absolute{position:absolute}.sm\:bui-position-fixed{position:fixed}.sm\:bui-position-sticky{position:sticky}.sm\:bui-position-relative{position:relative}.sm\:bui-position-static{position:static}}@media (width>=1024px){.md\:bui-position-absolute{position:absolute}.md\:bui-position-fixed{position:fixed}.md\:bui-position-sticky{position:sticky}.md\:bui-position-relative{position:relative}.md\:bui-position-static{position:static}}@media (width>=1280px){.lg\:bui-position-absolute{position:absolute}.lg\:bui-position-fixed{position:fixed}.lg\:bui-position-sticky{position:sticky}.lg\:bui-position-relative{position:relative}.lg\:bui-position-static{position:static}}@media (width>=1536px){.xl\:bui-position-absolute{position:absolute}.xl\:bui-position-fixed{position:fixed}.xl\:bui-position-sticky{position:sticky}.xl\:bui-position-relative{position:relative}.xl\:bui-position-static{position:static}}.bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.bui-col-span-1{grid-column:span 1/span 1}.bui-col-span-2{grid-column:span 2/span 2}.bui-col-span-3{grid-column:span 3/span 3}.bui-col-span-4{grid-column:span 4/span 4}.bui-col-span-5{grid-column:span 5/span 5}.bui-col-span-6{grid-column:span 6/span 6}.bui-col-span-7{grid-column:span 7/span 7}.bui-col-span-8{grid-column:span 8/span 8}.bui-col-span-9{grid-column:span 9/span 9}.bui-col-span-10{grid-column:span 10/span 10}.bui-col-span-11{grid-column:span 11/span 11}.bui-col-span-12{grid-column:span 12/span 12}.bui-col-span-auto{grid-column:span auto/span auto}.bui-col-start-1{grid-column-start:1}.bui-col-start-2{grid-column-start:2}.bui-col-start-3{grid-column-start:3}.bui-col-start-4{grid-column-start:4}.bui-col-start-5{grid-column-start:5}.bui-col-start-6{grid-column-start:6}.bui-col-start-7{grid-column-start:7}.bui-col-start-8{grid-column-start:8}.bui-col-start-9{grid-column-start:9}.bui-col-start-10{grid-column-start:10}.bui-col-start-11{grid-column-start:11}.bui-col-start-12{grid-column-start:12}.bui-col-start-13{grid-column-start:13}.bui-col-start-auto{grid-column-start:auto}.bui-col-end-1{grid-column-end:1}.bui-col-end-2{grid-column-end:2}.bui-col-end-3{grid-column-end:3}.bui-col-end-4{grid-column-end:4}.bui-col-end-5{grid-column-end:5}.bui-col-end-6{grid-column-end:6}.bui-col-end-7{grid-column-end:7}.bui-col-end-8{grid-column-end:8}.bui-col-end-9{grid-column-end:9}.bui-col-end-10{grid-column-end:10}.bui-col-end-11{grid-column-end:11}.bui-col-end-12{grid-column-end:12}.bui-col-end-13{grid-column-end:13}.bui-col-end-auto{grid-column-end:auto}.bui-row-span-1{grid-row:span 1/span 1}.bui-row-span-2{grid-row:span 2/span 2}.bui-row-span-3{grid-row:span 3/span 3}.bui-row-span-4{grid-row:span 4/span 4}.bui-row-span-5{grid-row:span 5/span 5}.bui-row-span-6{grid-row:span 6/span 6}.bui-row-span-7{grid-row:span 7/span 7}.bui-row-span-8{grid-row:span 8/span 8}.bui-row-span-9{grid-row:span 9/span 9}.bui-row-span-10{grid-row:span 10/span 10}.bui-row-span-11{grid-row:span 11/span 11}.bui-row-span-12{grid-row:span 12/span 12}.bui-row-span-auto{grid-row:span auto/span auto}@media (width>=640px){.xs\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xs\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xs\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xs\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xs\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xs\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xs\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xs\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xs\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xs\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xs\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xs\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xs\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xs\:bui-col-span-1{grid-column:span 1/span 1}.xs\:bui-col-span-2{grid-column:span 2/span 2}.xs\:bui-col-span-3{grid-column:span 3/span 3}.xs\:bui-col-span-4{grid-column:span 4/span 4}.xs\:bui-col-span-5{grid-column:span 5/span 5}.xs\:bui-col-span-6{grid-column:span 6/span 6}.xs\:bui-col-span-7{grid-column:span 7/span 7}.xs\:bui-col-span-8{grid-column:span 8/span 8}.xs\:bui-col-span-9{grid-column:span 9/span 9}.xs\:bui-col-span-10{grid-column:span 10/span 10}.xs\:bui-col-span-11{grid-column:span 11/span 11}.xs\:bui-col-span-12{grid-column:span 12/span 12}.xs\:bui-col-span-auto{grid-column:span auto/span auto}.xs\:bui-col-start-1{grid-column-start:1}.xs\:bui-col-start-2{grid-column-start:2}.xs\:bui-col-start-3{grid-column-start:3}.xs\:bui-col-start-4{grid-column-start:4}.xs\:bui-col-start-5{grid-column-start:5}.xs\:bui-col-start-6{grid-column-start:6}.xs\:bui-col-start-7{grid-column-start:7}.xs\:bui-col-start-8{grid-column-start:8}.xs\:bui-col-start-9{grid-column-start:9}.xs\:bui-col-start-10{grid-column-start:10}.xs\:bui-col-start-11{grid-column-start:11}.xs\:bui-col-start-12{grid-column-start:12}.xs\:bui-col-start-13{grid-column-start:13}.xs\:bui-col-start-auto{grid-column-start:auto}.xs\:bui-col-end-1{grid-column-end:1}.xs\:bui-col-end-2{grid-column-end:2}.xs\:bui-col-end-3{grid-column-end:3}.xs\:bui-col-end-4{grid-column-end:4}.xs\:bui-col-end-5{grid-column-end:5}.xs\:bui-col-end-6{grid-column-end:6}.xs\:bui-col-end-7{grid-column-end:7}.xs\:bui-col-end-8{grid-column-end:8}.xs\:bui-col-end-9{grid-column-end:9}.xs\:bui-col-end-10{grid-column-end:10}.xs\:bui-col-end-11{grid-column-end:11}.xs\:bui-col-end-12{grid-column-end:12}.xs\:bui-col-end-13{grid-column-end:13}.xs\:bui-col-end-auto{grid-column-end:auto}.xs\:bui-row-span-1{grid-row:span 1/span 1}.xs\:bui-row-span-2{grid-row:span 2/span 2}.xs\:bui-row-span-3{grid-row:span 3/span 3}.xs\:bui-row-span-4{grid-row:span 4/span 4}.xs\:bui-row-span-5{grid-row:span 5/span 5}.xs\:bui-row-span-6{grid-row:span 6/span 6}.xs\:bui-row-span-7{grid-row:span 7/span 7}.xs\:bui-row-span-8{grid-row:span 8/span 8}.xs\:bui-row-span-9{grid-row:span 9/span 9}.xs\:bui-row-span-10{grid-row:span 10/span 10}.xs\:bui-row-span-11{grid-row:span 11/span 11}.xs\:bui-row-span-12{grid-row:span 12/span 12}.xs\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=768px){.sm\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.sm\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:bui-col-span-1{grid-column:span 1/span 1}.sm\:bui-col-span-2{grid-column:span 2/span 2}.sm\:bui-col-span-3{grid-column:span 3/span 3}.sm\:bui-col-span-4{grid-column:span 4/span 4}.sm\:bui-col-span-5{grid-column:span 5/span 5}.sm\:bui-col-span-6{grid-column:span 6/span 6}.sm\:bui-col-span-7{grid-column:span 7/span 7}.sm\:bui-col-span-8{grid-column:span 8/span 8}.sm\:bui-col-span-9{grid-column:span 9/span 9}.sm\:bui-col-span-10{grid-column:span 10/span 10}.sm\:bui-col-span-11{grid-column:span 11/span 11}.sm\:bui-col-span-12{grid-column:span 12/span 12}.sm\:bui-col-span-auto{grid-column:span auto/span auto}.sm\:bui-col-start-1{grid-column-start:1}.sm\:bui-col-start-2{grid-column-start:2}.sm\:bui-col-start-3{grid-column-start:3}.sm\:bui-col-start-4{grid-column-start:4}.sm\:bui-col-start-5{grid-column-start:5}.sm\:bui-col-start-6{grid-column-start:6}.sm\:bui-col-start-7{grid-column-start:7}.sm\:bui-col-start-8{grid-column-start:8}.sm\:bui-col-start-9{grid-column-start:9}.sm\:bui-col-start-10{grid-column-start:10}.sm\:bui-col-start-11{grid-column-start:11}.sm\:bui-col-start-12{grid-column-start:12}.sm\:bui-col-start-13{grid-column-start:13}.sm\:bui-col-start-auto{grid-column-start:auto}.sm\:bui-col-end-1{grid-column-end:1}.sm\:bui-col-end-2{grid-column-end:2}.sm\:bui-col-end-3{grid-column-end:3}.sm\:bui-col-end-4{grid-column-end:4}.sm\:bui-col-end-5{grid-column-end:5}.sm\:bui-col-end-6{grid-column-end:6}.sm\:bui-col-end-7{grid-column-end:7}.sm\:bui-col-end-8{grid-column-end:8}.sm\:bui-col-end-9{grid-column-end:9}.sm\:bui-col-end-10{grid-column-end:10}.sm\:bui-col-end-11{grid-column-end:11}.sm\:bui-col-end-12{grid-column-end:12}.sm\:bui-col-end-13{grid-column-end:13}.sm\:bui-col-end-auto{grid-column-end:auto}.sm\:bui-row-span-1{grid-row:span 1/span 1}.sm\:bui-row-span-2{grid-row:span 2/span 2}.sm\:bui-row-span-3{grid-row:span 3/span 3}.sm\:bui-row-span-4{grid-row:span 4/span 4}.sm\:bui-row-span-5{grid-row:span 5/span 5}.sm\:bui-row-span-6{grid-row:span 6/span 6}.sm\:bui-row-span-7{grid-row:span 7/span 7}.sm\:bui-row-span-8{grid-row:span 8/span 8}.sm\:bui-row-span-9{grid-row:span 9/span 9}.sm\:bui-row-span-10{grid-row:span 10/span 10}.sm\:bui-row-span-11{grid-row:span 11/span 11}.sm\:bui-row-span-12{grid-row:span 12/span 12}.sm\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1024px){.md\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.md\:bui-col-span-1{grid-column:span 1/span 1}.md\:bui-col-span-2{grid-column:span 2/span 2}.md\:bui-col-span-3{grid-column:span 3/span 3}.md\:bui-col-span-4{grid-column:span 4/span 4}.md\:bui-col-span-5{grid-column:span 5/span 5}.md\:bui-col-span-6{grid-column:span 6/span 6}.md\:bui-col-span-7{grid-column:span 7/span 7}.md\:bui-col-span-8{grid-column:span 8/span 8}.md\:bui-col-span-9{grid-column:span 9/span 9}.md\:bui-col-span-10{grid-column:span 10/span 10}.md\:bui-col-span-11{grid-column:span 11/span 11}.md\:bui-col-span-12{grid-column:span 12/span 12}.md\:bui-col-span-auto{grid-column:span auto/span auto}.md\:bui-col-start-1{grid-column-start:1}.md\:bui-col-start-2{grid-column-start:2}.md\:bui-col-start-3{grid-column-start:3}.md\:bui-col-start-4{grid-column-start:4}.md\:bui-col-start-5{grid-column-start:5}.md\:bui-col-start-6{grid-column-start:6}.md\:bui-col-start-7{grid-column-start:7}.md\:bui-col-start-8{grid-column-start:8}.md\:bui-col-start-9{grid-column-start:9}.md\:bui-col-start-10{grid-column-start:10}.md\:bui-col-start-11{grid-column-start:11}.md\:bui-col-start-12{grid-column-start:12}.md\:bui-col-start-13{grid-column-start:13}.md\:bui-col-start-auto{grid-column-start:auto}.md\:bui-col-end-1{grid-column-end:1}.md\:bui-col-end-2{grid-column-end:2}.md\:bui-col-end-3{grid-column-end:3}.md\:bui-col-end-4{grid-column-end:4}.md\:bui-col-end-5{grid-column-end:5}.md\:bui-col-end-6{grid-column-end:6}.md\:bui-col-end-7{grid-column-end:7}.md\:bui-col-end-8{grid-column-end:8}.md\:bui-col-end-9{grid-column-end:9}.md\:bui-col-end-10{grid-column-end:10}.md\:bui-col-end-11{grid-column-end:11}.md\:bui-col-end-12{grid-column-end:12}.md\:bui-col-end-13{grid-column-end:13}.md\:bui-col-end-auto{grid-column-end:auto}.md\:bui-row-span-1{grid-row:span 1/span 1}.md\:bui-row-span-2{grid-row:span 2/span 2}.md\:bui-row-span-3{grid-row:span 3/span 3}.md\:bui-row-span-4{grid-row:span 4/span 4}.md\:bui-row-span-5{grid-row:span 5/span 5}.md\:bui-row-span-6{grid-row:span 6/span 6}.md\:bui-row-span-7{grid-row:span 7/span 7}.md\:bui-row-span-8{grid-row:span 8/span 8}.md\:bui-row-span-9{grid-row:span 9/span 9}.md\:bui-row-span-10{grid-row:span 10/span 10}.md\:bui-row-span-11{grid-row:span 11/span 11}.md\:bui-row-span-12{grid-row:span 12/span 12}.md\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1280px){.lg\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.lg\:bui-col-span-1{grid-column:span 1/span 1}.lg\:bui-col-span-2{grid-column:span 2/span 2}.lg\:bui-col-span-3{grid-column:span 3/span 3}.lg\:bui-col-span-4{grid-column:span 4/span 4}.lg\:bui-col-span-5{grid-column:span 5/span 5}.lg\:bui-col-span-6{grid-column:span 6/span 6}.lg\:bui-col-span-7{grid-column:span 7/span 7}.lg\:bui-col-span-8{grid-column:span 8/span 8}.lg\:bui-col-span-9{grid-column:span 9/span 9}.lg\:bui-col-span-10{grid-column:span 10/span 10}.lg\:bui-col-span-11{grid-column:span 11/span 11}.lg\:bui-col-span-12{grid-column:span 12/span 12}.lg\:bui-col-span-auto{grid-column:span auto/span auto}.lg\:bui-col-start-1{grid-column-start:1}.lg\:bui-col-start-2{grid-column-start:2}.lg\:bui-col-start-3{grid-column-start:3}.lg\:bui-col-start-4{grid-column-start:4}.lg\:bui-col-start-5{grid-column-start:5}.lg\:bui-col-start-6{grid-column-start:6}.lg\:bui-col-start-7{grid-column-start:7}.lg\:bui-col-start-8{grid-column-start:8}.lg\:bui-col-start-9{grid-column-start:9}.lg\:bui-col-start-10{grid-column-start:10}.lg\:bui-col-start-11{grid-column-start:11}.lg\:bui-col-start-12{grid-column-start:12}.lg\:bui-col-start-13{grid-column-start:13}.lg\:bui-col-start-auto{grid-column-start:auto}.lg\:bui-col-end-1{grid-column-end:1}.lg\:bui-col-end-2{grid-column-end:2}.lg\:bui-col-end-3{grid-column-end:3}.lg\:bui-col-end-4{grid-column-end:4}.lg\:bui-col-end-5{grid-column-end:5}.lg\:bui-col-end-6{grid-column-end:6}.lg\:bui-col-end-7{grid-column-end:7}.lg\:bui-col-end-8{grid-column-end:8}.lg\:bui-col-end-9{grid-column-end:9}.lg\:bui-col-end-10{grid-column-end:10}.lg\:bui-col-end-11{grid-column-end:11}.lg\:bui-col-end-12{grid-column-end:12}.lg\:bui-col-end-13{grid-column-end:13}.lg\:bui-col-end-auto{grid-column-end:auto}.lg\:bui-row-span-1{grid-row:span 1/span 1}.lg\:bui-row-span-2{grid-row:span 2/span 2}.lg\:bui-row-span-3{grid-row:span 3/span 3}.lg\:bui-row-span-4{grid-row:span 4/span 4}.lg\:bui-row-span-5{grid-row:span 5/span 5}.lg\:bui-row-span-6{grid-row:span 6/span 6}.lg\:bui-row-span-7{grid-row:span 7/span 7}.lg\:bui-row-span-8{grid-row:span 8/span 8}.lg\:bui-row-span-9{grid-row:span 9/span 9}.lg\:bui-row-span-10{grid-row:span 10/span 10}.lg\:bui-row-span-11{grid-row:span 11/span 11}.lg\:bui-row-span-12{grid-row:span 12/span 12}.lg\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1536px){.xl\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xl\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xl\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xl\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xl\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xl\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xl\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xl\:bui-col-span-1{grid-column:span 1/span 1}.xl\:bui-col-span-2{grid-column:span 2/span 2}.xl\:bui-col-span-3{grid-column:span 3/span 3}.xl\:bui-col-span-4{grid-column:span 4/span 4}.xl\:bui-col-span-5{grid-column:span 5/span 5}.xl\:bui-col-span-6{grid-column:span 6/span 6}.xl\:bui-col-span-7{grid-column:span 7/span 7}.xl\:bui-col-span-8{grid-column:span 8/span 8}.xl\:bui-col-span-9{grid-column:span 9/span 9}.xl\:bui-col-span-10{grid-column:span 10/span 10}.xl\:bui-col-span-11{grid-column:span 11/span 11}.xl\:bui-col-span-12{grid-column:span 12/span 12}.xl\:bui-col-span-auto{grid-column:span auto/span auto}.xl\:bui-col-start-1{grid-column-start:1}.xl\:bui-col-start-2{grid-column-start:2}.xl\:bui-col-start-3{grid-column-start:3}.xl\:bui-col-start-4{grid-column-start:4}.xl\:bui-col-start-5{grid-column-start:5}.xl\:bui-col-start-6{grid-column-start:6}.xl\:bui-col-start-7{grid-column-start:7}.xl\:bui-col-start-8{grid-column-start:8}.xl\:bui-col-start-9{grid-column-start:9}.xl\:bui-col-start-10{grid-column-start:10}.xl\:bui-col-start-11{grid-column-start:11}.xl\:bui-col-start-12{grid-column-start:12}.xl\:bui-col-start-13{grid-column-start:13}.xl\:bui-col-start-auto{grid-column-start:auto}.xl\:bui-col-end-1{grid-column-end:1}.xl\:bui-col-end-2{grid-column-end:2}.xl\:bui-col-end-3{grid-column-end:3}.xl\:bui-col-end-4{grid-column-end:4}.xl\:bui-col-end-5{grid-column-end:5}.xl\:bui-col-end-6{grid-column-end:6}.xl\:bui-col-end-7{grid-column-end:7}.xl\:bui-col-end-8{grid-column-end:8}.xl\:bui-col-end-9{grid-column-end:9}.xl\:bui-col-end-10{grid-column-end:10}.xl\:bui-col-end-11{grid-column-end:11}.xl\:bui-col-end-12{grid-column-end:12}.xl\:bui-col-end-13{grid-column-end:13}.xl\:bui-col-end-auto{grid-column-end:auto}.xl\:bui-row-span-1{grid-row:span 1/span 1}.xl\:bui-row-span-2{grid-row:span 2/span 2}.xl\:bui-row-span-3{grid-row:span 3/span 3}.xl\:bui-row-span-4{grid-row:span 4/span 4}.xl\:bui-row-span-5{grid-row:span 5/span 5}.xl\:bui-row-span-6{grid-row:span 6/span 6}.xl\:bui-row-span-7{grid-row:span 7/span 7}.xl\:bui-row-span-8{grid-row:span 8/span 8}.xl\:bui-row-span-9{grid-row:span 9/span 9}.xl\:bui-row-span-10{grid-row:span 10/span 10}.xl\:bui-row-span-11{grid-row:span 11/span 11}.xl\:bui-row-span-12{grid-row:span 12/span 12}.xl\:bui-row-span-auto{grid-row:span auto/span auto}}.bui-gap{gap:var(--gap)}.bui-gap-0\.5{gap:var(--bui-space-0_5)}.bui-gap-1{gap:var(--bui-space-1)}.bui-gap-1\.5{gap:var(--bui-space-1_5)}.bui-gap-2{gap:var(--bui-space-2)}.bui-gap-3{gap:var(--bui-space-3)}.bui-gap-4{gap:var(--bui-space-4)}.bui-gap-5{gap:var(--bui-space-5)}.bui-gap-6{gap:var(--bui-space-6)}.bui-gap-7{gap:var(--bui-space-7)}.bui-gap-8{gap:var(--bui-space-8)}.bui-gap-9{gap:var(--bui-space-9)}.bui-gap-10{gap:var(--bui-space-10)}.bui-gap-11{gap:var(--bui-space-11)}.bui-gap-12{gap:var(--bui-space-12)}.bui-gap-13{gap:var(--bui-space-13)}.bui-gap-14{gap:var(--bui-space-14)}@media (width>=640px){.xs\:bui-gap{gap:var(--gap-xs)}.xs\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xs\:bui-gap-1{gap:var(--bui-space-1)}.xs\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xs\:bui-gap-2{gap:var(--bui-space-2)}.xs\:bui-gap-3{gap:var(--bui-space-3)}.xs\:bui-gap-4{gap:var(--bui-space-4)}.xs\:bui-gap-5{gap:var(--bui-space-5)}.xs\:bui-gap-6{gap:var(--bui-space-6)}.xs\:bui-gap-7{gap:var(--bui-space-7)}.xs\:bui-gap-8{gap:var(--bui-space-8)}.xs\:bui-gap-9{gap:var(--bui-space-9)}.xs\:bui-gap-10{gap:var(--bui-space-10)}.xs\:bui-gap-11{gap:var(--bui-space-11)}.xs\:bui-gap-12{gap:var(--bui-space-12)}.xs\:bui-gap-13{gap:var(--bui-space-13)}.xs\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-gap{gap:var(--gap-sm)}.sm\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.sm\:bui-gap-1{gap:var(--bui-space-1)}.sm\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.sm\:bui-gap-2{gap:var(--bui-space-2)}.sm\:bui-gap-3{gap:var(--bui-space-3)}.sm\:bui-gap-4{gap:var(--bui-space-4)}.sm\:bui-gap-5{gap:var(--bui-space-5)}.sm\:bui-gap-6{gap:var(--bui-space-6)}.sm\:bui-gap-7{gap:var(--bui-space-7)}.sm\:bui-gap-8{gap:var(--bui-space-8)}.sm\:bui-gap-9{gap:var(--bui-space-9)}.sm\:bui-gap-10{gap:var(--bui-space-10)}.sm\:bui-gap-11{gap:var(--bui-space-11)}.sm\:bui-gap-12{gap:var(--bui-space-12)}.sm\:bui-gap-13{gap:var(--bui-space-13)}.sm\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-gap{gap:var(--gap-md)}.md\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.md\:bui-gap-1{gap:var(--bui-space-1)}.md\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.md\:bui-gap-2{gap:var(--bui-space-2)}.md\:bui-gap-3{gap:var(--bui-space-3)}.md\:bui-gap-4{gap:var(--bui-space-4)}.md\:bui-gap-5{gap:var(--bui-space-5)}.md\:bui-gap-6{gap:var(--bui-space-6)}.md\:bui-gap-7{gap:var(--bui-space-7)}.md\:bui-gap-8{gap:var(--bui-space-8)}.md\:bui-gap-9{gap:var(--bui-space-9)}.md\:bui-gap-10{gap:var(--bui-space-10)}.md\:bui-gap-11{gap:var(--bui-space-11)}.md\:bui-gap-12{gap:var(--bui-space-12)}.md\:bui-gap-13{gap:var(--bui-space-13)}.md\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-gap{gap:var(--gap-lg)}.lg\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.lg\:bui-gap-1{gap:var(--bui-space-1)}.lg\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.lg\:bui-gap-2{gap:var(--bui-space-2)}.lg\:bui-gap-3{gap:var(--bui-space-3)}.lg\:bui-gap-4{gap:var(--bui-space-4)}.lg\:bui-gap-5{gap:var(--bui-space-5)}.lg\:bui-gap-6{gap:var(--bui-space-6)}.lg\:bui-gap-7{gap:var(--bui-space-7)}.lg\:bui-gap-8{gap:var(--bui-space-8)}.lg\:bui-gap-9{gap:var(--bui-space-9)}.lg\:bui-gap-10{gap:var(--bui-space-10)}.lg\:bui-gap-11{gap:var(--bui-space-11)}.lg\:bui-gap-12{gap:var(--bui-space-12)}.lg\:bui-gap-13{gap:var(--bui-space-13)}.lg\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-gap{gap:var(--gap-xl)}.xl\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xl\:bui-gap-1{gap:var(--bui-space-1)}.xl\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xl\:bui-gap-2{gap:var(--bui-space-2)}.xl\:bui-gap-3{gap:var(--bui-space-3)}.xl\:bui-gap-4{gap:var(--bui-space-4)}.xl\:bui-gap-5{gap:var(--bui-space-5)}.xl\:bui-gap-6{gap:var(--bui-space-6)}.xl\:bui-gap-7{gap:var(--bui-space-7)}.xl\:bui-gap-8{gap:var(--bui-space-8)}.xl\:bui-gap-9{gap:var(--bui-space-9)}.xl\:bui-gap-10{gap:var(--bui-space-10)}.xl\:bui-gap-11{gap:var(--bui-space-11)}.xl\:bui-gap-12{gap:var(--bui-space-12)}.xl\:bui-gap-13{gap:var(--bui-space-13)}.xl\:bui-gap-14{gap:var(--bui-space-14)}}.bui-align-start{align-items:start}.bui-align-center{align-items:center}.bui-align-end{align-items:end}.bui-align-stretch{align-items:stretch}.bui-jc-start{justify-content:start}.bui-jc-center{justify-content:center}.bui-jc-end{justify-content:end}.bui-jc-between{justify-content:space-between}.bui-fd-row{flex-direction:row}.bui-fd-column{flex-direction:column}.bui-fd-row-reverse{flex-direction:row-reverse}.bui-fd-column-reverse{flex-direction:column-reverse}@media (width>=640px){.xs\:bui-align-start{align-items:start}.xs\:bui-align-center{align-items:center}.xs\:bui-align-end{align-items:end}.xs\:bui-align-stretch{align-items:stretch}.xs\:bui-jc-start{justify-content:start}.xs\:bui-jc-center{justify-content:center}.xs\:bui-jc-end{justify-content:end}.xs\:bui-jc-between{justify-content:space-between}.xs\:bui-fd-row{flex-direction:row}.xs\:bui-fd-column{flex-direction:column}.xs\:bui-fd-row-reverse{flex-direction:row-reverse}.xs\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=768px){.sm\:bui-align-start{align-items:start}.sm\:bui-align-center{align-items:center}.sm\:bui-align-end{align-items:end}.sm\:bui-align-stretch{align-items:stretch}.sm\:bui-jc-start{justify-content:start}.sm\:bui-jc-center{justify-content:center}.sm\:bui-jc-end{justify-content:end}.sm\:bui-jc-between{justify-content:space-between}.sm\:bui-fd-row{flex-direction:row}.sm\:bui-fd-column{flex-direction:column}.sm\:bui-fd-row-reverse{flex-direction:row-reverse}.sm\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1024px){.md\:bui-align-start{align-items:start}.md\:bui-align-center{align-items:center}.md\:bui-align-end{align-items:end}.md\:bui-align-stretch{align-items:stretch}.md\:bui-jc-start{justify-content:start}.md\:bui-jc-center{justify-content:center}.md\:bui-jc-end{justify-content:end}.md\:bui-jc-between{justify-content:space-between}.md\:bui-fd-row{flex-direction:row}.md\:bui-fd-column{flex-direction:column}.md\:bui-fd-row-reverse{flex-direction:row-reverse}.md\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1280px){.lg\:bui-align-start{align-items:start}.lg\:bui-align-center{align-items:center}.lg\:bui-align-end{align-items:end}.lg\:bui-align-stretch{align-items:stretch}.lg\:bui-jc-start{justify-content:start}.lg\:bui-jc-center{justify-content:center}.lg\:bui-jc-end{justify-content:end}.lg\:bui-jc-between{justify-content:space-between}.lg\:bui-fd-row{flex-direction:row}.lg\:bui-fd-column{flex-direction:column}.lg\:bui-fd-row-reverse{flex-direction:row-reverse}.lg\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1536px){.xl\:bui-align-start{align-items:start}.xl\:bui-align-center{align-items:center}.xl\:bui-align-end{align-items:end}.xl\:bui-align-stretch{align-items:stretch}.xl\:bui-jc-start{justify-content:start}.xl\:bui-jc-center{justify-content:center}.xl\:bui-jc-end{justify-content:end}.xl\:bui-jc-between{justify-content:space-between}.xl\:bui-fd-row{flex-direction:row}.xl\:bui-fd-column{flex-direction:column}.xl\:bui-fd-row-reverse{flex-direction:row-reverse}.xl\:bui-fd-column-reverse{flex-direction:column-reverse}}:where(a){color:inherit;text-decoration:none}@keyframes pulse{50%{opacity:.5}}:root{--bui-font-regular:system-ui;--bui-font-monospace:ui-monospace,"Menlo","Monaco","Consolas","Liberation Mono","Courier New",monospace;--bui-font-weight-regular:400;--bui-font-weight-bold:600;--bui-font-size-1:.625rem;--bui-font-size-2:.75rem;--bui-font-size-3:.875rem;--bui-font-size-4:1rem;--bui-font-size-5:1.25rem;--bui-font-size-6:1.5rem;--bui-font-size-7:2rem;--bui-font-size-8:3rem;--bui-font-size-9:4rem;--bui-font-size-10:5.75rem;--bui-space:.25rem;--bui-space-0_5:calc(var(--bui-space)*.5);--bui-space-1:var(--bui-space);--bui-space-1_5:calc(var(--bui-space)*1.5);--bui-space-2:calc(var(--bui-space)*2);--bui-space-3:calc(var(--bui-space)*3);--bui-space-4:calc(var(--bui-space)*4);--bui-space-5:calc(var(--bui-space)*5);--bui-space-6:calc(var(--bui-space)*6);--bui-space-7:calc(var(--bui-space)*7);--bui-space-8:calc(var(--bui-space)*8);--bui-space-9:calc(var(--bui-space)*9);--bui-space-10:calc(var(--bui-space)*10);--bui-space-11:calc(var(--bui-space)*11);--bui-space-12:calc(var(--bui-space)*12);--bui-space-13:calc(var(--bui-space)*13);--bui-space-14:calc(var(--bui-space)*14);--bui-radius-1:calc(.125rem);--bui-radius-2:calc(.25rem);--bui-radius-3:calc(.5rem);--bui-radius-4:calc(.75rem);--bui-radius-5:calc(1rem);--bui-radius-6:calc(1.25rem);--bui-radius-full:9999px;--bui-black:#000;--bui-white:#fff;--bui-gray-1:#f8f8f8;--bui-gray-2:#ececec;--bui-gray-3:#d9d9d9;--bui-gray-4:#c1c1c1;--bui-gray-5:#9e9e9e;--bui-gray-6:#8c8c8c;--bui-gray-7:#757575;--bui-gray-8:#595959;--bui-bg:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1f5493;--bui-bg-solid-hover:#163a66;--bui-bg-solid-pressed:#0f2b4e;--bui-bg-solid-disabled:#ebebeb;--bui-bg-tint:transparent;--bui-bg-tint-hover:#1f549366;--bui-bg-tint-pressed:#1f549399;--bui-bg-tint-disabled:#ebebeb;--bui-bg-danger:#feebe7;--bui-bg-warning:#fff2b2;--bui-bg-success:#e6f6eb;--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#1f5493;--bui-fg-link-hover:#1f2d5c;--bui-fg-disabled:#9e9e9e;--bui-fg-solid:var(--bui-white);--bui-fg-solid-disabled:#9c9c9c;--bui-fg-tint:#1f5493;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#0000001a;--bui-border-hover:#0003;--bui-border-pressed:#0006;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#a0a0a03b;--bui-scrollbar-thumb:#a0a0a0;--bui-animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite}[data-theme-mode=dark]{--bui-gray-1:#191919;--bui-gray-2:#242424;--bui-gray-3:#373737;--bui-gray-4:#464646;--bui-gray-5:#575757;--bui-gray-6:#7b7b7b;--bui-gray-7:#9e9e9e;--bui-gray-8:#b4b4b4;--bui-bg:#333;--bui-bg-surface-1:#424242;--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#9cc9ff;--bui-bg-solid-hover:#83b9fd;--bui-bg-solid-pressed:#83b9fd;--bui-bg-solid-disabled:#222;--bui-bg-tint:transparent;--bui-bg-tint-hover:#9cc9ff1f;--bui-bg-tint-pressed:#9cc9ff29;--bui-bg-tint-disabled:transparent;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#9cc9ff;--bui-fg-link-hover:#7eb5f7;--bui-fg-disabled:var(--bui-gray-7);--bui-fg-solid:#101821;--bui-fg-solid-disabled:var(--bui-gray-5);--bui-fg-tint:#9cc9ff;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#ffffff1f;--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#3636363a;--bui-scrollbar-thumb:#575757}.bui-AvatarRoot{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-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}.bui-AvatarRoot[data-size=small]{width:1.5rem;height:1.5rem}.bui-AvatarRoot[data-size=medium]{width:2rem;height:2rem}.bui-AvatarRoot[data-size=large]{width:3rem;height:3rem}.bui-AvatarImage{object-fit:cover;width:100%;height:100%}.bui-AvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-Box{font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary)}.bui-Button{user-select:none;font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-bold);cursor:pointer;border-radius:var(--bui-radius-2);justify-content:center;align-items:center;gap:var(--bui-space-1_5);border:none;flex-shrink:0;padding:0;display:inline-flex;&[data-disabled=true]{cursor:not-allowed}}.bui-Button[data-variant=primary]{background-color:var(--bui-bg-solid);color:var(--bui-fg-solid);&:hover{background-color:var(--bui-bg-solid-hover);transition:background-color .15s}&:active{background-color:var(--bui-bg-solid-pressed)}&:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled=true]{background-color:var(--bui-bg-solid-disabled);color:var(--bui-fg-solid-disabled)}}.bui-Button[data-variant=secondary]{background-color:var(--bui-bg-surface-1);box-shadow:inset 0 0 0 1px var(--bui-border);color:var(--bui-fg-primary);&:hover{box-shadow:inset 0 0 0 1px var(--bui-border-hover);transition:box-shadow .15s}&:active{box-shadow:inset 0 0 0 1px var(--bui-border-pressed)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{box-shadow:inset 0 0 0 1px var(--bui-border-disabled);color:var(--bui-fg-disabled)}}.bui-Button[data-variant=tertiary]{color:var(--bui-fg-primary);background-color:#0000;&:hover{background-color:var(--bui-bg-surface-1);transition:background-color .2s}&:active{background-color:var(--bui-bg-surface-2)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{color:var(--bui-fg-disabled);background-color:#0000}}.bui-Button[data-size=medium]{font-size:var(--bui-font-size-4);padding:0 var(--bui-space-3);height:2.5rem}.bui-Button[data-size=small]{font-size:var(--bui-font-size-3);padding:0 var(--bui-space-2);height:2rem}.bui-Button[data-size=small] svg{width:1rem;height:1rem}.bui-Button[data-size=medium] svg{width:1.25rem;height:1.25rem}.bui-ButtonIcon{justify-content:center;align-items:center}.bui-ButtonIcon[data-size=small]{width:2rem;padding:0}.bui-ButtonIcon[data-size=medium]{width:2.5rem;padding:0}.bui-Card{gap:var(--bui-space-3);background-color:var(--bui-bg-surface-1);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-3);color:var(--bui-fg-primary);border:1px solid var(--bui-border);flex-direction:column;width:100%;min-height:0;display:flex;overflow:hidden}.bui-CardBody{flex:1;min-height:0;overflow:auto}.bui-CardHeader,.bui-CardFooter{padding-inline:var(--bui-space-3)}.bui-CheckboxRoot{width:1rem;height:1rem;box-shadow:inset 0 0 0 1px var(--bui-border);cursor:pointer;background-color:var(--bui-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}.bui-CheckboxRoot:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px;transition:none}.bui-CheckboxRoot[data-checked]{background-color:var(--bui-bg-solid);box-shadow:none;color:var(--bui-fg-solid)}.bui-CheckboxLabel{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);user-select:none;flex-direction:row;display:flex;&:hover{& .bui-CheckboxRoot:not([data-checked]){box-shadow:inset 0 0 0 1px var(--bui-border-hover)}}}.bui-CheckboxIndicator{color:var(--bui-fg-solid);justify-content:center;align-items:center;display:flex}.bui-CollapsiblePanel{height:var(--collapsible-panel-height);transition:all .15s ease-out;display:flex;overflow:hidden;&[data-starting-style],&[data-ending-style]{height:0}}.bui-Container{max-width:120rem;padding-inline:var(--bui-space-4);margin-inline:auto;transition:padding .2s ease-in-out}@media (width>=640px){.bui-Container{padding-inline:var(--bui-space-5)}}.bui-FieldError{color:var(--bui-fg-danger);font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);margin-top:var(--bui-space-2);display:inline-block}.bui-FieldLabelWrapper{margin-bottom:var(--bui-space-3);gap:var(--bui-space-1);flex-direction:column;display:flex}.bui-FieldLabel{color:var(--bui-fg-primary);cursor:pointer;font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);margin-right:auto}.bui-FieldSecondaryLabel{color:var(--bui-fg-secondary);font-weight:var(--bui-font-weight-regular);margin-left:var(--bui-space-1)}.bui-FieldDescription{font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);color:var(--bui-fg-secondary);margin:0}.bui-Flex{min-width:0;display:flex}.bui-Grid{display:grid}.bui-HeaderToolbar{margin-bottom:var(--bui-space-6);&:before{content:"";background-color:var(--bui-bg);z-index:0;height:16px;position:absolute;top:0;left:0;right:0}&[data-has-tabs=true]{margin-bottom:0}}.bui-HeaderToolbarWrapper{z-index:1;background-color:var(--bui-bg-surface-1);padding-inline:var(--bui-space-5);border-bottom:1px solid var(--bui-border);color:var(--bui-fg-primary);flex-direction:row;justify-content:space-between;align-items:center;height:52px;display:flex;position:relative}.bui-HeaderToolbarContent{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-HeaderToolbarName{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);flex-direction:row;flex-shrink:0;display:flex}.bui-HeaderToolbarIcon{width:16px;height:16px;color:var(--bui-fg-primary);& svg{width:100%;height:100%}}.bui-HeaderToolbarControls{right:var(--bui-space-5);align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex;position:absolute;top:50%;transform:translateY(-50%)}.bui-HeaderTabsWrapper{margin-bottom:var(--bui-space-4);padding-inline:var(--bui-space-3);border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1)}.bui-HeaderPage{gap:var(--bui-space-1);margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6);flex-direction:column;display:flex}.bui-HeaderPageContent{flex-direction:row;justify-content:space-between;display:flex}.bui-HeaderPageTabsWrapper{margin-left:-8px}.bui-HeaderPageControls,.bui-HeaderPageBreadcrumbs{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-Icon{width:1rem;height:1rem}.bui-Link{font-family:var(--bui-font-regular);cursor:pointer;margin:0;padding:0;text-decoration-line:none;display:inline-block;&: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,currentColor 30%,transparent)}}.bui-MenuPopover{border:1px solid var(--bui-border);border-radius:var(--bui-radius-2);background:var(--bui-bg-surface-1);color:var(--bui-fg-primary);outline:none;flex-direction:column;min-height:0;transition:transform .2s,opacity .2s;display:flex;overflow:hidden;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}&[data-placement=top]{--origin:translateY(8px)}&[data-placement=bottom]{--origin:translateY(-8px)}&[data-placement=right]{--origin:translateX(-8px)}&[data-placement=left]{--origin:translateX(8px)}}.bui-MenuContent{max-height:inherit;box-sizing:border-box;padding:var(--bui-space-1);outline:none;min-width:150px;overflow:auto}.bui-MenuPopover .bui-ScrollAreaRoot{flex-direction:column;flex:1;height:100%;min-height:0;display:flex}.bui-MenuPopover .bui-ScrollAreaScrollbar{margin-inline:var(--bui-space-1_5)}.bui-MenuItem{height:2rem;padding-inline:var(--bui-space-2);border-radius:var(--bui-radius-2);cursor:default;color:var(--bui-fg-primary);font-size:var(--bui-font-size-3);justify-content:space-between;align-items:center;gap:var(--bui-space-6);outline:none;display:flex;&[data-focused],&[data-open]{background:var(--bui-bg-surface-2);color:var(--bui-fg-primary)}&[data-color=danger]{color:var(--bui-fg-danger)}&[data-color=danger][data-focused]{background:var(--bui-bg-danger);color:var(--bui-fg-danger)}&[data-has-submenu]{&>.bui-MenuItemArrow{display:block}}}.bui-MenuItemListBox{height:2rem;padding-inline:var(--bui-space-2);border-radius:var(--bui-radius-2);cursor:default;color:var(--bui-fg-primary);font-size:var(--bui-font-size-3);justify-content:space-between;align-items:center;gap:var(--bui-space-6);outline:none;display:flex;&:hover{background:var(--bui-bg-surface-2);color:var(--bui-fg-primary)}&[data-selected] .bui-MenuItemListBoxCheck{&>svg{opacity:1;color:var(--bui-fg-primary)}}}.bui-MenuItemListBoxCheck{justify-content:center;align-items:center;width:1rem;height:1rem;display:flex;&>svg{opacity:0;width:1rem;height:1rem}}.bui-MenuItemContent{align-items:center;gap:var(--bui-space-2);display:flex;&>svg{width:1rem;height:1rem}}.bui-MenuItemArrow{width:1rem;height:1rem;display:none;&>svg{width:1rem;height:1rem}}.bui-MenuSection{&:first-child .bui-MenuSectionHeader{padding-top:0}}.bui-MenuSectionHeader{height:2rem;padding-top:var(--bui-space-3);padding-left:var(--bui-space-2);color:var(--bui-fg-primary);font-size:var(--bui-font-size-1);letter-spacing:.05rem;text-transform:uppercase;align-items:center;font-weight:700;display:flex}.bui-MenuSeparator{background:var(--bui-border);height:1px;margin-inline:var(--bui-space-1_5);margin-block:var(--bui-space-1)}.bui-MenuSearchField{font-family:var(--bui-font-regular);flex-shrink:0;width:100%;position:relative;&[data-empty]{& .bui-MenuSearchFieldClear{display:none}}}.bui-MenuSearchFieldInput{padding:0 var(--bui-space-3);border:none;border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);width:100%;height:2rem;cursor:inherit;outline:none;align-items:center;display:flex;&::-webkit-search-cancel-button,&::-webkit-search-decoration{-webkit-appearance:none}}.bui-MenuSearchFieldClear{right:var(--bui-space-2);cursor:pointer;color:var(--bui-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;&>svg{width:1rem;height:1rem}}.bui-MenuEmptyState{padding:var(--bui-space-1);color:var(--bui-fg-secondary);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular)}.bui-Popover{background-color:var(--bui-bg-surface-1);border:1px solid var(--bui-border);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-1);margin-right:12px;overflow:scroll;box-shadow:0 4px 12px #0000001a}.bui-RadioGroup{color:var(--bui-fg-primary);flex-direction:column;display:flex}.bui-RadioGroup[data-orientation=horizontal] .bui-RadioGroupContent{gap:var(--bui-space-4);flex-direction:row}.bui-RadioGroupContent{gap:var(--bui-space-2);flex-direction:column;display:flex}.bui-Radio{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-2);color:var(--bui-fg-primary);forced-color-adjust:none;display:flex;position:relative;&:before{content:"";box-sizing:border-box;border:.125rem solid var(--bui-border);background:var(--bui-gray-1);border-radius:var(--bui-radius-full);width:1rem;height:1rem;transition:all .2s;display:block}&[data-pressed]:before{border-color:var(--bui-border)}&[data-selected]{&:before{border-color:var(--bui-bg-solid);border-width:.25rem}&[data-pressed]:before{border-color:var(--bui-bg-solid)}}&[data-focus-visible]:before{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}&[data-invalid]:before,&[data-invalid][data-selected]:before{border-color:var(--bui-border-danger)}&[data-disabled][data-invalid]{color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}}.bui-Table{caption-side:bottom;border-collapse:collapse;width:100%}.bui-TableHeader{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out}.bui-TableHead{text-align:left;padding:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary)}.bui-TableHeadSortButton{cursor:pointer;user-select:none;align-items:center;gap:var(--bui-space-1);display:inline-flex;&:hover svg{opacity:.5}& svg{opacity:0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}&[data-sort-order=asc] svg{opacity:1;transform:rotate(0)}&[data-sort-order=desc] svg{opacity:1;transform:rotate(180deg)}}.bui-TableBody{color:var(--bui-fg-primary)}.bui-TableRow{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out;&[data-react-aria-pressable=true]{cursor:pointer}}.bui-TableBody .bui-TableRow:hover{background-color:var(--bui-gray-2)}.bui-TableCell{padding:var(--bui-space-3);font-size:var(--bui-font-size-3);padding:var(--bui-space-3);font-size:var(--bui-font-size-3)}.bui-TableCellContentWrapper{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:inline-flex}.bui-TableCellIcon,.bui-TableCellIcon svg{color:var(--bui-fg-primary);align-items:center;display:inline-flex}.bui-TableCellContent{gap:var(--bui-space-0_5);flex-direction:column;display:flex}.bui-TableCellProfile{gap:var(--bui-space-2);flex-direction:row;align-items:center;display:flex}.bui-TableCellProfileAvatar{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-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}.bui-TableCellProfileAvatarImage{object-fit:cover;width:100%;height:100%}.bui-TableCellProfileAvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-DataTablePagination{padding-top:var(--bui-space-5);justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--left{justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--right{justify-content:space-between;align-items:center;gap:var(--bui-space-2);display:flex}.bui-DataTablePagination--select{min-width:10.5rem}.bui-Tabs{--active-tab-left:0px;--active-tab-right:0px;--active-tab-top:0px;--active-tab-bottom:0px;--active-tab-width:0px;--active-tab-height:0px;--active-transition-duration:0s;--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}.bui-TabList{flex-direction:row;display:flex}.bui-TabListWrapper{position:relative}.bui-Tab{font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-secondary);cursor:pointer;z-index:2;height:36px;padding-inline:var(--bui-space-2);justify-content:center;align-items:center;display:flex;position:relative;&[data-selected=true]{color:var(--bui-fg-primary)}}.bui-TabActive{content:"";left:calc(var(--active-tab-left) + var(--bui-space-2));width:calc(var(--active-tab-width) - var(--bui-space-4));background-color:var(--bui-fg-primary);height:1px;transition:left var(--active-transition-duration)ease-out,opacity .15s ease-out,width var(--active-transition-duration)ease-out;opacity:1;border-radius:4px;position:absolute;bottom:-1px}.bui-TabHovered{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(--bui-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}.bui-TabPanel{padding-inline:var(--bui-space-2);padding-top:var(--bui-space-4)}.bui-TagList{gap:var(--bui-space-2);flex-wrap:wrap;display:flex}.bui-Tag{color:var(--bui-fg-primary);background-color:var(--bui-gray-2);border-radius:var(--bui-radius-2);font-weight:var(--bui-font-weight-regular);justify-content:center;align-items:center;gap:var(--bui-space-1);box-sizing:border-box;transition-property:background-color,box-shadow,color;transition-duration:.2s;transition-timing-function:ease-in-out;display:flex}.bui-Tag[data-size=small]{height:26px;padding:0 var(--bui-space-2);font-size:var(--bui-font-size-1)}.bui-Tag[data-size=medium]{height:32px;padding:0 var(--bui-space-2);font-size:var(--bui-font-size-2)}.bui-Tag[data-hovered]{background-color:var(--bui-gray-3);cursor:pointer}.bui-Tag[data-focus-visible]{outline:2px solid var(--bui-ring);outline-offset:1px}.bui-Tag[data-selected]{box-shadow:inset 0 0 0 1px var(--bui-gray-8)}.bui-Tag[data-disabled]{color:var(--bui-fg-disabled);cursor:not-allowed}.bui-TagRemoveButton{cursor:pointer;color:var(--bui-fg-primary);background-color:#0000;border:none;width:1rem;height:1rem;margin:0;padding:0}.bui-TagIcon{justify-content:center;align-items:center;transition:color .2s ease-in-out;display:flex;& svg{width:1rem;height:1rem}}.bui-Text{font-family:var(--bui-font-regular);margin:0;padding:0}.bui-Text[data-variant=title-large]{font-size:var(--bui-font-size-8);line-height:140%}.bui-Text[data-variant=title-medium]{font-size:var(--bui-font-size-7);line-height:140%}.bui-Text[data-variant=title-small]{font-size:var(--bui-font-size-6);line-height:140%}.bui-Text[data-variant=title-x-small]{font-size:var(--bui-font-size-5);line-height:140%}.bui-Text[data-variant=body-large]{font-size:var(--bui-font-size-4);line-height:140%}.bui-Text[data-variant=body-medium]{font-size:var(--bui-font-size-3);line-height:140%}.bui-Text[data-variant=body-small]{font-size:var(--bui-font-size-2);line-height:140%}.bui-Text[data-variant=body-x-small]{font-size:var(--bui-font-size-1);line-height:140%}.bui-Text[data-weight=regular]{font-weight:var(--bui-font-weight-regular)}.bui-Text[data-weight=bold]{font-weight:var(--bui-font-weight-bold)}.bui-Text[data-color=primary]{color:var(--bui-fg-primary)}.bui-Text[data-color=secondary]{color:var(--bui-fg-secondary)}.bui-Text[data-color=danger]{color:var(--bui-fg-danger)}.bui-Text[data-color=warning]{color:var(--bui-fg-warning)}.bui-Text[data-color=success]{color:var(--bui-fg-success)}.bui-Text[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bui-Text[data-as=span],.bui-Text[data-as=label],.bui-Text[data-as=strong],.bui-Text[data-as=em],.bui-Text[data-as=small]{display:inline-block}.bui-TextField{font-family:var(--bui-font-regular);flex-direction:column;flex-shrink:0;width:100%;display:flex}.bui-InputWrapper{position:relative;&[data-size=small] .bui-Input{height:2rem}&[data-size=medium] .bui-Input{height:2.5rem}&[data-size=small] .bui-Input[data-icon]{padding-left:var(--bui-space-8)}&[data-size=medium] .bui-Input[data-icon]{padding-left:var(--bui-space-9)}}.bui-InputIcon{left:var(--bui-space-3);margin-right:var(--bui-space-1);color:var(--bui-fg-primary);pointer-events:none;flex-shrink:0;transition:left .2s ease-in-out;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}}.bui-Input{padding:0 var(--bui-space-3);border-radius:var(--bui-radius-2);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-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(--bui-fg-secondary)}&[data-focused]{outline-color:var(--bui-border-pressed);outline-width:0}&[data-hovered]{border-color:var(--bui-border-hover)}&[data-focused]{border-color:var(--bui-border-pressed);outline-width:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-disabled]{opacity:.5;cursor:not-allowed;border:1px solid var(--bui-border-disabled)}}.bui-SearchField{&[data-empty]{& .bui-InputClear{display:none}}&[data-start-collapsed=true]{padding:0;transition:width .3s ease-in-out;&[data-collapsed=false]{cursor:pointer;&[data-size=medium]{width:2.5rem;height:2.5rem}&[data-size=small]{width:2rem;height:2rem}&[data-size=medium] .bui-Input{padding-left:0;&::placeholder{opacity:0}}&[data-size=small] .bui-Input{padding-left:0;&::placeholder{opacity:0}}&[data-size=small] .bui-InputIcon{left:var(--bui-space-2)}&[data-size=medium] .bui-InputIcon{left:10px}}}}.bui-InputClear{cursor:pointer;color:var(--bui-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}.bui-InputClear:hover{color:var(--bui-fg-primary)}.bui-InputClear[data-size=small]{width:2rem;height:2rem}.bui-InputClear[data-size=medium]{width:2.5rem;height:2.5rem}.bui-InputClear svg{width:1rem;height:1rem}.bui-Skeleton{animation:var(--bui-animate-pulse);background-color:var(--bui-bg-surface-2);border-radius:var(--bui-radius-2)}.bui-Skeleton[data-rounded=true]{border-radius:var(--bui-radius-full)}.bui-Tooltip{background:var(--bui-bg-surface-1);border:1px solid var(--bui-gray-3);forced-color-adjust:none;padding:var(--bui-space-2)var(--bui-space-3);max-width:240px;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);color:var(--bui-fg-primary);border-radius:4px;outline:none;transition:transform .2s,opacity .2s;transform:translate(0,0);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}--tooltip-offset:var(--bui-space-3)&[data-placement=top]{margin-bottom:var(--tooltip-offset);--origin:translateY(4px)}&[data-placement=right]{margin-left:var(--tooltip-offset);--origin:translateX(-4px)}&[data-placement=bottom]{margin-top:var(--tooltip-offset);--origin:translateY(-4px)}&[data-placement=left]{margin-right:var(--tooltip-offset);--origin:translateX(4px)}}.bui-TooltipArrow{& svg{display:block;& path:first-child{fill:var(--bui-bg-surface-1)}& path:nth-child(2){fill:var(--bui-gray-3)}--tooltip-arrow-overlap:-2px}&[data-placement=top] svg{margin-top:var(--tooltip-arrow-overlap)}&[data-placement=bottom] svg{margin-bottom:var(--tooltip-arrow-overlap);transform:rotate(180deg)}&[data-placement=right] svg{margin-right:var(--tooltip-arrow-overlap);transform:rotate(90deg)}&[data-placement=left] svg{margin-left:var(--tooltip-arrow-overlap);transform:rotate(-90deg)}}[data-theme=dark]{& .bui-Tooltip{background:var(--bui-bg-surface-2);box-shadow:none;border:1px solid var(--bui-gray-4)}& .bui-TooltipArrow{& svg path:first-child{fill:var(--bui-bg-surface-2)}& svg path:nth-child(2){fill:var(--bui-gray-4)}}}.bui-ScrollAreaRoot{box-sizing:border-box;width:100%}.bui-ScrollAreaViewport{overscroll-behavior:contain;height:100%}.bui-ScrollAreaContent{padding-block:.75rem;flex-direction:column;gap:1rem;padding-left:1rem;padding-right:1.5rem;display:flex}.bui-ScrollAreaScrollbar{background-color:var(--bui-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}}.bui-ScrollAreaThumb{border-radius:inherit;background-color:var(--bui-scrollbar-thumb);width:100%}.bui-Select[data-invalid]{& .bui-SelectTrigger{border-color:var(--bui-fg-danger)}}.bui-SelectTrigger{box-sizing:border-box;border-radius:var(--bui-radius-3);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);cursor:pointer;justify-content:space-between;align-items:center;gap:var(--bui-space-2);width:100%;display:flex;& svg{color:var(--bui-fg-secondary);flex-shrink:0}&[data-size=small]{height:2rem;padding-inline:var(--bui-space-3)}&[data-size=medium]{height:3rem;padding-inline:var(--bui-space-4)}&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium] svg{width:1.25rem;height:1.25rem}&::placeholder{color:var(--bui-fg-secondary)}&:hover{border-color:var(--bui-border-hover);transition:border-color .2s ease-in-out,outline-color .2s ease-in-out}&:focus-visible{border-color:var(--bui-border-pressed);outline:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-invalid]:hover,&[data-invalid]:focus-visible{border-width:2px}&[disabled]{cursor:not-allowed;border-color:var(--bui-border-disabled);color:var(--bui-fg-disabled)}&[disabled] .bui-SelectValue{color:var(--bui-fg-disabled)}&[data-popup-open] .bui-SelectIcon{transform:rotate(180deg)}}.bui-SelectValue{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);text-align:left;overflow:hidden;& .bui-SelectItemIndicator{display:none}&[disabled]{color:var(--bui-fg-disabled)}}.bui-SelectItem{width:var(--anchor-width);padding-block:var(--bui-space-2);padding-left:var(--bui-space-3);padding-right:var(--bui-space-4);color:var(--bui-fg-primary);border-radius:var(--bui-radius-3);cursor:pointer;user-select:none;font-size:var(--bui-font-size-3);align-items:center;gap:var(--bui-space-1);outline:none;grid-template-columns:1rem 1fr;grid-template-areas:"icon text";display:grid;position:relative;&[data-focused]{z-index:0;color:var(--bui-fg-primary);position:relative}&[data-focused]:before{content:"";z-index:-1;background-color:var(--bui-bg-tint-hover);border-radius:.25rem;position:absolute;inset-block:0;inset-inline:.25rem}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled)}&[data-selected] .bui-SelectItemIndicator{opacity:1}}.bui-SelectItemIndicator{opacity:0;grid-area:icon;justify-content:center;align-items:center;transition:opacity .2s ease-in-out;display:flex}.bui-SelectItemLabel{flex:1;grid-area:text}.bui-Switch{align-items:center;gap:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary);cursor:pointer;display:flex;position:relative;&[data-pressed] .bui-SwitchIndicator{&:before{background:var(--bui-fg-solid)}}&[data-selected]{& .bui-SwitchIndicator{background:var(--bui-bg-solid);&:before{background:var(--bui-fg-solid);transform:translate(100%)}}&[data-pressed]{& .indicator{background:var(--bui-gray-3)}}}&[data-focus-visible] .bui-SwitchIndicator{outline-offset:2px;outline:2px solid}}.bui-SwitchIndicator{background:var(--bui-gray-3);border:2px;border-radius:1.143rem;width:2rem;height:1.143rem;transition:all .2s;&:before{content:"";background:var(--bui-fg-solid);border-radius:16px;width:.857rem;height:.857rem;margin:.143rem;transition:all .2s;display:block}} \ No newline at end of file +@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}}.bui-p{padding:var(--p)}.bui-p-0\.5{padding:var(--bui-space-0_5)}.bui-p-1{padding:var(--bui-space-1)}.bui-p-1\.5{padding:var(--bui-space-1_5)}.bui-p-2{padding:var(--bui-space-2)}.bui-p-3{padding:var(--bui-space-3)}.bui-p-4{padding:var(--bui-space-4)}.bui-p-5{padding:var(--bui-space-5)}.bui-p-6{padding:var(--bui-space-6)}.bui-p-7{padding:var(--bui-space-7)}.bui-p-8{padding:var(--bui-space-8)}.bui-p-9{padding:var(--bui-space-9)}.bui-p-10{padding:var(--bui-space-10)}.bui-p-11{padding:var(--bui-space-11)}.bui-p-12{padding:var(--bui-space-12)}.bui-p-13{padding:var(--bui-space-13)}.bui-p-14{padding:var(--bui-space-14)}@media (width>=640px){.xs\:bui-p{padding:var(--p-xs)}.xs\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xs\:bui-p-1{padding:var(--bui-space-1)}.xs\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xs\:bui-p-2{padding:var(--bui-space-2)}.xs\:bui-p-3{padding:var(--bui-space-3)}.xs\:bui-p-4{padding:var(--bui-space-4)}.xs\:bui-p-5{padding:var(--bui-space-5)}.xs\:bui-p-6{padding:var(--bui-space-6)}.xs\:bui-p-7{padding:var(--bui-space-7)}.xs\:bui-p-8{padding:var(--bui-space-8)}.xs\:bui-p-9{padding:var(--bui-space-9)}.xs\:bui-p-10{padding:var(--bui-space-10)}.xs\:bui-p-11{padding:var(--bui-space-11)}.xs\:bui-p-12{padding:var(--bui-space-12)}.xs\:bui-p-13{padding:var(--bui-space-13)}.xs\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-p{padding:var(--p-sm)}.sm\:bui-p-0\.5{padding:var(--bui-space-0_5)}.sm\:bui-p-1{padding:var(--bui-space-1)}.sm\:bui-p-1\.5{padding:var(--bui-space-1_5)}.sm\:bui-p-2{padding:var(--bui-space-2)}.sm\:bui-p-3{padding:var(--bui-space-3)}.sm\:bui-p-4{padding:var(--bui-space-4)}.sm\:bui-p-5{padding:var(--bui-space-5)}.sm\:bui-p-6{padding:var(--bui-space-6)}.sm\:bui-p-7{padding:var(--bui-space-7)}.sm\:bui-p-8{padding:var(--bui-space-8)}.sm\:bui-p-9{padding:var(--bui-space-9)}.sm\:bui-p-10{padding:var(--bui-space-10)}.sm\:bui-p-11{padding:var(--bui-space-11)}.sm\:bui-p-12{padding:var(--bui-space-12)}.sm\:bui-p-13{padding:var(--bui-space-13)}.sm\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-p{padding:var(--p-md)}.md\:bui-p-0\.5{padding:var(--bui-space-0_5)}.md\:bui-p-1{padding:var(--bui-space-1)}.md\:bui-p-1\.5{padding:var(--bui-space-1_5)}.md\:bui-p-2{padding:var(--bui-space-2)}.md\:bui-p-3{padding:var(--bui-space-3)}.md\:bui-p-4{padding:var(--bui-space-4)}.md\:bui-p-5{padding:var(--bui-space-5)}.md\:bui-p-6{padding:var(--bui-space-6)}.md\:bui-p-7{padding:var(--bui-space-7)}.md\:bui-p-8{padding:var(--bui-space-8)}.md\:bui-p-9{padding:var(--bui-space-9)}.md\:bui-p-10{padding:var(--bui-space-10)}.md\:bui-p-11{padding:var(--bui-space-11)}.md\:bui-p-12{padding:var(--bui-space-12)}.md\:bui-p-13{padding:var(--bui-space-13)}.md\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-p{padding:var(--p-lg)}.lg\:bui-p-0\.5{padding:var(--bui-space-0_5)}.lg\:bui-p-1{padding:var(--bui-space-1)}.lg\:bui-p-1\.5{padding:var(--bui-space-1_5)}.lg\:bui-p-2{padding:var(--bui-space-2)}.lg\:bui-p-3{padding:var(--bui-space-3)}.lg\:bui-p-4{padding:var(--bui-space-4)}.lg\:bui-p-5{padding:var(--bui-space-5)}.lg\:bui-p-6{padding:var(--bui-space-6)}.lg\:bui-p-7{padding:var(--bui-space-7)}.lg\:bui-p-8{padding:var(--bui-space-8)}.lg\:bui-p-9{padding:var(--bui-space-9)}.lg\:bui-p-10{padding:var(--bui-space-10)}.lg\:bui-p-11{padding:var(--bui-space-11)}.lg\:bui-p-12{padding:var(--bui-space-12)}.lg\:bui-p-13{padding:var(--bui-space-13)}.lg\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-p{padding:var(--p-xl)}.xl\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xl\:bui-p-1{padding:var(--bui-space-1)}.xl\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xl\:bui-p-2{padding:var(--bui-space-2)}.xl\:bui-p-3{padding:var(--bui-space-3)}.xl\:bui-p-4{padding:var(--bui-space-4)}.xl\:bui-p-5{padding:var(--bui-space-5)}.xl\:bui-p-6{padding:var(--bui-space-6)}.xl\:bui-p-7{padding:var(--bui-space-7)}.xl\:bui-p-8{padding:var(--bui-space-8)}.xl\:bui-p-9{padding:var(--bui-space-9)}.xl\:bui-p-10{padding:var(--bui-space-10)}.xl\:bui-p-11{padding:var(--bui-space-11)}.xl\:bui-p-12{padding:var(--bui-space-12)}.xl\:bui-p-13{padding:var(--bui-space-13)}.xl\:bui-p-14{padding:var(--bui-space-14)}}.bui-pl{padding-left:var(--pl)}.bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.bui-pl-1{padding-left:var(--bui-space-1)}.bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.bui-pl-2{padding-left:var(--bui-space-2)}.bui-pl-3{padding-left:var(--bui-space-3)}.bui-pl-4{padding-left:var(--bui-space-4)}.bui-pl-5{padding-left:var(--bui-space-5)}.bui-pl-6{padding-left:var(--bui-space-6)}.bui-pl-7{padding-left:var(--bui-space-7)}.bui-pl-8{padding-left:var(--bui-space-8)}.bui-pl-9{padding-left:var(--bui-space-9)}.bui-pl-10{padding-left:var(--bui-space-10)}.bui-pl-11{padding-left:var(--bui-space-11)}.bui-pl-12{padding-left:var(--bui-space-12)}.bui-pl-13{padding-left:var(--bui-space-13)}.bui-pl-14{padding-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pl{padding-left:var(--pl-xs)}.xs\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xs\:bui-pl-1{padding-left:var(--bui-space-1)}.xs\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xs\:bui-pl-2{padding-left:var(--bui-space-2)}.xs\:bui-pl-3{padding-left:var(--bui-space-3)}.xs\:bui-pl-4{padding-left:var(--bui-space-4)}.xs\:bui-pl-5{padding-left:var(--bui-space-5)}.xs\:bui-pl-6{padding-left:var(--bui-space-6)}.xs\:bui-pl-7{padding-left:var(--bui-space-7)}.xs\:bui-pl-8{padding-left:var(--bui-space-8)}.xs\:bui-pl-9{padding-left:var(--bui-space-9)}.xs\:bui-pl-10{padding-left:var(--bui-space-10)}.xs\:bui-pl-11{padding-left:var(--bui-space-11)}.xs\:bui-pl-12{padding-left:var(--bui-space-12)}.xs\:bui-pl-13{padding-left:var(--bui-space-13)}.xs\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pl{padding-left:var(--pl-sm)}.sm\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.sm\:bui-pl-1{padding-left:var(--bui-space-1)}.sm\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.sm\:bui-pl-2{padding-left:var(--bui-space-2)}.sm\:bui-pl-3{padding-left:var(--bui-space-3)}.sm\:bui-pl-4{padding-left:var(--bui-space-4)}.sm\:bui-pl-5{padding-left:var(--bui-space-5)}.sm\:bui-pl-6{padding-left:var(--bui-space-6)}.sm\:bui-pl-7{padding-left:var(--bui-space-7)}.sm\:bui-pl-8{padding-left:var(--bui-space-8)}.sm\:bui-pl-9{padding-left:var(--bui-space-9)}.sm\:bui-pl-10{padding-left:var(--bui-space-10)}.sm\:bui-pl-11{padding-left:var(--bui-space-11)}.sm\:bui-pl-12{padding-left:var(--bui-space-12)}.sm\:bui-pl-13{padding-left:var(--bui-space-13)}.sm\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pl{padding-left:var(--pl-md)}.md\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.md\:bui-pl-1{padding-left:var(--bui-space-1)}.md\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.md\:bui-pl-2{padding-left:var(--bui-space-2)}.md\:bui-pl-3{padding-left:var(--bui-space-3)}.md\:bui-pl-4{padding-left:var(--bui-space-4)}.md\:bui-pl-5{padding-left:var(--bui-space-5)}.md\:bui-pl-6{padding-left:var(--bui-space-6)}.md\:bui-pl-7{padding-left:var(--bui-space-7)}.md\:bui-pl-8{padding-left:var(--bui-space-8)}.md\:bui-pl-9{padding-left:var(--bui-space-9)}.md\:bui-pl-10{padding-left:var(--bui-space-10)}.md\:bui-pl-11{padding-left:var(--bui-space-11)}.md\:bui-pl-12{padding-left:var(--bui-space-12)}.md\:bui-pl-13{padding-left:var(--bui-space-13)}.md\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pl{padding-left:var(--pl-lg)}.lg\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.lg\:bui-pl-1{padding-left:var(--bui-space-1)}.lg\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.lg\:bui-pl-2{padding-left:var(--bui-space-2)}.lg\:bui-pl-3{padding-left:var(--bui-space-3)}.lg\:bui-pl-4{padding-left:var(--bui-space-4)}.lg\:bui-pl-5{padding-left:var(--bui-space-5)}.lg\:bui-pl-6{padding-left:var(--bui-space-6)}.lg\:bui-pl-7{padding-left:var(--bui-space-7)}.lg\:bui-pl-8{padding-left:var(--bui-space-8)}.lg\:bui-pl-9{padding-left:var(--bui-space-9)}.lg\:bui-pl-10{padding-left:var(--bui-space-10)}.lg\:bui-pl-11{padding-left:var(--bui-space-11)}.lg\:bui-pl-12{padding-left:var(--bui-space-12)}.lg\:bui-pl-13{padding-left:var(--bui-space-13)}.lg\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pl{padding-left:var(--pl-xl)}.xl\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xl\:bui-pl-1{padding-left:var(--bui-space-1)}.xl\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xl\:bui-pl-2{padding-left:var(--bui-space-2)}.xl\:bui-pl-3{padding-left:var(--bui-space-3)}.xl\:bui-pl-4{padding-left:var(--bui-space-4)}.xl\:bui-pl-5{padding-left:var(--bui-space-5)}.xl\:bui-pl-6{padding-left:var(--bui-space-6)}.xl\:bui-pl-7{padding-left:var(--bui-space-7)}.xl\:bui-pl-8{padding-left:var(--bui-space-8)}.xl\:bui-pl-9{padding-left:var(--bui-space-9)}.xl\:bui-pl-10{padding-left:var(--bui-space-10)}.xl\:bui-pl-11{padding-left:var(--bui-space-11)}.xl\:bui-pl-12{padding-left:var(--bui-space-12)}.xl\:bui-pl-13{padding-left:var(--bui-space-13)}.xl\:bui-pl-14{padding-left:var(--bui-space-14)}}.bui-pr{padding-right:var(--pr)}.bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.bui-pr-1{padding-right:var(--bui-space-1)}.bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.bui-pr-2{padding-right:var(--bui-space-2)}.bui-pr-3{padding-right:var(--bui-space-3)}.bui-pr-4{padding-right:var(--bui-space-4)}.bui-pr-5{padding-right:var(--bui-space-5)}.bui-pr-6{padding-right:var(--bui-space-6)}.bui-pr-7{padding-right:var(--bui-space-7)}.bui-pr-8{padding-right:var(--bui-space-8)}.bui-pr-9{padding-right:var(--bui-space-9)}.bui-pr-10{padding-right:var(--bui-space-10)}.bui-pr-11{padding-right:var(--bui-space-11)}.bui-pr-12{padding-right:var(--bui-space-12)}.bui-pr-13{padding-right:var(--bui-space-13)}.bui-pr-14{padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pr{padding-right:var(--pr-xs)}.xs\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xs\:bui-pr-1{padding-right:var(--bui-space-1)}.xs\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xs\:bui-pr-2{padding-right:var(--bui-space-2)}.xs\:bui-pr-3{padding-right:var(--bui-space-3)}.xs\:bui-pr-4{padding-right:var(--bui-space-4)}.xs\:bui-pr-5{padding-right:var(--bui-space-5)}.xs\:bui-pr-6{padding-right:var(--bui-space-6)}.xs\:bui-pr-7{padding-right:var(--bui-space-7)}.xs\:bui-pr-8{padding-right:var(--bui-space-8)}.xs\:bui-pr-9{padding-right:var(--bui-space-9)}.xs\:bui-pr-10{padding-right:var(--bui-space-10)}.xs\:bui-pr-11{padding-right:var(--bui-space-11)}.xs\:bui-pr-12{padding-right:var(--bui-space-12)}.xs\:bui-pr-13{padding-right:var(--bui-space-13)}.xs\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pr{padding-right:var(--pr-sm)}.sm\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.sm\:bui-pr-1{padding-right:var(--bui-space-1)}.sm\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.sm\:bui-pr-2{padding-right:var(--bui-space-2)}.sm\:bui-pr-3{padding-right:var(--bui-space-3)}.sm\:bui-pr-4{padding-right:var(--bui-space-4)}.sm\:bui-pr-5{padding-right:var(--bui-space-5)}.sm\:bui-pr-6{padding-right:var(--bui-space-6)}.sm\:bui-pr-7{padding-right:var(--bui-space-7)}.sm\:bui-pr-8{padding-right:var(--bui-space-8)}.sm\:bui-pr-9{padding-right:var(--bui-space-9)}.sm\:bui-pr-10{padding-right:var(--bui-space-10)}.sm\:bui-pr-11{padding-right:var(--bui-space-11)}.sm\:bui-pr-12{padding-right:var(--bui-space-12)}.sm\:bui-pr-13{padding-right:var(--bui-space-13)}.sm\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pr{padding-right:var(--pr-md)}.md\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.md\:bui-pr-1{padding-right:var(--bui-space-1)}.md\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.md\:bui-pr-2{padding-right:var(--bui-space-2)}.md\:bui-pr-3{padding-right:var(--bui-space-3)}.md\:bui-pr-4{padding-right:var(--bui-space-4)}.md\:bui-pr-5{padding-right:var(--bui-space-5)}.md\:bui-pr-6{padding-right:var(--bui-space-6)}.md\:bui-pr-7{padding-right:var(--bui-space-7)}.md\:bui-pr-8{padding-right:var(--bui-space-8)}.md\:bui-pr-9{padding-right:var(--bui-space-9)}.md\:bui-pr-10{padding-right:var(--bui-space-10)}.md\:bui-pr-11{padding-right:var(--bui-space-11)}.md\:bui-pr-12{padding-right:var(--bui-space-12)}.md\:bui-pr-13{padding-right:var(--bui-space-13)}.md\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pr{padding-right:var(--pr-lg)}.lg\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.lg\:bui-pr-1{padding-right:var(--bui-space-1)}.lg\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.lg\:bui-pr-2{padding-right:var(--bui-space-2)}.lg\:bui-pr-3{padding-right:var(--bui-space-3)}.lg\:bui-pr-4{padding-right:var(--bui-space-4)}.lg\:bui-pr-5{padding-right:var(--bui-space-5)}.lg\:bui-pr-6{padding-right:var(--bui-space-6)}.lg\:bui-pr-7{padding-right:var(--bui-space-7)}.lg\:bui-pr-8{padding-right:var(--bui-space-8)}.lg\:bui-pr-9{padding-right:var(--bui-space-9)}.lg\:bui-pr-10{padding-right:var(--bui-space-10)}.lg\:bui-pr-11{padding-right:var(--bui-space-11)}.lg\:bui-pr-12{padding-right:var(--bui-space-12)}.lg\:bui-pr-13{padding-right:var(--bui-space-13)}.lg\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pr{padding-right:var(--pr-xl)}.xl\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xl\:bui-pr-1{padding-right:var(--bui-space-1)}.xl\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xl\:bui-pr-2{padding-right:var(--bui-space-2)}.xl\:bui-pr-3{padding-right:var(--bui-space-3)}.xl\:bui-pr-4{padding-right:var(--bui-space-4)}.xl\:bui-pr-5{padding-right:var(--bui-space-5)}.xl\:bui-pr-6{padding-right:var(--bui-space-6)}.xl\:bui-pr-7{padding-right:var(--bui-space-7)}.xl\:bui-pr-8{padding-right:var(--bui-space-8)}.xl\:bui-pr-9{padding-right:var(--bui-space-9)}.xl\:bui-pr-10{padding-right:var(--bui-space-10)}.xl\:bui-pr-11{padding-right:var(--bui-space-11)}.xl\:bui-pr-12{padding-right:var(--bui-space-12)}.xl\:bui-pr-13{padding-right:var(--bui-space-13)}.xl\:bui-pr-14{padding-right:var(--bui-space-14)}}.bui-pt{padding-top:var(--pt)}.bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.bui-pt-1{padding-top:var(--bui-space-1)}.bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.bui-pt-2{padding-top:var(--bui-space-2)}.bui-pt-3{padding-top:var(--bui-space-3)}.bui-pt-4{padding-top:var(--bui-space-4)}.bui-pt-5{padding-top:var(--bui-space-5)}.bui-pt-6{padding-top:var(--bui-space-6)}.bui-pt-7{padding-top:var(--bui-space-7)}.bui-pt-8{padding-top:var(--bui-space-8)}.bui-pt-9{padding-top:var(--bui-space-9)}.bui-pt-10{padding-top:var(--bui-space-10)}.bui-pt-11{padding-top:var(--bui-space-11)}.bui-pt-12{padding-top:var(--bui-space-12)}.bui-pt-13{padding-top:var(--bui-space-13)}.bui-pt-14{padding-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pt{padding-top:var(--pt-xs)}.xs\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xs\:bui-pt-1{padding-top:var(--bui-space-1)}.xs\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xs\:bui-pt-2{padding-top:var(--bui-space-2)}.xs\:bui-pt-3{padding-top:var(--bui-space-3)}.xs\:bui-pt-4{padding-top:var(--bui-space-4)}.xs\:bui-pt-5{padding-top:var(--bui-space-5)}.xs\:bui-pt-6{padding-top:var(--bui-space-6)}.xs\:bui-pt-7{padding-top:var(--bui-space-7)}.xs\:bui-pt-8{padding-top:var(--bui-space-8)}.xs\:bui-pt-9{padding-top:var(--bui-space-9)}.xs\:bui-pt-10{padding-top:var(--bui-space-10)}.xs\:bui-pt-11{padding-top:var(--bui-space-11)}.xs\:bui-pt-12{padding-top:var(--bui-space-12)}.xs\:bui-pt-13{padding-top:var(--bui-space-13)}.xs\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pt{padding-top:var(--pt-sm)}.sm\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.sm\:bui-pt-1{padding-top:var(--bui-space-1)}.sm\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.sm\:bui-pt-2{padding-top:var(--bui-space-2)}.sm\:bui-pt-3{padding-top:var(--bui-space-3)}.sm\:bui-pt-4{padding-top:var(--bui-space-4)}.sm\:bui-pt-5{padding-top:var(--bui-space-5)}.sm\:bui-pt-6{padding-top:var(--bui-space-6)}.sm\:bui-pt-7{padding-top:var(--bui-space-7)}.sm\:bui-pt-8{padding-top:var(--bui-space-8)}.sm\:bui-pt-9{padding-top:var(--bui-space-9)}.sm\:bui-pt-10{padding-top:var(--bui-space-10)}.sm\:bui-pt-11{padding-top:var(--bui-space-11)}.sm\:bui-pt-12{padding-top:var(--bui-space-12)}.sm\:bui-pt-13{padding-top:var(--bui-space-13)}.sm\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pt{padding-top:var(--pt-md)}.md\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.md\:bui-pt-1{padding-top:var(--bui-space-1)}.md\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.md\:bui-pt-2{padding-top:var(--bui-space-2)}.md\:bui-pt-3{padding-top:var(--bui-space-3)}.md\:bui-pt-4{padding-top:var(--bui-space-4)}.md\:bui-pt-5{padding-top:var(--bui-space-5)}.md\:bui-pt-6{padding-top:var(--bui-space-6)}.md\:bui-pt-7{padding-top:var(--bui-space-7)}.md\:bui-pt-8{padding-top:var(--bui-space-8)}.md\:bui-pt-9{padding-top:var(--bui-space-9)}.md\:bui-pt-10{padding-top:var(--bui-space-10)}.md\:bui-pt-11{padding-top:var(--bui-space-11)}.md\:bui-pt-12{padding-top:var(--bui-space-12)}.md\:bui-pt-13{padding-top:var(--bui-space-13)}.md\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pt{padding-top:var(--pt-lg)}.lg\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.lg\:bui-pt-1{padding-top:var(--bui-space-1)}.lg\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.lg\:bui-pt-2{padding-top:var(--bui-space-2)}.lg\:bui-pt-3{padding-top:var(--bui-space-3)}.lg\:bui-pt-4{padding-top:var(--bui-space-4)}.lg\:bui-pt-5{padding-top:var(--bui-space-5)}.lg\:bui-pt-6{padding-top:var(--bui-space-6)}.lg\:bui-pt-7{padding-top:var(--bui-space-7)}.lg\:bui-pt-8{padding-top:var(--bui-space-8)}.lg\:bui-pt-9{padding-top:var(--bui-space-9)}.lg\:bui-pt-10{padding-top:var(--bui-space-10)}.lg\:bui-pt-11{padding-top:var(--bui-space-11)}.lg\:bui-pt-12{padding-top:var(--bui-space-12)}.lg\:bui-pt-13{padding-top:var(--bui-space-13)}.lg\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pt{padding-top:var(--pt-xl)}.xl\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xl\:bui-pt-1{padding-top:var(--bui-space-1)}.xl\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xl\:bui-pt-2{padding-top:var(--bui-space-2)}.xl\:bui-pt-3{padding-top:var(--bui-space-3)}.xl\:bui-pt-4{padding-top:var(--bui-space-4)}.xl\:bui-pt-5{padding-top:var(--bui-space-5)}.xl\:bui-pt-6{padding-top:var(--bui-space-6)}.xl\:bui-pt-7{padding-top:var(--bui-space-7)}.xl\:bui-pt-8{padding-top:var(--bui-space-8)}.xl\:bui-pt-9{padding-top:var(--bui-space-9)}.xl\:bui-pt-10{padding-top:var(--bui-space-10)}.xl\:bui-pt-11{padding-top:var(--bui-space-11)}.xl\:bui-pt-12{padding-top:var(--bui-space-12)}.xl\:bui-pt-13{padding-top:var(--bui-space-13)}.xl\:bui-pt-14{padding-top:var(--bui-space-14)}}.bui-pb{padding-bottom:var(--pb)}.bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.bui-pb-1{padding-bottom:var(--bui-space-1)}.bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.bui-pb-2{padding-bottom:var(--bui-space-2)}.bui-pb-3{padding-bottom:var(--bui-space-3)}.bui-pb-4{padding-bottom:var(--bui-space-4)}.bui-pb-5{padding-bottom:var(--bui-space-5)}.bui-pb-6{padding-bottom:var(--bui-space-6)}.bui-pb-7{padding-bottom:var(--bui-space-7)}.bui-pb-8{padding-bottom:var(--bui-space-8)}.bui-pb-9{padding-bottom:var(--bui-space-9)}.bui-pb-10{padding-bottom:var(--bui-space-10)}.bui-pb-11{padding-bottom:var(--bui-space-11)}.bui-pb-12{padding-bottom:var(--bui-space-12)}.bui-pb-13{padding-bottom:var(--bui-space-13)}.bui-pb-14{padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pb{padding-bottom:var(--pb-xs)}.xs\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xs\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xs\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xs\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xs\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xs\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xs\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xs\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xs\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xs\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xs\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xs\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xs\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xs\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xs\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xs\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pb{padding-bottom:var(--pb-sm)}.sm\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.sm\:bui-pb-1{padding-bottom:var(--bui-space-1)}.sm\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.sm\:bui-pb-2{padding-bottom:var(--bui-space-2)}.sm\:bui-pb-3{padding-bottom:var(--bui-space-3)}.sm\:bui-pb-4{padding-bottom:var(--bui-space-4)}.sm\:bui-pb-5{padding-bottom:var(--bui-space-5)}.sm\:bui-pb-6{padding-bottom:var(--bui-space-6)}.sm\:bui-pb-7{padding-bottom:var(--bui-space-7)}.sm\:bui-pb-8{padding-bottom:var(--bui-space-8)}.sm\:bui-pb-9{padding-bottom:var(--bui-space-9)}.sm\:bui-pb-10{padding-bottom:var(--bui-space-10)}.sm\:bui-pb-11{padding-bottom:var(--bui-space-11)}.sm\:bui-pb-12{padding-bottom:var(--bui-space-12)}.sm\:bui-pb-13{padding-bottom:var(--bui-space-13)}.sm\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pb{padding-bottom:var(--pb-md)}.md\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.md\:bui-pb-1{padding-bottom:var(--bui-space-1)}.md\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.md\:bui-pb-2{padding-bottom:var(--bui-space-2)}.md\:bui-pb-3{padding-bottom:var(--bui-space-3)}.md\:bui-pb-4{padding-bottom:var(--bui-space-4)}.md\:bui-pb-5{padding-bottom:var(--bui-space-5)}.md\:bui-pb-6{padding-bottom:var(--bui-space-6)}.md\:bui-pb-7{padding-bottom:var(--bui-space-7)}.md\:bui-pb-8{padding-bottom:var(--bui-space-8)}.md\:bui-pb-9{padding-bottom:var(--bui-space-9)}.md\:bui-pb-10{padding-bottom:var(--bui-space-10)}.md\:bui-pb-11{padding-bottom:var(--bui-space-11)}.md\:bui-pb-12{padding-bottom:var(--bui-space-12)}.md\:bui-pb-13{padding-bottom:var(--bui-space-13)}.md\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pb{padding-bottom:var(--pb-lg)}.lg\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.lg\:bui-pb-1{padding-bottom:var(--bui-space-1)}.lg\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.lg\:bui-pb-2{padding-bottom:var(--bui-space-2)}.lg\:bui-pb-3{padding-bottom:var(--bui-space-3)}.lg\:bui-pb-4{padding-bottom:var(--bui-space-4)}.lg\:bui-pb-5{padding-bottom:var(--bui-space-5)}.lg\:bui-pb-6{padding-bottom:var(--bui-space-6)}.lg\:bui-pb-7{padding-bottom:var(--bui-space-7)}.lg\:bui-pb-8{padding-bottom:var(--bui-space-8)}.lg\:bui-pb-9{padding-bottom:var(--bui-space-9)}.lg\:bui-pb-10{padding-bottom:var(--bui-space-10)}.lg\:bui-pb-11{padding-bottom:var(--bui-space-11)}.lg\:bui-pb-12{padding-bottom:var(--bui-space-12)}.lg\:bui-pb-13{padding-bottom:var(--bui-space-13)}.lg\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pb{padding-bottom:var(--pb-xl)}.xl\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xl\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xl\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xl\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xl\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xl\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xl\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xl\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xl\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xl\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xl\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xl\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xl\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xl\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xl\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xl\:bui-pb-14{padding-bottom:var(--bui-space-14)}}.bui-py{padding-top:var(--py);padding-bottom:var(--py)}.bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-py{padding-top:var(--py-xs);padding-bottom:var(--py-xs)}.xs\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xs\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xs\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xs\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xs\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xs\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xs\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xs\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xs\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xs\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xs\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xs\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xs\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xs\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xs\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xs\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-py{padding-top:var(--py-sm);padding-bottom:var(--py-sm)}.sm\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.sm\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.sm\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.sm\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.sm\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.sm\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.sm\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.sm\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.sm\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.sm\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.sm\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.sm\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.sm\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.sm\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.sm\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.sm\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-py{padding-top:var(--py-md);padding-bottom:var(--py-md)}.md\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.md\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.md\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.md\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.md\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.md\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.md\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.md\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.md\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.md\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.md\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.md\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.md\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.md\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.md\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.md\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-py{padding-top:var(--py-lg);padding-bottom:var(--py-lg)}.lg\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.lg\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.lg\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.lg\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.lg\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.lg\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.lg\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.lg\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.lg\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.lg\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.lg\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.lg\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.lg\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.lg\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.lg\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.lg\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-py{padding-top:var(--py-xl);padding-bottom:var(--py-xl)}.xl\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xl\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xl\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xl\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xl\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xl\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xl\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xl\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xl\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xl\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xl\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xl\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xl\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xl\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xl\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xl\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}.bui-px{padding-left:var(--px);padding-right:var(--px)}.bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-px{padding-left:var(--px-xs);padding-right:var(--px-xs)}.xs\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xs\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xs\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xs\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xs\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xs\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xs\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xs\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xs\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xs\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xs\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xs\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xs\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xs\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xs\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xs\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-px{padding-left:var(--px-sm);padding-right:var(--px-sm)}.sm\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.sm\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.sm\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.sm\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.sm\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.sm\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.sm\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.sm\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.sm\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.sm\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.sm\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.sm\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.sm\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.sm\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.sm\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.sm\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-px{padding-left:var(--px-md);padding-right:var(--px-md)}.md\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.md\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.md\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.md\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.md\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.md\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.md\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.md\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.md\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.md\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.md\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.md\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.md\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.md\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.md\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.md\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-px{padding-left:var(--px-lg);padding-right:var(--px-lg)}.lg\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.lg\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.lg\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.lg\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.lg\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.lg\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.lg\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.lg\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.lg\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.lg\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.lg\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.lg\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.lg\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.lg\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.lg\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.lg\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-px{padding-left:var(--px-xl);padding-right:var(--px-xl)}.xl\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xl\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xl\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xl\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xl\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xl\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xl\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xl\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xl\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xl\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xl\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xl\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xl\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xl\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xl\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xl\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}.bui-m{margin:var(--m)}.bui-m-0\.5{margin:var(--bui-space-0_5)}.bui-m-1{margin:var(--bui-space-1)}.bui-m-1\.5{margin:var(--bui-space-1_5)}.bui-m-2{margin:var(--bui-space-2)}.bui-m-3{margin:var(--bui-space-3)}.bui-m-4{margin:var(--bui-space-4)}.bui-m-5{margin:var(--bui-space-5)}.bui-m-6{margin:var(--bui-space-6)}.bui-m-7{margin:var(--bui-space-7)}.bui-m-8{margin:var(--bui-space-8)}.bui-m-9{margin:var(--bui-space-9)}.bui-m-10{margin:var(--bui-space-10)}.bui-m-11{margin:var(--bui-space-11)}.bui-m-12{margin:var(--bui-space-12)}.bui-m-13{margin:var(--bui-space-13)}.bui-m-14{margin:var(--bui-space-14)}@media (width>=640px){.xs\:bui-m{margin:var(--p-xs)}.xs\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xs\:bui-m-1{margin:var(--bui-space-1)}.xs\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xs\:bui-m-2{margin:var(--bui-space-2)}.xs\:bui-m-3{margin:var(--bui-space-3)}.xs\:bui-m-4{margin:var(--bui-space-4)}.xs\:bui-m-5{margin:var(--bui-space-5)}.xs\:bui-m-6{margin:var(--bui-space-6)}.xs\:bui-m-7{margin:var(--bui-space-7)}.xs\:bui-m-8{margin:var(--bui-space-8)}.xs\:bui-m-9{margin:var(--bui-space-9)}.xs\:bui-m-10{margin:var(--bui-space-10)}.xs\:bui-m-11{margin:var(--bui-space-11)}.xs\:bui-m-12{margin:var(--bui-space-12)}.xs\:bui-m-13{margin:var(--bui-space-13)}.xs\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-m{margin:var(--p-sm)}.sm\:bui-m-0\.5{margin:var(--bui-space-0_5)}.sm\:bui-m-1{margin:var(--bui-space-1)}.sm\:bui-m-1\.5{margin:var(--bui-space-1_5)}.sm\:bui-m-2{margin:var(--bui-space-2)}.sm\:bui-m-3{margin:var(--bui-space-3)}.sm\:bui-m-4{margin:var(--bui-space-4)}.sm\:bui-m-5{margin:var(--bui-space-5)}.sm\:bui-m-6{margin:var(--bui-space-6)}.sm\:bui-m-7{margin:var(--bui-space-7)}.sm\:bui-m-8{margin:var(--bui-space-8)}.sm\:bui-m-9{margin:var(--bui-space-9)}.sm\:bui-m-10{margin:var(--bui-space-10)}.sm\:bui-m-11{margin:var(--bui-space-11)}.sm\:bui-m-12{margin:var(--bui-space-12)}.sm\:bui-m-13{margin:var(--bui-space-13)}.sm\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-m{margin:var(--p-md)}.md\:bui-m-0\.5{margin:var(--bui-space-0_5)}.md\:bui-m-1{margin:var(--bui-space-1)}.md\:bui-m-1\.5{margin:var(--bui-space-1_5)}.md\:bui-m-2{margin:var(--bui-space-2)}.md\:bui-m-3{margin:var(--bui-space-3)}.md\:bui-m-4{margin:var(--bui-space-4)}.md\:bui-m-5{margin:var(--bui-space-5)}.md\:bui-m-6{margin:var(--bui-space-6)}.md\:bui-m-7{margin:var(--bui-space-7)}.md\:bui-m-8{margin:var(--bui-space-8)}.md\:bui-m-9{margin:var(--bui-space-9)}.md\:bui-m-10{margin:var(--bui-space-10)}.md\:bui-m-11{margin:var(--bui-space-11)}.md\:bui-m-12{margin:var(--bui-space-12)}.md\:bui-m-13{margin:var(--bui-space-13)}.md\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-m{margin:var(--p-lg)}.lg\:bui-m-0\.5{margin:var(--bui-space-0_5)}.lg\:bui-m-1{margin:var(--bui-space-1)}.lg\:bui-m-1\.5{margin:var(--bui-space-1_5)}.lg\:bui-m-2{margin:var(--bui-space-2)}.lg\:bui-m-3{margin:var(--bui-space-3)}.lg\:bui-m-4{margin:var(--bui-space-4)}.lg\:bui-m-5{margin:var(--bui-space-5)}.lg\:bui-m-6{margin:var(--bui-space-6)}.lg\:bui-m-7{margin:var(--bui-space-7)}.lg\:bui-m-8{margin:var(--bui-space-8)}.lg\:bui-m-9{margin:var(--bui-space-9)}.lg\:bui-m-10{margin:var(--bui-space-10)}.lg\:bui-m-11{margin:var(--bui-space-11)}.lg\:bui-m-12{margin:var(--bui-space-12)}.lg\:bui-m-13{margin:var(--bui-space-13)}.lg\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-m{margin:var(--p-xl)}.xl\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xl\:bui-m-1{margin:var(--bui-space-1)}.xl\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xl\:bui-m-2{margin:var(--bui-space-2)}.xl\:bui-m-3{margin:var(--bui-space-3)}.xl\:bui-m-4{margin:var(--bui-space-4)}.xl\:bui-m-5{margin:var(--bui-space-5)}.xl\:bui-m-6{margin:var(--bui-space-6)}.xl\:bui-m-7{margin:var(--bui-space-7)}.xl\:bui-m-8{margin:var(--bui-space-8)}.xl\:bui-m-9{margin:var(--bui-space-9)}.xl\:bui-m-10{margin:var(--bui-space-10)}.xl\:bui-m-11{margin:var(--bui-space-11)}.xl\:bui-m-12{margin:var(--bui-space-12)}.xl\:bui-m-13{margin:var(--bui-space-13)}.xl\:bui-m-14{margin:var(--bui-space-14)}}.bui-ml{margin-left:var(--ml)}.bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.bui-ml-1{margin-left:var(--bui-space-1)}.bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.bui-ml-2{margin-left:var(--bui-space-2)}.bui-ml-3{margin-left:var(--bui-space-3)}.bui-ml-4{margin-left:var(--bui-space-4)}.bui-ml-5{margin-left:var(--bui-space-5)}.bui-ml-6{margin-left:var(--bui-space-6)}.bui-ml-7{margin-left:var(--bui-space-7)}.bui-ml-8{margin-left:var(--bui-space-8)}.bui-ml-9{margin-left:var(--bui-space-9)}.bui-ml-10{margin-left:var(--bui-space-10)}.bui-ml-11{margin-left:var(--bui-space-11)}.bui-ml-12{margin-left:var(--bui-space-12)}.bui-ml-13{margin-left:var(--bui-space-13)}.bui-ml-14{margin-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-ml{margin-left:var(--pl-xs)}.xs\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xs\:bui-ml-1{margin-left:var(--bui-space-1)}.xs\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xs\:bui-ml-2{margin-left:var(--bui-space-2)}.xs\:bui-ml-3{margin-left:var(--bui-space-3)}.xs\:bui-ml-4{margin-left:var(--bui-space-4)}.xs\:bui-ml-5{margin-left:var(--bui-space-5)}.xs\:bui-ml-6{margin-left:var(--bui-space-6)}.xs\:bui-ml-7{margin-left:var(--bui-space-7)}.xs\:bui-ml-8{margin-left:var(--bui-space-8)}.xs\:bui-ml-9{margin-left:var(--bui-space-9)}.xs\:bui-ml-10{margin-left:var(--bui-space-10)}.xs\:bui-ml-11{margin-left:var(--bui-space-11)}.xs\:bui-ml-12{margin-left:var(--bui-space-12)}.xs\:bui-ml-13{margin-left:var(--bui-space-13)}.xs\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-ml{margin-left:var(--pl-sm)}.sm\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.sm\:bui-ml-1{margin-left:var(--bui-space-1)}.sm\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.sm\:bui-ml-2{margin-left:var(--bui-space-2)}.sm\:bui-ml-3{margin-left:var(--bui-space-3)}.sm\:bui-ml-4{margin-left:var(--bui-space-4)}.sm\:bui-ml-5{margin-left:var(--bui-space-5)}.sm\:bui-ml-6{margin-left:var(--bui-space-6)}.sm\:bui-ml-7{margin-left:var(--bui-space-7)}.sm\:bui-ml-8{margin-left:var(--bui-space-8)}.sm\:bui-ml-9{margin-left:var(--bui-space-9)}.sm\:bui-ml-10{margin-left:var(--bui-space-10)}.sm\:bui-ml-11{margin-left:var(--bui-space-11)}.sm\:bui-ml-12{margin-left:var(--bui-space-12)}.sm\:bui-ml-13{margin-left:var(--bui-space-13)}.sm\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-ml{margin-left:var(--pl-md)}.md\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.md\:bui-ml-1{margin-left:var(--bui-space-1)}.md\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.md\:bui-ml-2{margin-left:var(--bui-space-2)}.md\:bui-ml-3{margin-left:var(--bui-space-3)}.md\:bui-ml-4{margin-left:var(--bui-space-4)}.md\:bui-ml-5{margin-left:var(--bui-space-5)}.md\:bui-ml-6{margin-left:var(--bui-space-6)}.md\:bui-ml-7{margin-left:var(--bui-space-7)}.md\:bui-ml-8{margin-left:var(--bui-space-8)}.md\:bui-ml-9{margin-left:var(--bui-space-9)}.md\:bui-ml-10{margin-left:var(--bui-space-10)}.md\:bui-ml-11{margin-left:var(--bui-space-11)}.md\:bui-ml-12{margin-left:var(--bui-space-12)}.md\:bui-ml-13{margin-left:var(--bui-space-13)}.md\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-ml{margin-left:var(--pl-lg)}.lg\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.lg\:bui-ml-1{margin-left:var(--bui-space-1)}.lg\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.lg\:bui-ml-2{margin-left:var(--bui-space-2)}.lg\:bui-ml-3{margin-left:var(--bui-space-3)}.lg\:bui-ml-4{margin-left:var(--bui-space-4)}.lg\:bui-ml-5{margin-left:var(--bui-space-5)}.lg\:bui-ml-6{margin-left:var(--bui-space-6)}.lg\:bui-ml-7{margin-left:var(--bui-space-7)}.lg\:bui-ml-8{margin-left:var(--bui-space-8)}.lg\:bui-ml-9{margin-left:var(--bui-space-9)}.lg\:bui-ml-10{margin-left:var(--bui-space-10)}.lg\:bui-ml-11{margin-left:var(--bui-space-11)}.lg\:bui-ml-12{margin-left:var(--bui-space-12)}.lg\:bui-ml-13{margin-left:var(--bui-space-13)}.lg\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-ml{margin-left:var(--pl-xl)}.xl\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xl\:bui-ml-1{margin-left:var(--bui-space-1)}.xl\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xl\:bui-ml-2{margin-left:var(--bui-space-2)}.xl\:bui-ml-3{margin-left:var(--bui-space-3)}.xl\:bui-ml-4{margin-left:var(--bui-space-4)}.xl\:bui-ml-5{margin-left:var(--bui-space-5)}.xl\:bui-ml-6{margin-left:var(--bui-space-6)}.xl\:bui-ml-7{margin-left:var(--bui-space-7)}.xl\:bui-ml-8{margin-left:var(--bui-space-8)}.xl\:bui-ml-9{margin-left:var(--bui-space-9)}.xl\:bui-ml-10{margin-left:var(--bui-space-10)}.xl\:bui-ml-11{margin-left:var(--bui-space-11)}.xl\:bui-ml-12{margin-left:var(--bui-space-12)}.xl\:bui-ml-13{margin-left:var(--bui-space-13)}.xl\:bui-ml-14{margin-left:var(--bui-space-14)}}.bui-mr{margin-right:var(--mr)}.bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.bui-mr-1{margin-right:var(--bui-space-1)}.bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.bui-mr-2{margin-right:var(--bui-space-2)}.bui-mr-3{margin-right:var(--bui-space-3)}.bui-mr-4{margin-right:var(--bui-space-4)}.bui-mr-5{margin-right:var(--bui-space-5)}.bui-mr-6{margin-right:var(--bui-space-6)}.bui-mr-7{margin-right:var(--bui-space-7)}.bui-mr-8{margin-right:var(--bui-space-8)}.bui-mr-9{margin-right:var(--bui-space-9)}.bui-mr-10{margin-right:var(--bui-space-10)}.bui-mr-11{margin-right:var(--bui-space-11)}.bui-mr-12{margin-right:var(--bui-space-12)}.bui-mr-13{margin-right:var(--bui-space-13)}.bui-mr-14{margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mr{margin-right:var(--pr-xs)}.xs\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xs\:bui-mr-1{margin-right:var(--bui-space-1)}.xs\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xs\:bui-mr-2{margin-right:var(--bui-space-2)}.xs\:bui-mr-3{margin-right:var(--bui-space-3)}.xs\:bui-mr-4{margin-right:var(--bui-space-4)}.xs\:bui-mr-5{margin-right:var(--bui-space-5)}.xs\:bui-mr-6{margin-right:var(--bui-space-6)}.xs\:bui-mr-7{margin-right:var(--bui-space-7)}.xs\:bui-mr-8{margin-right:var(--bui-space-8)}.xs\:bui-mr-9{margin-right:var(--bui-space-9)}.xs\:bui-mr-10{margin-right:var(--bui-space-10)}.xs\:bui-mr-11{margin-right:var(--bui-space-11)}.xs\:bui-mr-12{margin-right:var(--bui-space-12)}.xs\:bui-mr-13{margin-right:var(--bui-space-13)}.xs\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mr{margin-right:var(--pr-sm)}.sm\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.sm\:bui-mr-1{margin-right:var(--bui-space-1)}.sm\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.sm\:bui-mr-2{margin-right:var(--bui-space-2)}.sm\:bui-mr-3{margin-right:var(--bui-space-3)}.sm\:bui-mr-4{margin-right:var(--bui-space-4)}.sm\:bui-mr-5{margin-right:var(--bui-space-5)}.sm\:bui-mr-6{margin-right:var(--bui-space-6)}.sm\:bui-mr-7{margin-right:var(--bui-space-7)}.sm\:bui-mr-8{margin-right:var(--bui-space-8)}.sm\:bui-mr-9{margin-right:var(--bui-space-9)}.sm\:bui-mr-10{margin-right:var(--bui-space-10)}.sm\:bui-mr-11{margin-right:var(--bui-space-11)}.sm\:bui-mr-12{margin-right:var(--bui-space-12)}.sm\:bui-mr-13{margin-right:var(--bui-space-13)}.sm\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mr{margin-right:var(--pr-md)}.md\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.md\:bui-mr-1{margin-right:var(--bui-space-1)}.md\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.md\:bui-mr-2{margin-right:var(--bui-space-2)}.md\:bui-mr-3{margin-right:var(--bui-space-3)}.md\:bui-mr-4{margin-right:var(--bui-space-4)}.md\:bui-mr-5{margin-right:var(--bui-space-5)}.md\:bui-mr-6{margin-right:var(--bui-space-6)}.md\:bui-mr-7{margin-right:var(--bui-space-7)}.md\:bui-mr-8{margin-right:var(--bui-space-8)}.md\:bui-mr-9{margin-right:var(--bui-space-9)}.md\:bui-mr-10{margin-right:var(--bui-space-10)}.md\:bui-mr-11{margin-right:var(--bui-space-11)}.md\:bui-mr-12{margin-right:var(--bui-space-12)}.md\:bui-mr-13{margin-right:var(--bui-space-13)}.md\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mr{margin-right:var(--pr-lg)}.lg\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.lg\:bui-mr-1{margin-right:var(--bui-space-1)}.lg\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.lg\:bui-mr-2{margin-right:var(--bui-space-2)}.lg\:bui-mr-3{margin-right:var(--bui-space-3)}.lg\:bui-mr-4{margin-right:var(--bui-space-4)}.lg\:bui-mr-5{margin-right:var(--bui-space-5)}.lg\:bui-mr-6{margin-right:var(--bui-space-6)}.lg\:bui-mr-7{margin-right:var(--bui-space-7)}.lg\:bui-mr-8{margin-right:var(--bui-space-8)}.lg\:bui-mr-9{margin-right:var(--bui-space-9)}.lg\:bui-mr-10{margin-right:var(--bui-space-10)}.lg\:bui-mr-11{margin-right:var(--bui-space-11)}.lg\:bui-mr-12{margin-right:var(--bui-space-12)}.lg\:bui-mr-13{margin-right:var(--bui-space-13)}.lg\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mr{margin-right:var(--pr-xl)}.xl\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xl\:bui-mr-1{margin-right:var(--bui-space-1)}.xl\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xl\:bui-mr-2{margin-right:var(--bui-space-2)}.xl\:bui-mr-3{margin-right:var(--bui-space-3)}.xl\:bui-mr-4{margin-right:var(--bui-space-4)}.xl\:bui-mr-5{margin-right:var(--bui-space-5)}.xl\:bui-mr-6{margin-right:var(--bui-space-6)}.xl\:bui-mr-7{margin-right:var(--bui-space-7)}.xl\:bui-mr-8{margin-right:var(--bui-space-8)}.xl\:bui-mr-9{margin-right:var(--bui-space-9)}.xl\:bui-mr-10{margin-right:var(--bui-space-10)}.xl\:bui-mr-11{margin-right:var(--bui-space-11)}.xl\:bui-mr-12{margin-right:var(--bui-space-12)}.xl\:bui-mr-13{margin-right:var(--bui-space-13)}.xl\:bui-mr-14{margin-right:var(--bui-space-14)}}.bui-mt{margin-top:var(--mt)}.bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.bui-mt-1{margin-top:var(--bui-space-1)}.bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.bui-mt-2{margin-top:var(--bui-space-2)}.bui-mt-3{margin-top:var(--bui-space-3)}.bui-mt-4{margin-top:var(--bui-space-4)}.bui-mt-5{margin-top:var(--bui-space-5)}.bui-mt-6{margin-top:var(--bui-space-6)}.bui-mt-7{margin-top:var(--bui-space-7)}.bui-mt-8{margin-top:var(--bui-space-8)}.bui-mt-9{margin-top:var(--bui-space-9)}.bui-mt-10{margin-top:var(--bui-space-10)}.bui-mt-11{margin-top:var(--bui-space-11)}.bui-mt-12{margin-top:var(--bui-space-12)}.bui-mt-13{margin-top:var(--bui-space-13)}.bui-mt-14{margin-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mt{margin-top:var(--pt-xs)}.xs\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xs\:bui-mt-1{margin-top:var(--bui-space-1)}.xs\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xs\:bui-mt-2{margin-top:var(--bui-space-2)}.xs\:bui-mt-3{margin-top:var(--bui-space-3)}.xs\:bui-mt-4{margin-top:var(--bui-space-4)}.xs\:bui-mt-5{margin-top:var(--bui-space-5)}.xs\:bui-mt-6{margin-top:var(--bui-space-6)}.xs\:bui-mt-7{margin-top:var(--bui-space-7)}.xs\:bui-mt-8{margin-top:var(--bui-space-8)}.xs\:bui-mt-9{margin-top:var(--bui-space-9)}.xs\:bui-mt-10{margin-top:var(--bui-space-10)}.xs\:bui-mt-11{margin-top:var(--bui-space-11)}.xs\:bui-mt-12{margin-top:var(--bui-space-12)}.xs\:bui-mt-13{margin-top:var(--bui-space-13)}.xs\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mt{margin-top:var(--pt-sm)}.sm\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.sm\:bui-mt-1{margin-top:var(--bui-space-1)}.sm\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.sm\:bui-mt-2{margin-top:var(--bui-space-2)}.sm\:bui-mt-3{margin-top:var(--bui-space-3)}.sm\:bui-mt-4{margin-top:var(--bui-space-4)}.sm\:bui-mt-5{margin-top:var(--bui-space-5)}.sm\:bui-mt-6{margin-top:var(--bui-space-6)}.sm\:bui-mt-7{margin-top:var(--bui-space-7)}.sm\:bui-mt-8{margin-top:var(--bui-space-8)}.sm\:bui-mt-9{margin-top:var(--bui-space-9)}.sm\:bui-mt-10{margin-top:var(--bui-space-10)}.sm\:bui-mt-11{margin-top:var(--bui-space-11)}.sm\:bui-mt-12{margin-top:var(--bui-space-12)}.sm\:bui-mt-13{margin-top:var(--bui-space-13)}.sm\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mt{margin-top:var(--pt-md)}.md\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.md\:bui-mt-1{margin-top:var(--bui-space-1)}.md\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.md\:bui-mt-2{margin-top:var(--bui-space-2)}.md\:bui-mt-3{margin-top:var(--bui-space-3)}.md\:bui-mt-4{margin-top:var(--bui-space-4)}.md\:bui-mt-5{margin-top:var(--bui-space-5)}.md\:bui-mt-6{margin-top:var(--bui-space-6)}.md\:bui-mt-7{margin-top:var(--bui-space-7)}.md\:bui-mt-8{margin-top:var(--bui-space-8)}.md\:bui-mt-9{margin-top:var(--bui-space-9)}.md\:bui-mt-10{margin-top:var(--bui-space-10)}.md\:bui-mt-11{margin-top:var(--bui-space-11)}.md\:bui-mt-12{margin-top:var(--bui-space-12)}.md\:bui-mt-13{margin-top:var(--bui-space-13)}.md\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mt{margin-top:var(--pt-lg)}.lg\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.lg\:bui-mt-1{margin-top:var(--bui-space-1)}.lg\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.lg\:bui-mt-2{margin-top:var(--bui-space-2)}.lg\:bui-mt-3{margin-top:var(--bui-space-3)}.lg\:bui-mt-4{margin-top:var(--bui-space-4)}.lg\:bui-mt-5{margin-top:var(--bui-space-5)}.lg\:bui-mt-6{margin-top:var(--bui-space-6)}.lg\:bui-mt-7{margin-top:var(--bui-space-7)}.lg\:bui-mt-8{margin-top:var(--bui-space-8)}.lg\:bui-mt-9{margin-top:var(--bui-space-9)}.lg\:bui-mt-10{margin-top:var(--bui-space-10)}.lg\:bui-mt-11{margin-top:var(--bui-space-11)}.lg\:bui-mt-12{margin-top:var(--bui-space-12)}.lg\:bui-mt-13{margin-top:var(--bui-space-13)}.lg\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mt{margin-top:var(--pt-xl)}.xl\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xl\:bui-mt-1{margin-top:var(--bui-space-1)}.xl\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xl\:bui-mt-2{margin-top:var(--bui-space-2)}.xl\:bui-mt-3{margin-top:var(--bui-space-3)}.xl\:bui-mt-4{margin-top:var(--bui-space-4)}.xl\:bui-mt-5{margin-top:var(--bui-space-5)}.xl\:bui-mt-6{margin-top:var(--bui-space-6)}.xl\:bui-mt-7{margin-top:var(--bui-space-7)}.xl\:bui-mt-8{margin-top:var(--bui-space-8)}.xl\:bui-mt-9{margin-top:var(--bui-space-9)}.xl\:bui-mt-10{margin-top:var(--bui-space-10)}.xl\:bui-mt-11{margin-top:var(--bui-space-11)}.xl\:bui-mt-12{margin-top:var(--bui-space-12)}.xl\:bui-mt-13{margin-top:var(--bui-space-13)}.xl\:bui-mt-14{margin-top:var(--bui-space-14)}}.bui-mb{margin-bottom:var(--mb)}.bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.bui-mb-1{margin-bottom:var(--bui-space-1)}.bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.bui-mb-2{margin-bottom:var(--bui-space-2)}.bui-mb-3{margin-bottom:var(--bui-space-3)}.bui-mb-4{margin-bottom:var(--bui-space-4)}.bui-mb-5{margin-bottom:var(--bui-space-5)}.bui-mb-6{margin-bottom:var(--bui-space-6)}.bui-mb-7{margin-bottom:var(--bui-space-7)}.bui-mb-8{margin-bottom:var(--bui-space-8)}.bui-mb-9{margin-bottom:var(--bui-space-9)}.bui-mb-10{margin-bottom:var(--bui-space-10)}.bui-mb-11{margin-bottom:var(--bui-space-11)}.bui-mb-12{margin-bottom:var(--bui-space-12)}.bui-mb-13{margin-bottom:var(--bui-space-13)}.bui-mb-14{margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mb{margin-bottom:var(--pb-xs)}.xs\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xs\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xs\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xs\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xs\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xs\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xs\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xs\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xs\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xs\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xs\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xs\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xs\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xs\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xs\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xs\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mb{margin-bottom:var(--pb-sm)}.sm\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.sm\:bui-mb-1{margin-bottom:var(--bui-space-1)}.sm\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.sm\:bui-mb-2{margin-bottom:var(--bui-space-2)}.sm\:bui-mb-3{margin-bottom:var(--bui-space-3)}.sm\:bui-mb-4{margin-bottom:var(--bui-space-4)}.sm\:bui-mb-5{margin-bottom:var(--bui-space-5)}.sm\:bui-mb-6{margin-bottom:var(--bui-space-6)}.sm\:bui-mb-7{margin-bottom:var(--bui-space-7)}.sm\:bui-mb-8{margin-bottom:var(--bui-space-8)}.sm\:bui-mb-9{margin-bottom:var(--bui-space-9)}.sm\:bui-mb-10{margin-bottom:var(--bui-space-10)}.sm\:bui-mb-11{margin-bottom:var(--bui-space-11)}.sm\:bui-mb-12{margin-bottom:var(--bui-space-12)}.sm\:bui-mb-13{margin-bottom:var(--bui-space-13)}.sm\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mb{margin-bottom:var(--pb-md)}.md\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.md\:bui-mb-1{margin-bottom:var(--bui-space-1)}.md\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.md\:bui-mb-2{margin-bottom:var(--bui-space-2)}.md\:bui-mb-3{margin-bottom:var(--bui-space-3)}.md\:bui-mb-4{margin-bottom:var(--bui-space-4)}.md\:bui-mb-5{margin-bottom:var(--bui-space-5)}.md\:bui-mb-6{margin-bottom:var(--bui-space-6)}.md\:bui-mb-7{margin-bottom:var(--bui-space-7)}.md\:bui-mb-8{margin-bottom:var(--bui-space-8)}.md\:bui-mb-9{margin-bottom:var(--bui-space-9)}.md\:bui-mb-10{margin-bottom:var(--bui-space-10)}.md\:bui-mb-11{margin-bottom:var(--bui-space-11)}.md\:bui-mb-12{margin-bottom:var(--bui-space-12)}.md\:bui-mb-13{margin-bottom:var(--bui-space-13)}.md\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mb{margin-bottom:var(--pb-lg)}.lg\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.lg\:bui-mb-1{margin-bottom:var(--bui-space-1)}.lg\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.lg\:bui-mb-2{margin-bottom:var(--bui-space-2)}.lg\:bui-mb-3{margin-bottom:var(--bui-space-3)}.lg\:bui-mb-4{margin-bottom:var(--bui-space-4)}.lg\:bui-mb-5{margin-bottom:var(--bui-space-5)}.lg\:bui-mb-6{margin-bottom:var(--bui-space-6)}.lg\:bui-mb-7{margin-bottom:var(--bui-space-7)}.lg\:bui-mb-8{margin-bottom:var(--bui-space-8)}.lg\:bui-mb-9{margin-bottom:var(--bui-space-9)}.lg\:bui-mb-10{margin-bottom:var(--bui-space-10)}.lg\:bui-mb-11{margin-bottom:var(--bui-space-11)}.lg\:bui-mb-12{margin-bottom:var(--bui-space-12)}.lg\:bui-mb-13{margin-bottom:var(--bui-space-13)}.lg\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mb{margin-bottom:var(--pb-xl)}.xl\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xl\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xl\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xl\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xl\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xl\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xl\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xl\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xl\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xl\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xl\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xl\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xl\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xl\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xl\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xl\:bui-mb-14{margin-bottom:var(--bui-space-14)}}.bui-my{margin-top:var(--my);margin-bottom:var(--my)}.bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-my{margin-top:var(--py-xs);margin-bottom:var(--py-xs)}.xs\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xs\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xs\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xs\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xs\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xs\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xs\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xs\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xs\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xs\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xs\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xs\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xs\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xs\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xs\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xs\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-my{margin-top:var(--py-sm);margin-bottom:var(--py-sm)}.sm\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.sm\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.sm\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.sm\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.sm\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.sm\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.sm\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.sm\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.sm\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.sm\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.sm\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.sm\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.sm\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.sm\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.sm\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.sm\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-my{margin-top:var(--py-md);margin-bottom:var(--py-md)}.md\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.md\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.md\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.md\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.md\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.md\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.md\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.md\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.md\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.md\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.md\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.md\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.md\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.md\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.md\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.md\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-my{margin-top:var(--py-lg);margin-bottom:var(--py-lg)}.lg\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.lg\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.lg\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.lg\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.lg\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.lg\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.lg\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.lg\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.lg\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.lg\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.lg\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.lg\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.lg\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.lg\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.lg\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.lg\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-my{margin-top:var(--py-xl);margin-bottom:var(--py-xl)}.xl\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xl\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xl\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xl\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xl\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xl\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xl\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xl\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xl\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xl\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xl\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xl\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xl\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xl\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xl\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xl\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}.bui-mx{margin-left:var(--mx);margin-right:var(--mx)}.bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mx{margin-left:var(--px-xs);margin-right:var(--px-xs)}.xs\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xs\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xs\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xs\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xs\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xs\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xs\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xs\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xs\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xs\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xs\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xs\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xs\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xs\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xs\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xs\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mx{margin-left:var(--px-sm);margin-right:var(--px-sm)}.sm\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.sm\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.sm\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.sm\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.sm\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.sm\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.sm\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.sm\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.sm\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.sm\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.sm\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.sm\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.sm\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.sm\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.sm\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.sm\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mx{margin-left:var(--px-md);margin-right:var(--px-md)}.md\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.md\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.md\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.md\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.md\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.md\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.md\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.md\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.md\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.md\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.md\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.md\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.md\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.md\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.md\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.md\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mx{margin-left:var(--px-lg);margin-right:var(--px-lg)}.lg\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.lg\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.lg\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.lg\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.lg\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.lg\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.lg\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.lg\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.lg\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.lg\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.lg\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.lg\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.lg\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.lg\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.lg\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.lg\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mx{margin-left:var(--px-xl);margin-right:var(--px-xl)}.xl\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xl\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xl\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xl\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xl\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xl\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xl\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xl\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xl\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xl\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xl\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xl\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xl\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xl\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xl\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xl\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}.bui-display-none{display:none}.bui-display-inline{display:inline}.bui-display-inline-block{display:inline-block}.bui-display-block{display:block}@media (width>=640px){.xs\:bui-display-none{display:none}.xs\:bui-display-inline{display:inline}.xs\:bui-display-inline-block{display:inline-block}.xs\:bui-display-block{display:block}}@media (width>=768px){.sm\:bui-display-none{display:none}.sm\:bui-display-inline{display:inline}.sm\:bui-display-inline-block{display:inline-block}.sm\:bui-display-block{display:block}}@media (width>=1024px){.md\:bui-display-none{display:none}.md\:bui-display-inline{display:inline}.md\:bui-display-inline-block{display:inline-block}.md\:bui-display-block{display:block}}@media (width>=1280px){.lg\:bui-display-none{display:none}.lg\:bui-display-inline{display:inline}.lg\:bui-display-inline-block{display:inline-block}.lg\:bui-display-block{display:block}}@media (width>=1536px){.xl\:bui-display-none{display:none}.xl\:bui-display-inline{display:inline}.xl\:bui-display-inline-block{display:inline-block}.xl\:bui-display-block{display:block}}.bui-w{width:var(--width)}.bui-min-w{min-width:var(--min-width)}.bui-max-w{max-width:var(--max-width)}@media (width>=640px){.xs\:bui-w{width:var(--width)}.xs\:bui-min-w{min-width:var(--min-width)}.xs\:bui-max-w{max-width:var(--max-width)}}@media (width>=768px){.sm\:bui-w{width:var(--width)}.sm\:bui-min-w{min-width:var(--min-width)}.sm\:bui-max-w{max-width:var(--max-width)}}@media (width>=1024px){.md\:bui-w{width:var(--width)}.md\:bui-min-w{min-width:var(--min-width)}.md\:bui-max-w{max-width:var(--max-width)}}@media (width>=1280px){.lg\:bui-w{width:var(--width)}.lg\:bui-min-w{min-width:var(--min-width)}.lg\:bui-max-w{max-width:var(--max-width)}}@media (width>=1536px){.xl\:bui-w{width:var(--width)}.xl\:bui-min-w{min-width:var(--min-width)}.xl\:bui-max-w{max-width:var(--max-width)}}.bui-h{height:var(--height)}.bui-min-h{min-height:var(--min-height)}.bui-max-h{max-height:var(--max-height)}@media (width>=640px){.xs\:bui-h{height:var(--height)}.xs\:bui-min-h{min-height:var(--min-height)}.xs\:bui-max-h{max-height:var(--max-height)}}@media (width>=768px){.sm\:bui-h{height:var(--height)}.sm\:bui-min-h{min-height:var(--min-height)}.sm\:bui-max-h{max-height:var(--max-height)}}@media (width>=1024px){.md\:bui-h{height:var(--height)}.md\:bui-min-h{min-height:var(--min-height)}.md\:bui-max-h{max-height:var(--max-height)}}@media (width>=1280px){.lg\:bui-h{height:var(--height)}.lg\:bui-min-h{min-height:var(--min-height)}.lg\:bui-max-h{max-height:var(--max-height)}}@media (width>=1536px){.xl\:bui-h{height:var(--height)}.xl\:bui-min-h{min-height:var(--min-height)}.xl\:bui-max-h{max-height:var(--max-height)}}.bui-position-absolute{position:absolute}.bui-position-fixed{position:fixed}.bui-position-sticky{position:sticky}.bui-position-relative{position:relative}.bui-position-static{position:static}@media (width>=640px){.xs\:bui-position-absolute{position:absolute}.xs\:bui-position-fixed{position:fixed}.xs\:bui-position-sticky{position:sticky}.xs\:bui-position-relative{position:relative}.xs\:bui-position-static{position:static}}@media (width>=768px){.sm\:bui-position-absolute{position:absolute}.sm\:bui-position-fixed{position:fixed}.sm\:bui-position-sticky{position:sticky}.sm\:bui-position-relative{position:relative}.sm\:bui-position-static{position:static}}@media (width>=1024px){.md\:bui-position-absolute{position:absolute}.md\:bui-position-fixed{position:fixed}.md\:bui-position-sticky{position:sticky}.md\:bui-position-relative{position:relative}.md\:bui-position-static{position:static}}@media (width>=1280px){.lg\:bui-position-absolute{position:absolute}.lg\:bui-position-fixed{position:fixed}.lg\:bui-position-sticky{position:sticky}.lg\:bui-position-relative{position:relative}.lg\:bui-position-static{position:static}}@media (width>=1536px){.xl\:bui-position-absolute{position:absolute}.xl\:bui-position-fixed{position:fixed}.xl\:bui-position-sticky{position:sticky}.xl\:bui-position-relative{position:relative}.xl\:bui-position-static{position:static}}.bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.bui-col-span-1{grid-column:span 1/span 1}.bui-col-span-2{grid-column:span 2/span 2}.bui-col-span-3{grid-column:span 3/span 3}.bui-col-span-4{grid-column:span 4/span 4}.bui-col-span-5{grid-column:span 5/span 5}.bui-col-span-6{grid-column:span 6/span 6}.bui-col-span-7{grid-column:span 7/span 7}.bui-col-span-8{grid-column:span 8/span 8}.bui-col-span-9{grid-column:span 9/span 9}.bui-col-span-10{grid-column:span 10/span 10}.bui-col-span-11{grid-column:span 11/span 11}.bui-col-span-12{grid-column:span 12/span 12}.bui-col-span-auto{grid-column:span auto/span auto}.bui-col-start-1{grid-column-start:1}.bui-col-start-2{grid-column-start:2}.bui-col-start-3{grid-column-start:3}.bui-col-start-4{grid-column-start:4}.bui-col-start-5{grid-column-start:5}.bui-col-start-6{grid-column-start:6}.bui-col-start-7{grid-column-start:7}.bui-col-start-8{grid-column-start:8}.bui-col-start-9{grid-column-start:9}.bui-col-start-10{grid-column-start:10}.bui-col-start-11{grid-column-start:11}.bui-col-start-12{grid-column-start:12}.bui-col-start-13{grid-column-start:13}.bui-col-start-auto{grid-column-start:auto}.bui-col-end-1{grid-column-end:1}.bui-col-end-2{grid-column-end:2}.bui-col-end-3{grid-column-end:3}.bui-col-end-4{grid-column-end:4}.bui-col-end-5{grid-column-end:5}.bui-col-end-6{grid-column-end:6}.bui-col-end-7{grid-column-end:7}.bui-col-end-8{grid-column-end:8}.bui-col-end-9{grid-column-end:9}.bui-col-end-10{grid-column-end:10}.bui-col-end-11{grid-column-end:11}.bui-col-end-12{grid-column-end:12}.bui-col-end-13{grid-column-end:13}.bui-col-end-auto{grid-column-end:auto}.bui-row-span-1{grid-row:span 1/span 1}.bui-row-span-2{grid-row:span 2/span 2}.bui-row-span-3{grid-row:span 3/span 3}.bui-row-span-4{grid-row:span 4/span 4}.bui-row-span-5{grid-row:span 5/span 5}.bui-row-span-6{grid-row:span 6/span 6}.bui-row-span-7{grid-row:span 7/span 7}.bui-row-span-8{grid-row:span 8/span 8}.bui-row-span-9{grid-row:span 9/span 9}.bui-row-span-10{grid-row:span 10/span 10}.bui-row-span-11{grid-row:span 11/span 11}.bui-row-span-12{grid-row:span 12/span 12}.bui-row-span-auto{grid-row:span auto/span auto}@media (width>=640px){.xs\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xs\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xs\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xs\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xs\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xs\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xs\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xs\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xs\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xs\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xs\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xs\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xs\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xs\:bui-col-span-1{grid-column:span 1/span 1}.xs\:bui-col-span-2{grid-column:span 2/span 2}.xs\:bui-col-span-3{grid-column:span 3/span 3}.xs\:bui-col-span-4{grid-column:span 4/span 4}.xs\:bui-col-span-5{grid-column:span 5/span 5}.xs\:bui-col-span-6{grid-column:span 6/span 6}.xs\:bui-col-span-7{grid-column:span 7/span 7}.xs\:bui-col-span-8{grid-column:span 8/span 8}.xs\:bui-col-span-9{grid-column:span 9/span 9}.xs\:bui-col-span-10{grid-column:span 10/span 10}.xs\:bui-col-span-11{grid-column:span 11/span 11}.xs\:bui-col-span-12{grid-column:span 12/span 12}.xs\:bui-col-span-auto{grid-column:span auto/span auto}.xs\:bui-col-start-1{grid-column-start:1}.xs\:bui-col-start-2{grid-column-start:2}.xs\:bui-col-start-3{grid-column-start:3}.xs\:bui-col-start-4{grid-column-start:4}.xs\:bui-col-start-5{grid-column-start:5}.xs\:bui-col-start-6{grid-column-start:6}.xs\:bui-col-start-7{grid-column-start:7}.xs\:bui-col-start-8{grid-column-start:8}.xs\:bui-col-start-9{grid-column-start:9}.xs\:bui-col-start-10{grid-column-start:10}.xs\:bui-col-start-11{grid-column-start:11}.xs\:bui-col-start-12{grid-column-start:12}.xs\:bui-col-start-13{grid-column-start:13}.xs\:bui-col-start-auto{grid-column-start:auto}.xs\:bui-col-end-1{grid-column-end:1}.xs\:bui-col-end-2{grid-column-end:2}.xs\:bui-col-end-3{grid-column-end:3}.xs\:bui-col-end-4{grid-column-end:4}.xs\:bui-col-end-5{grid-column-end:5}.xs\:bui-col-end-6{grid-column-end:6}.xs\:bui-col-end-7{grid-column-end:7}.xs\:bui-col-end-8{grid-column-end:8}.xs\:bui-col-end-9{grid-column-end:9}.xs\:bui-col-end-10{grid-column-end:10}.xs\:bui-col-end-11{grid-column-end:11}.xs\:bui-col-end-12{grid-column-end:12}.xs\:bui-col-end-13{grid-column-end:13}.xs\:bui-col-end-auto{grid-column-end:auto}.xs\:bui-row-span-1{grid-row:span 1/span 1}.xs\:bui-row-span-2{grid-row:span 2/span 2}.xs\:bui-row-span-3{grid-row:span 3/span 3}.xs\:bui-row-span-4{grid-row:span 4/span 4}.xs\:bui-row-span-5{grid-row:span 5/span 5}.xs\:bui-row-span-6{grid-row:span 6/span 6}.xs\:bui-row-span-7{grid-row:span 7/span 7}.xs\:bui-row-span-8{grid-row:span 8/span 8}.xs\:bui-row-span-9{grid-row:span 9/span 9}.xs\:bui-row-span-10{grid-row:span 10/span 10}.xs\:bui-row-span-11{grid-row:span 11/span 11}.xs\:bui-row-span-12{grid-row:span 12/span 12}.xs\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=768px){.sm\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.sm\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:bui-col-span-1{grid-column:span 1/span 1}.sm\:bui-col-span-2{grid-column:span 2/span 2}.sm\:bui-col-span-3{grid-column:span 3/span 3}.sm\:bui-col-span-4{grid-column:span 4/span 4}.sm\:bui-col-span-5{grid-column:span 5/span 5}.sm\:bui-col-span-6{grid-column:span 6/span 6}.sm\:bui-col-span-7{grid-column:span 7/span 7}.sm\:bui-col-span-8{grid-column:span 8/span 8}.sm\:bui-col-span-9{grid-column:span 9/span 9}.sm\:bui-col-span-10{grid-column:span 10/span 10}.sm\:bui-col-span-11{grid-column:span 11/span 11}.sm\:bui-col-span-12{grid-column:span 12/span 12}.sm\:bui-col-span-auto{grid-column:span auto/span auto}.sm\:bui-col-start-1{grid-column-start:1}.sm\:bui-col-start-2{grid-column-start:2}.sm\:bui-col-start-3{grid-column-start:3}.sm\:bui-col-start-4{grid-column-start:4}.sm\:bui-col-start-5{grid-column-start:5}.sm\:bui-col-start-6{grid-column-start:6}.sm\:bui-col-start-7{grid-column-start:7}.sm\:bui-col-start-8{grid-column-start:8}.sm\:bui-col-start-9{grid-column-start:9}.sm\:bui-col-start-10{grid-column-start:10}.sm\:bui-col-start-11{grid-column-start:11}.sm\:bui-col-start-12{grid-column-start:12}.sm\:bui-col-start-13{grid-column-start:13}.sm\:bui-col-start-auto{grid-column-start:auto}.sm\:bui-col-end-1{grid-column-end:1}.sm\:bui-col-end-2{grid-column-end:2}.sm\:bui-col-end-3{grid-column-end:3}.sm\:bui-col-end-4{grid-column-end:4}.sm\:bui-col-end-5{grid-column-end:5}.sm\:bui-col-end-6{grid-column-end:6}.sm\:bui-col-end-7{grid-column-end:7}.sm\:bui-col-end-8{grid-column-end:8}.sm\:bui-col-end-9{grid-column-end:9}.sm\:bui-col-end-10{grid-column-end:10}.sm\:bui-col-end-11{grid-column-end:11}.sm\:bui-col-end-12{grid-column-end:12}.sm\:bui-col-end-13{grid-column-end:13}.sm\:bui-col-end-auto{grid-column-end:auto}.sm\:bui-row-span-1{grid-row:span 1/span 1}.sm\:bui-row-span-2{grid-row:span 2/span 2}.sm\:bui-row-span-3{grid-row:span 3/span 3}.sm\:bui-row-span-4{grid-row:span 4/span 4}.sm\:bui-row-span-5{grid-row:span 5/span 5}.sm\:bui-row-span-6{grid-row:span 6/span 6}.sm\:bui-row-span-7{grid-row:span 7/span 7}.sm\:bui-row-span-8{grid-row:span 8/span 8}.sm\:bui-row-span-9{grid-row:span 9/span 9}.sm\:bui-row-span-10{grid-row:span 10/span 10}.sm\:bui-row-span-11{grid-row:span 11/span 11}.sm\:bui-row-span-12{grid-row:span 12/span 12}.sm\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1024px){.md\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.md\:bui-col-span-1{grid-column:span 1/span 1}.md\:bui-col-span-2{grid-column:span 2/span 2}.md\:bui-col-span-3{grid-column:span 3/span 3}.md\:bui-col-span-4{grid-column:span 4/span 4}.md\:bui-col-span-5{grid-column:span 5/span 5}.md\:bui-col-span-6{grid-column:span 6/span 6}.md\:bui-col-span-7{grid-column:span 7/span 7}.md\:bui-col-span-8{grid-column:span 8/span 8}.md\:bui-col-span-9{grid-column:span 9/span 9}.md\:bui-col-span-10{grid-column:span 10/span 10}.md\:bui-col-span-11{grid-column:span 11/span 11}.md\:bui-col-span-12{grid-column:span 12/span 12}.md\:bui-col-span-auto{grid-column:span auto/span auto}.md\:bui-col-start-1{grid-column-start:1}.md\:bui-col-start-2{grid-column-start:2}.md\:bui-col-start-3{grid-column-start:3}.md\:bui-col-start-4{grid-column-start:4}.md\:bui-col-start-5{grid-column-start:5}.md\:bui-col-start-6{grid-column-start:6}.md\:bui-col-start-7{grid-column-start:7}.md\:bui-col-start-8{grid-column-start:8}.md\:bui-col-start-9{grid-column-start:9}.md\:bui-col-start-10{grid-column-start:10}.md\:bui-col-start-11{grid-column-start:11}.md\:bui-col-start-12{grid-column-start:12}.md\:bui-col-start-13{grid-column-start:13}.md\:bui-col-start-auto{grid-column-start:auto}.md\:bui-col-end-1{grid-column-end:1}.md\:bui-col-end-2{grid-column-end:2}.md\:bui-col-end-3{grid-column-end:3}.md\:bui-col-end-4{grid-column-end:4}.md\:bui-col-end-5{grid-column-end:5}.md\:bui-col-end-6{grid-column-end:6}.md\:bui-col-end-7{grid-column-end:7}.md\:bui-col-end-8{grid-column-end:8}.md\:bui-col-end-9{grid-column-end:9}.md\:bui-col-end-10{grid-column-end:10}.md\:bui-col-end-11{grid-column-end:11}.md\:bui-col-end-12{grid-column-end:12}.md\:bui-col-end-13{grid-column-end:13}.md\:bui-col-end-auto{grid-column-end:auto}.md\:bui-row-span-1{grid-row:span 1/span 1}.md\:bui-row-span-2{grid-row:span 2/span 2}.md\:bui-row-span-3{grid-row:span 3/span 3}.md\:bui-row-span-4{grid-row:span 4/span 4}.md\:bui-row-span-5{grid-row:span 5/span 5}.md\:bui-row-span-6{grid-row:span 6/span 6}.md\:bui-row-span-7{grid-row:span 7/span 7}.md\:bui-row-span-8{grid-row:span 8/span 8}.md\:bui-row-span-9{grid-row:span 9/span 9}.md\:bui-row-span-10{grid-row:span 10/span 10}.md\:bui-row-span-11{grid-row:span 11/span 11}.md\:bui-row-span-12{grid-row:span 12/span 12}.md\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1280px){.lg\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.lg\:bui-col-span-1{grid-column:span 1/span 1}.lg\:bui-col-span-2{grid-column:span 2/span 2}.lg\:bui-col-span-3{grid-column:span 3/span 3}.lg\:bui-col-span-4{grid-column:span 4/span 4}.lg\:bui-col-span-5{grid-column:span 5/span 5}.lg\:bui-col-span-6{grid-column:span 6/span 6}.lg\:bui-col-span-7{grid-column:span 7/span 7}.lg\:bui-col-span-8{grid-column:span 8/span 8}.lg\:bui-col-span-9{grid-column:span 9/span 9}.lg\:bui-col-span-10{grid-column:span 10/span 10}.lg\:bui-col-span-11{grid-column:span 11/span 11}.lg\:bui-col-span-12{grid-column:span 12/span 12}.lg\:bui-col-span-auto{grid-column:span auto/span auto}.lg\:bui-col-start-1{grid-column-start:1}.lg\:bui-col-start-2{grid-column-start:2}.lg\:bui-col-start-3{grid-column-start:3}.lg\:bui-col-start-4{grid-column-start:4}.lg\:bui-col-start-5{grid-column-start:5}.lg\:bui-col-start-6{grid-column-start:6}.lg\:bui-col-start-7{grid-column-start:7}.lg\:bui-col-start-8{grid-column-start:8}.lg\:bui-col-start-9{grid-column-start:9}.lg\:bui-col-start-10{grid-column-start:10}.lg\:bui-col-start-11{grid-column-start:11}.lg\:bui-col-start-12{grid-column-start:12}.lg\:bui-col-start-13{grid-column-start:13}.lg\:bui-col-start-auto{grid-column-start:auto}.lg\:bui-col-end-1{grid-column-end:1}.lg\:bui-col-end-2{grid-column-end:2}.lg\:bui-col-end-3{grid-column-end:3}.lg\:bui-col-end-4{grid-column-end:4}.lg\:bui-col-end-5{grid-column-end:5}.lg\:bui-col-end-6{grid-column-end:6}.lg\:bui-col-end-7{grid-column-end:7}.lg\:bui-col-end-8{grid-column-end:8}.lg\:bui-col-end-9{grid-column-end:9}.lg\:bui-col-end-10{grid-column-end:10}.lg\:bui-col-end-11{grid-column-end:11}.lg\:bui-col-end-12{grid-column-end:12}.lg\:bui-col-end-13{grid-column-end:13}.lg\:bui-col-end-auto{grid-column-end:auto}.lg\:bui-row-span-1{grid-row:span 1/span 1}.lg\:bui-row-span-2{grid-row:span 2/span 2}.lg\:bui-row-span-3{grid-row:span 3/span 3}.lg\:bui-row-span-4{grid-row:span 4/span 4}.lg\:bui-row-span-5{grid-row:span 5/span 5}.lg\:bui-row-span-6{grid-row:span 6/span 6}.lg\:bui-row-span-7{grid-row:span 7/span 7}.lg\:bui-row-span-8{grid-row:span 8/span 8}.lg\:bui-row-span-9{grid-row:span 9/span 9}.lg\:bui-row-span-10{grid-row:span 10/span 10}.lg\:bui-row-span-11{grid-row:span 11/span 11}.lg\:bui-row-span-12{grid-row:span 12/span 12}.lg\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1536px){.xl\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xl\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xl\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xl\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xl\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xl\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xl\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xl\:bui-col-span-1{grid-column:span 1/span 1}.xl\:bui-col-span-2{grid-column:span 2/span 2}.xl\:bui-col-span-3{grid-column:span 3/span 3}.xl\:bui-col-span-4{grid-column:span 4/span 4}.xl\:bui-col-span-5{grid-column:span 5/span 5}.xl\:bui-col-span-6{grid-column:span 6/span 6}.xl\:bui-col-span-7{grid-column:span 7/span 7}.xl\:bui-col-span-8{grid-column:span 8/span 8}.xl\:bui-col-span-9{grid-column:span 9/span 9}.xl\:bui-col-span-10{grid-column:span 10/span 10}.xl\:bui-col-span-11{grid-column:span 11/span 11}.xl\:bui-col-span-12{grid-column:span 12/span 12}.xl\:bui-col-span-auto{grid-column:span auto/span auto}.xl\:bui-col-start-1{grid-column-start:1}.xl\:bui-col-start-2{grid-column-start:2}.xl\:bui-col-start-3{grid-column-start:3}.xl\:bui-col-start-4{grid-column-start:4}.xl\:bui-col-start-5{grid-column-start:5}.xl\:bui-col-start-6{grid-column-start:6}.xl\:bui-col-start-7{grid-column-start:7}.xl\:bui-col-start-8{grid-column-start:8}.xl\:bui-col-start-9{grid-column-start:9}.xl\:bui-col-start-10{grid-column-start:10}.xl\:bui-col-start-11{grid-column-start:11}.xl\:bui-col-start-12{grid-column-start:12}.xl\:bui-col-start-13{grid-column-start:13}.xl\:bui-col-start-auto{grid-column-start:auto}.xl\:bui-col-end-1{grid-column-end:1}.xl\:bui-col-end-2{grid-column-end:2}.xl\:bui-col-end-3{grid-column-end:3}.xl\:bui-col-end-4{grid-column-end:4}.xl\:bui-col-end-5{grid-column-end:5}.xl\:bui-col-end-6{grid-column-end:6}.xl\:bui-col-end-7{grid-column-end:7}.xl\:bui-col-end-8{grid-column-end:8}.xl\:bui-col-end-9{grid-column-end:9}.xl\:bui-col-end-10{grid-column-end:10}.xl\:bui-col-end-11{grid-column-end:11}.xl\:bui-col-end-12{grid-column-end:12}.xl\:bui-col-end-13{grid-column-end:13}.xl\:bui-col-end-auto{grid-column-end:auto}.xl\:bui-row-span-1{grid-row:span 1/span 1}.xl\:bui-row-span-2{grid-row:span 2/span 2}.xl\:bui-row-span-3{grid-row:span 3/span 3}.xl\:bui-row-span-4{grid-row:span 4/span 4}.xl\:bui-row-span-5{grid-row:span 5/span 5}.xl\:bui-row-span-6{grid-row:span 6/span 6}.xl\:bui-row-span-7{grid-row:span 7/span 7}.xl\:bui-row-span-8{grid-row:span 8/span 8}.xl\:bui-row-span-9{grid-row:span 9/span 9}.xl\:bui-row-span-10{grid-row:span 10/span 10}.xl\:bui-row-span-11{grid-row:span 11/span 11}.xl\:bui-row-span-12{grid-row:span 12/span 12}.xl\:bui-row-span-auto{grid-row:span auto/span auto}}.bui-gap{gap:var(--gap)}.bui-gap-0\.5{gap:var(--bui-space-0_5)}.bui-gap-1{gap:var(--bui-space-1)}.bui-gap-1\.5{gap:var(--bui-space-1_5)}.bui-gap-2{gap:var(--bui-space-2)}.bui-gap-3{gap:var(--bui-space-3)}.bui-gap-4{gap:var(--bui-space-4)}.bui-gap-5{gap:var(--bui-space-5)}.bui-gap-6{gap:var(--bui-space-6)}.bui-gap-7{gap:var(--bui-space-7)}.bui-gap-8{gap:var(--bui-space-8)}.bui-gap-9{gap:var(--bui-space-9)}.bui-gap-10{gap:var(--bui-space-10)}.bui-gap-11{gap:var(--bui-space-11)}.bui-gap-12{gap:var(--bui-space-12)}.bui-gap-13{gap:var(--bui-space-13)}.bui-gap-14{gap:var(--bui-space-14)}@media (width>=640px){.xs\:bui-gap{gap:var(--gap-xs)}.xs\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xs\:bui-gap-1{gap:var(--bui-space-1)}.xs\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xs\:bui-gap-2{gap:var(--bui-space-2)}.xs\:bui-gap-3{gap:var(--bui-space-3)}.xs\:bui-gap-4{gap:var(--bui-space-4)}.xs\:bui-gap-5{gap:var(--bui-space-5)}.xs\:bui-gap-6{gap:var(--bui-space-6)}.xs\:bui-gap-7{gap:var(--bui-space-7)}.xs\:bui-gap-8{gap:var(--bui-space-8)}.xs\:bui-gap-9{gap:var(--bui-space-9)}.xs\:bui-gap-10{gap:var(--bui-space-10)}.xs\:bui-gap-11{gap:var(--bui-space-11)}.xs\:bui-gap-12{gap:var(--bui-space-12)}.xs\:bui-gap-13{gap:var(--bui-space-13)}.xs\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-gap{gap:var(--gap-sm)}.sm\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.sm\:bui-gap-1{gap:var(--bui-space-1)}.sm\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.sm\:bui-gap-2{gap:var(--bui-space-2)}.sm\:bui-gap-3{gap:var(--bui-space-3)}.sm\:bui-gap-4{gap:var(--bui-space-4)}.sm\:bui-gap-5{gap:var(--bui-space-5)}.sm\:bui-gap-6{gap:var(--bui-space-6)}.sm\:bui-gap-7{gap:var(--bui-space-7)}.sm\:bui-gap-8{gap:var(--bui-space-8)}.sm\:bui-gap-9{gap:var(--bui-space-9)}.sm\:bui-gap-10{gap:var(--bui-space-10)}.sm\:bui-gap-11{gap:var(--bui-space-11)}.sm\:bui-gap-12{gap:var(--bui-space-12)}.sm\:bui-gap-13{gap:var(--bui-space-13)}.sm\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-gap{gap:var(--gap-md)}.md\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.md\:bui-gap-1{gap:var(--bui-space-1)}.md\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.md\:bui-gap-2{gap:var(--bui-space-2)}.md\:bui-gap-3{gap:var(--bui-space-3)}.md\:bui-gap-4{gap:var(--bui-space-4)}.md\:bui-gap-5{gap:var(--bui-space-5)}.md\:bui-gap-6{gap:var(--bui-space-6)}.md\:bui-gap-7{gap:var(--bui-space-7)}.md\:bui-gap-8{gap:var(--bui-space-8)}.md\:bui-gap-9{gap:var(--bui-space-9)}.md\:bui-gap-10{gap:var(--bui-space-10)}.md\:bui-gap-11{gap:var(--bui-space-11)}.md\:bui-gap-12{gap:var(--bui-space-12)}.md\:bui-gap-13{gap:var(--bui-space-13)}.md\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-gap{gap:var(--gap-lg)}.lg\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.lg\:bui-gap-1{gap:var(--bui-space-1)}.lg\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.lg\:bui-gap-2{gap:var(--bui-space-2)}.lg\:bui-gap-3{gap:var(--bui-space-3)}.lg\:bui-gap-4{gap:var(--bui-space-4)}.lg\:bui-gap-5{gap:var(--bui-space-5)}.lg\:bui-gap-6{gap:var(--bui-space-6)}.lg\:bui-gap-7{gap:var(--bui-space-7)}.lg\:bui-gap-8{gap:var(--bui-space-8)}.lg\:bui-gap-9{gap:var(--bui-space-9)}.lg\:bui-gap-10{gap:var(--bui-space-10)}.lg\:bui-gap-11{gap:var(--bui-space-11)}.lg\:bui-gap-12{gap:var(--bui-space-12)}.lg\:bui-gap-13{gap:var(--bui-space-13)}.lg\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-gap{gap:var(--gap-xl)}.xl\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xl\:bui-gap-1{gap:var(--bui-space-1)}.xl\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xl\:bui-gap-2{gap:var(--bui-space-2)}.xl\:bui-gap-3{gap:var(--bui-space-3)}.xl\:bui-gap-4{gap:var(--bui-space-4)}.xl\:bui-gap-5{gap:var(--bui-space-5)}.xl\:bui-gap-6{gap:var(--bui-space-6)}.xl\:bui-gap-7{gap:var(--bui-space-7)}.xl\:bui-gap-8{gap:var(--bui-space-8)}.xl\:bui-gap-9{gap:var(--bui-space-9)}.xl\:bui-gap-10{gap:var(--bui-space-10)}.xl\:bui-gap-11{gap:var(--bui-space-11)}.xl\:bui-gap-12{gap:var(--bui-space-12)}.xl\:bui-gap-13{gap:var(--bui-space-13)}.xl\:bui-gap-14{gap:var(--bui-space-14)}}.bui-align-start{align-items:start}.bui-align-center{align-items:center}.bui-align-end{align-items:end}.bui-align-baseline{align-items:baseline}.bui-align-stretch{align-items:stretch}.bui-jc-start{justify-content:start}.bui-jc-center{justify-content:center}.bui-jc-end{justify-content:end}.bui-jc-between{justify-content:space-between}.bui-fd-row{flex-direction:row}.bui-fd-column{flex-direction:column}.bui-fd-row-reverse{flex-direction:row-reverse}.bui-fd-column-reverse{flex-direction:column-reverse}@media (width>=640px){.xs\:bui-align-start{align-items:start}.xs\:bui-align-center{align-items:center}.xs\:bui-align-end{align-items:end}.xs\:bui-align-stretch{align-items:stretch}.xs\:bui-jc-start{justify-content:start}.xs\:bui-jc-center{justify-content:center}.xs\:bui-jc-end{justify-content:end}.xs\:bui-jc-between{justify-content:space-between}.xs\:bui-fd-row{flex-direction:row}.xs\:bui-fd-column{flex-direction:column}.xs\:bui-fd-row-reverse{flex-direction:row-reverse}.xs\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=768px){.sm\:bui-align-start{align-items:start}.sm\:bui-align-center{align-items:center}.sm\:bui-align-end{align-items:end}.sm\:bui-align-stretch{align-items:stretch}.sm\:bui-jc-start{justify-content:start}.sm\:bui-jc-center{justify-content:center}.sm\:bui-jc-end{justify-content:end}.sm\:bui-jc-between{justify-content:space-between}.sm\:bui-fd-row{flex-direction:row}.sm\:bui-fd-column{flex-direction:column}.sm\:bui-fd-row-reverse{flex-direction:row-reverse}.sm\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1024px){.md\:bui-align-start{align-items:start}.md\:bui-align-center{align-items:center}.md\:bui-align-end{align-items:end}.md\:bui-align-stretch{align-items:stretch}.md\:bui-jc-start{justify-content:start}.md\:bui-jc-center{justify-content:center}.md\:bui-jc-end{justify-content:end}.md\:bui-jc-between{justify-content:space-between}.md\:bui-fd-row{flex-direction:row}.md\:bui-fd-column{flex-direction:column}.md\:bui-fd-row-reverse{flex-direction:row-reverse}.md\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1280px){.lg\:bui-align-start{align-items:start}.lg\:bui-align-center{align-items:center}.lg\:bui-align-end{align-items:end}.lg\:bui-align-stretch{align-items:stretch}.lg\:bui-jc-start{justify-content:start}.lg\:bui-jc-center{justify-content:center}.lg\:bui-jc-end{justify-content:end}.lg\:bui-jc-between{justify-content:space-between}.lg\:bui-fd-row{flex-direction:row}.lg\:bui-fd-column{flex-direction:column}.lg\:bui-fd-row-reverse{flex-direction:row-reverse}.lg\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1536px){.xl\:bui-align-start{align-items:start}.xl\:bui-align-center{align-items:center}.xl\:bui-align-end{align-items:end}.xl\:bui-align-stretch{align-items:stretch}.xl\:bui-jc-start{justify-content:start}.xl\:bui-jc-center{justify-content:center}.xl\:bui-jc-end{justify-content:end}.xl\:bui-jc-between{justify-content:space-between}.xl\:bui-fd-row{flex-direction:row}.xl\:bui-fd-column{flex-direction:column}.xl\:bui-fd-row-reverse{flex-direction:row-reverse}.xl\:bui-fd-column-reverse{flex-direction:column-reverse}}:where(a){color:inherit;text-decoration:none}@keyframes pulse{50%{opacity:.5}}:root{--bui-font-regular:system-ui;--bui-font-monospace:ui-monospace,"Menlo","Monaco","Consolas","Liberation Mono","Courier New",monospace;--bui-font-weight-regular:400;--bui-font-weight-bold:600;--bui-font-size-1:.625rem;--bui-font-size-2:.75rem;--bui-font-size-3:.875rem;--bui-font-size-4:1rem;--bui-font-size-5:1.25rem;--bui-font-size-6:1.5rem;--bui-font-size-7:2rem;--bui-font-size-8:3rem;--bui-font-size-9:4rem;--bui-font-size-10:5.75rem;--bui-space:.25rem;--bui-space-0_5:calc(var(--bui-space)*.5);--bui-space-1:var(--bui-space);--bui-space-1_5:calc(var(--bui-space)*1.5);--bui-space-2:calc(var(--bui-space)*2);--bui-space-3:calc(var(--bui-space)*3);--bui-space-4:calc(var(--bui-space)*4);--bui-space-5:calc(var(--bui-space)*5);--bui-space-6:calc(var(--bui-space)*6);--bui-space-7:calc(var(--bui-space)*7);--bui-space-8:calc(var(--bui-space)*8);--bui-space-9:calc(var(--bui-space)*9);--bui-space-10:calc(var(--bui-space)*10);--bui-space-11:calc(var(--bui-space)*11);--bui-space-12:calc(var(--bui-space)*12);--bui-space-13:calc(var(--bui-space)*13);--bui-space-14:calc(var(--bui-space)*14);--bui-radius-1:calc(.125rem);--bui-radius-2:calc(.25rem);--bui-radius-3:calc(.5rem);--bui-radius-4:calc(.75rem);--bui-radius-5:calc(1rem);--bui-radius-6:calc(1.25rem);--bui-radius-full:9999px;--bui-black:#000;--bui-white:#fff;--bui-gray-1:#f8f8f8;--bui-gray-2:#ececec;--bui-gray-3:#d9d9d9;--bui-gray-4:#c1c1c1;--bui-gray-5:#9e9e9e;--bui-gray-6:#8c8c8c;--bui-gray-7:#757575;--bui-gray-8:#595959;--bui-bg:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1f5493;--bui-bg-solid-hover:#163a66;--bui-bg-solid-pressed:#0f2b4e;--bui-bg-solid-disabled:#ebebeb;--bui-bg-tint:transparent;--bui-bg-tint-hover:#1f549366;--bui-bg-tint-pressed:#1f549399;--bui-bg-tint-disabled:#ebebeb;--bui-bg-danger:#feebe7;--bui-bg-warning:#fff2b2;--bui-bg-success:#e6f6eb;--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#1f5493;--bui-fg-link-hover:#1f2d5c;--bui-fg-disabled:#9e9e9e;--bui-fg-solid:var(--bui-white);--bui-fg-solid-disabled:#9c9c9c;--bui-fg-tint:#1f5493;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#0000001a;--bui-border-hover:#0003;--bui-border-pressed:#0006;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#a0a0a03b;--bui-scrollbar-thumb:#a0a0a0;--bui-animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite}[data-theme-mode=dark]{--bui-gray-1:#191919;--bui-gray-2:#242424;--bui-gray-3:#373737;--bui-gray-4:#464646;--bui-gray-5:#575757;--bui-gray-6:#7b7b7b;--bui-gray-7:#9e9e9e;--bui-gray-8:#b4b4b4;--bui-bg:#333;--bui-bg-surface-1:#424242;--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#9cc9ff;--bui-bg-solid-hover:#83b9fd;--bui-bg-solid-pressed:#83b9fd;--bui-bg-solid-disabled:#222;--bui-bg-tint:transparent;--bui-bg-tint-hover:#9cc9ff1f;--bui-bg-tint-pressed:#9cc9ff29;--bui-bg-tint-disabled:transparent;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#9cc9ff;--bui-fg-link-hover:#7eb5f7;--bui-fg-disabled:var(--bui-gray-7);--bui-fg-solid:#101821;--bui-fg-solid-disabled:var(--bui-gray-5);--bui-fg-tint:#9cc9ff;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#ffffff1f;--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#3636363a;--bui-scrollbar-thumb:#575757}.bui-AvatarRoot{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-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}.bui-AvatarRoot[data-size=small]{width:1.5rem;height:1.5rem}.bui-AvatarRoot[data-size=medium]{width:2rem;height:2rem}.bui-AvatarRoot[data-size=large]{width:3rem;height:3rem}.bui-AvatarImage{object-fit:cover;width:100%;height:100%}.bui-AvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-Box{font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary)}.bui-Button{user-select:none;font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-bold);cursor:pointer;border-radius:var(--bui-radius-2);justify-content:center;align-items:center;gap:var(--bui-space-1_5);border:none;flex-shrink:0;padding:0;display:inline-flex;&[data-disabled=true]{cursor:not-allowed}}.bui-Button[data-variant=primary]{background-color:var(--bui-bg-solid);color:var(--bui-fg-solid);&:hover{background-color:var(--bui-bg-solid-hover);transition:background-color .15s}&:active{background-color:var(--bui-bg-solid-pressed)}&:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled=true]{background-color:var(--bui-bg-solid-disabled);color:var(--bui-fg-solid-disabled)}}.bui-Button[data-variant=secondary]{background-color:var(--bui-bg-surface-1);box-shadow:inset 0 0 0 1px var(--bui-border);color:var(--bui-fg-primary);&:hover{box-shadow:inset 0 0 0 1px var(--bui-border-hover);transition:box-shadow .15s}&:active{box-shadow:inset 0 0 0 1px var(--bui-border-pressed)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{box-shadow:inset 0 0 0 1px var(--bui-border-disabled);color:var(--bui-fg-disabled)}}.bui-Button[data-variant=tertiary]{color:var(--bui-fg-primary);background-color:#0000;&:hover{background-color:var(--bui-bg-surface-1);transition:background-color .2s}&:active{background-color:var(--bui-bg-surface-2)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{color:var(--bui-fg-disabled);background-color:#0000}}.bui-Button[data-size=medium]{font-size:var(--bui-font-size-4);padding:0 var(--bui-space-3);height:2.5rem}.bui-Button[data-size=small]{font-size:var(--bui-font-size-3);padding:0 var(--bui-space-2);height:2rem}.bui-Button[data-size=small] svg{width:1rem;height:1rem}.bui-Button[data-size=medium] svg{width:1.25rem;height:1.25rem}.bui-ButtonIcon{justify-content:center;align-items:center}.bui-ButtonIcon[data-size=small]{width:2rem;padding:0}.bui-ButtonIcon[data-size=medium]{width:2.5rem;padding:0}.bui-Card{gap:var(--bui-space-3);background-color:var(--bui-bg-surface-1);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-3);color:var(--bui-fg-primary);border:1px solid var(--bui-border);flex-direction:column;width:100%;min-height:0;display:flex;overflow:hidden}.bui-CardBody{flex:1;min-height:0;overflow:auto}.bui-CardHeader,.bui-CardFooter{padding-inline:var(--bui-space-3)}.bui-CheckboxRoot{width:1rem;height:1rem;box-shadow:inset 0 0 0 1px var(--bui-border);cursor:pointer;background-color:var(--bui-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}.bui-CheckboxRoot:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px;transition:none}.bui-CheckboxRoot[data-checked]{background-color:var(--bui-bg-solid);box-shadow:none;color:var(--bui-fg-solid)}.bui-CheckboxLabel{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);user-select:none;flex-direction:row;display:flex;&:hover{& .bui-CheckboxRoot:not([data-checked]){box-shadow:inset 0 0 0 1px var(--bui-border-hover)}}}.bui-CheckboxIndicator{color:var(--bui-fg-solid);justify-content:center;align-items:center;display:flex}.bui-CollapsiblePanel{height:var(--collapsible-panel-height);transition:all .15s ease-out;display:flex;overflow:hidden;&[data-starting-style],&[data-ending-style]{height:0}}.bui-Container{max-width:120rem;padding-inline:var(--bui-space-4);margin-inline:auto;transition:padding .2s ease-in-out}@media (width>=640px){.bui-Container{padding-inline:var(--bui-space-5)}}.bui-FieldError{color:var(--bui-fg-danger);font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);margin-top:var(--bui-space-2);display:inline-block}.bui-FieldLabelWrapper{margin-bottom:var(--bui-space-3);gap:var(--bui-space-1);flex-direction:column;display:flex}.bui-FieldLabel{color:var(--bui-fg-primary);cursor:pointer;font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);margin-right:auto}.bui-FieldSecondaryLabel{color:var(--bui-fg-secondary);font-weight:var(--bui-font-weight-regular);margin-left:var(--bui-space-1)}.bui-FieldDescription{font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);color:var(--bui-fg-secondary);margin:0}.bui-Flex{min-width:0;display:flex}.bui-Grid{display:grid}.bui-HeaderToolbar{margin-bottom:var(--bui-space-6);&:before{content:"";background-color:var(--bui-bg);z-index:0;height:16px;position:absolute;top:0;left:0;right:0}&[data-has-tabs=true]{margin-bottom:0}}.bui-HeaderToolbarWrapper{z-index:1;background-color:var(--bui-bg-surface-1);padding-inline:var(--bui-space-5);border-bottom:1px solid var(--bui-border);color:var(--bui-fg-primary);flex-direction:row;justify-content:space-between;align-items:center;height:52px;display:flex;position:relative}.bui-HeaderToolbarContent{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-HeaderToolbarName{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);flex-direction:row;flex-shrink:0;display:flex}.bui-HeaderToolbarIcon{width:16px;height:16px;color:var(--bui-fg-primary);& svg{width:100%;height:100%}}.bui-HeaderToolbarControls{right:var(--bui-space-5);align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex;position:absolute;top:50%;transform:translateY(-50%)}.bui-HeaderTabsWrapper{margin-bottom:var(--bui-space-4);padding-inline:var(--bui-space-3);border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1)}.bui-HeaderPage{gap:var(--bui-space-1);margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6);flex-direction:column;display:flex}.bui-HeaderPageContent{flex-direction:row;justify-content:space-between;display:flex}.bui-HeaderPageTabsWrapper{margin-left:-8px}.bui-HeaderPageControls,.bui-HeaderPageBreadcrumbs{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-Icon{width:1rem;height:1rem}.bui-Link{font-family:var(--bui-font-regular);cursor:pointer;margin:0;padding:0;text-decoration-line:none;display:inline-block;&: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,currentColor 30%,transparent)}}.bui-MenuPopover{border:1px solid var(--bui-border);border-radius:var(--bui-radius-2);background:var(--bui-bg-surface-1);color:var(--bui-fg-primary);outline:none;flex-direction:column;min-height:0;transition:transform .2s,opacity .2s;display:flex;overflow:hidden;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}&[data-placement=top]{--origin:translateY(8px)}&[data-placement=bottom]{--origin:translateY(-8px)}&[data-placement=right]{--origin:translateX(-8px)}&[data-placement=left]{--origin:translateX(8px)}}.bui-MenuContent{max-height:inherit;box-sizing:border-box;padding:var(--bui-space-1);outline:none;min-width:150px;overflow:auto}.bui-MenuPopover .bui-ScrollAreaRoot{flex-direction:column;flex:1;height:100%;min-height:0;display:flex}.bui-MenuPopover .bui-ScrollAreaScrollbar{margin-inline:var(--bui-space-1_5)}.bui-MenuItem{height:2rem;padding-inline:var(--bui-space-2);border-radius:var(--bui-radius-2);cursor:default;color:var(--bui-fg-primary);font-size:var(--bui-font-size-3);justify-content:space-between;align-items:center;gap:var(--bui-space-6);outline:none;display:flex;&[data-focused],&[data-open]{background:var(--bui-bg-surface-2);color:var(--bui-fg-primary)}&[data-color=danger]{color:var(--bui-fg-danger)}&[data-color=danger][data-focused]{background:var(--bui-bg-danger);color:var(--bui-fg-danger)}&[data-has-submenu]{&>.bui-MenuItemArrow{display:block}}}.bui-MenuItemListBox{height:2rem;padding-inline:var(--bui-space-2);border-radius:var(--bui-radius-2);cursor:default;color:var(--bui-fg-primary);font-size:var(--bui-font-size-3);justify-content:space-between;align-items:center;gap:var(--bui-space-6);outline:none;display:flex;&:hover{background:var(--bui-bg-surface-2);color:var(--bui-fg-primary)}&[data-selected] .bui-MenuItemListBoxCheck{&>svg{opacity:1;color:var(--bui-fg-primary)}}}.bui-MenuItemListBoxCheck{justify-content:center;align-items:center;width:1rem;height:1rem;display:flex;&>svg{opacity:0;width:1rem;height:1rem}}.bui-MenuItemContent{align-items:center;gap:var(--bui-space-2);display:flex;&>svg{width:1rem;height:1rem}}.bui-MenuItemArrow{width:1rem;height:1rem;display:none;&>svg{width:1rem;height:1rem}}.bui-MenuSection{&:first-child .bui-MenuSectionHeader{padding-top:0}}.bui-MenuSectionHeader{height:2rem;padding-top:var(--bui-space-3);padding-left:var(--bui-space-2);color:var(--bui-fg-primary);font-size:var(--bui-font-size-1);letter-spacing:.05rem;text-transform:uppercase;align-items:center;font-weight:700;display:flex}.bui-MenuSeparator{background:var(--bui-border);height:1px;margin-inline:var(--bui-space-1_5);margin-block:var(--bui-space-1)}.bui-MenuSearchField{font-family:var(--bui-font-regular);flex-shrink:0;width:100%;position:relative;&[data-empty]{& .bui-MenuSearchFieldClear{display:none}}}.bui-MenuSearchFieldInput{padding:0 var(--bui-space-3);border:none;border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);width:100%;height:2rem;cursor:inherit;outline:none;align-items:center;display:flex;&::-webkit-search-cancel-button,&::-webkit-search-decoration{-webkit-appearance:none}}.bui-MenuSearchFieldClear{right:var(--bui-space-2);cursor:pointer;color:var(--bui-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;&>svg{width:1rem;height:1rem}}.bui-MenuEmptyState{padding:var(--bui-space-1);color:var(--bui-fg-secondary);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular)}.bui-Popover{background-color:var(--bui-bg-surface-1);border:1px solid var(--bui-border);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-1);margin-right:12px;overflow:scroll;box-shadow:0 4px 12px #0000001a}.bui-RadioGroup{color:var(--bui-fg-primary);flex-direction:column;display:flex}.bui-RadioGroup[data-orientation=horizontal] .bui-RadioGroupContent{gap:var(--bui-space-4);flex-direction:row}.bui-RadioGroupContent{gap:var(--bui-space-2);flex-direction:column;display:flex}.bui-Radio{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-2);color:var(--bui-fg-primary);forced-color-adjust:none;display:flex;position:relative;&:before{content:"";box-sizing:border-box;border:.125rem solid var(--bui-border);background:var(--bui-gray-1);border-radius:var(--bui-radius-full);width:1rem;height:1rem;transition:all .2s;display:block}&[data-pressed]:before{border-color:var(--bui-border)}&[data-selected]{&:before{border-color:var(--bui-bg-solid);border-width:.25rem}&[data-pressed]:before{border-color:var(--bui-bg-solid)}}&[data-focus-visible]:before{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}&[data-invalid]:before,&[data-invalid][data-selected]:before{border-color:var(--bui-border-danger)}&[data-disabled][data-invalid]{color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}}.bui-Table{caption-side:bottom;border-collapse:collapse;width:100%}.bui-TableHeader{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out}.bui-TableHead{text-align:left;padding:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary)}.bui-TableHeadSortButton{cursor:pointer;user-select:none;align-items:center;gap:var(--bui-space-1);display:inline-flex;&:hover svg{opacity:.5}& svg{opacity:0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}&[data-sort-order=asc] svg{opacity:1;transform:rotate(0)}&[data-sort-order=desc] svg{opacity:1;transform:rotate(180deg)}}.bui-TableBody{color:var(--bui-fg-primary)}.bui-TableRow{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out;&[data-react-aria-pressable=true]{cursor:pointer}}.bui-TableBody .bui-TableRow:hover{background-color:var(--bui-gray-2)}.bui-TableCell{padding:var(--bui-space-3);font-size:var(--bui-font-size-3);padding:var(--bui-space-3);font-size:var(--bui-font-size-3)}.bui-TableCellContentWrapper{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:inline-flex}.bui-TableCellIcon,.bui-TableCellIcon svg{color:var(--bui-fg-primary);align-items:center;display:inline-flex}.bui-TableCellContent{gap:var(--bui-space-0_5);flex-direction:column;display:flex}.bui-TableCellProfile{gap:var(--bui-space-2);flex-direction:row;align-items:center;display:flex}.bui-TableCellProfileAvatar{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-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}.bui-TableCellProfileAvatarImage{object-fit:cover;width:100%;height:100%}.bui-TableCellProfileAvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-DataTablePagination{padding-top:var(--bui-space-5);justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--left{justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--right{justify-content:space-between;align-items:center;gap:var(--bui-space-2);display:flex}.bui-DataTablePagination--select{min-width:10.5rem}.bui-Tabs{--active-tab-left:0px;--active-tab-right:0px;--active-tab-top:0px;--active-tab-bottom:0px;--active-tab-width:0px;--active-tab-height:0px;--active-transition-duration:0s;--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}.bui-TabList{flex-direction:row;display:flex}.bui-TabListWrapper{position:relative}.bui-Tab{font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-secondary);cursor:pointer;z-index:2;height:36px;padding-inline:var(--bui-space-2);justify-content:center;align-items:center;display:flex;position:relative;&[data-selected=true]{color:var(--bui-fg-primary)}}.bui-TabActive{content:"";left:calc(var(--active-tab-left) + var(--bui-space-2));width:calc(var(--active-tab-width) - var(--bui-space-4));background-color:var(--bui-fg-primary);height:1px;transition:left var(--active-transition-duration)ease-out,opacity .15s ease-out,width var(--active-transition-duration)ease-out;opacity:1;border-radius:4px;position:absolute;bottom:-1px}.bui-TabHovered{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(--bui-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}.bui-TabPanel{padding-inline:var(--bui-space-2);padding-top:var(--bui-space-4)}.bui-TagList{gap:var(--bui-space-2);flex-wrap:wrap;display:flex}.bui-Tag{color:var(--bui-fg-primary);background-color:var(--bui-gray-2);border-radius:var(--bui-radius-2);font-weight:var(--bui-font-weight-regular);justify-content:center;align-items:center;gap:var(--bui-space-1);box-sizing:border-box;transition-property:background-color,box-shadow,color;transition-duration:.2s;transition-timing-function:ease-in-out;display:flex}.bui-Tag[data-size=small]{height:26px;padding:0 var(--bui-space-2);font-size:var(--bui-font-size-1)}.bui-Tag[data-size=medium]{height:32px;padding:0 var(--bui-space-2);font-size:var(--bui-font-size-2)}.bui-Tag[data-hovered]{background-color:var(--bui-gray-3);cursor:pointer}.bui-Tag[data-focus-visible]{outline:2px solid var(--bui-ring);outline-offset:1px}.bui-Tag[data-selected]{box-shadow:inset 0 0 0 1px var(--bui-gray-8)}.bui-Tag[data-disabled]{color:var(--bui-fg-disabled);cursor:not-allowed}.bui-TagRemoveButton{cursor:pointer;color:var(--bui-fg-primary);background-color:#0000;border:none;width:1rem;height:1rem;margin:0;padding:0}.bui-TagIcon{justify-content:center;align-items:center;transition:color .2s ease-in-out;display:flex;& svg{width:1rem;height:1rem}}.bui-Text{font-family:var(--bui-font-regular);margin:0;padding:0}.bui-Text[data-variant=title-large]{font-size:var(--bui-font-size-8);line-height:140%}.bui-Text[data-variant=title-medium]{font-size:var(--bui-font-size-7);line-height:140%}.bui-Text[data-variant=title-small]{font-size:var(--bui-font-size-6);line-height:140%}.bui-Text[data-variant=title-x-small]{font-size:var(--bui-font-size-5);line-height:140%}.bui-Text[data-variant=body-large]{font-size:var(--bui-font-size-4);line-height:140%}.bui-Text[data-variant=body-medium]{font-size:var(--bui-font-size-3);line-height:140%}.bui-Text[data-variant=body-small]{font-size:var(--bui-font-size-2);line-height:140%}.bui-Text[data-variant=body-x-small]{font-size:var(--bui-font-size-1);line-height:140%}.bui-Text[data-weight=regular]{font-weight:var(--bui-font-weight-regular)}.bui-Text[data-weight=bold]{font-weight:var(--bui-font-weight-bold)}.bui-Text[data-color=primary]{color:var(--bui-fg-primary)}.bui-Text[data-color=secondary]{color:var(--bui-fg-secondary)}.bui-Text[data-color=danger]{color:var(--bui-fg-danger)}.bui-Text[data-color=warning]{color:var(--bui-fg-warning)}.bui-Text[data-color=success]{color:var(--bui-fg-success)}.bui-Text[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bui-Text[data-as=span],.bui-Text[data-as=label],.bui-Text[data-as=strong],.bui-Text[data-as=em],.bui-Text[data-as=small]{display:inline-block}.bui-TextField{font-family:var(--bui-font-regular);flex-direction:column;flex-shrink:0;width:100%;display:flex}.bui-PasswordField{font-family:var(--bui-font-regular);--bui-passwordmanager-icon-width:var(--bui-space-1);flex-direction:column;flex-shrink:0;width:100%;display:flex}.bui-InputWrapper{position:relative;&[data-size=small] .bui-Input{height:2rem}&[data-size=medium] .bui-Input{height:2.5rem}&[data-size=small] .bui-Input[data-icon]{padding-left:var(--bui-space-8)}&[data-size=medium] .bui-Input[data-icon]{padding-left:var(--bui-space-9)}}.bui-InputAction{right:var(--bui-space-1);color:var(--bui-fg-primary);flex-direction:row;flex-shrink:0;transition:right .2s ease-in-out;display:flex;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}}.bui-InputVisibility{cursor:pointer;color:var(--bui-fg-primary);background-color:#0000;border:none;justify-content:center;align-items:center;margin:0;padding:0;display:flex;&[data-size=small]{width:2rem;height:2rem}&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium]{width:2.5rem;height:2.5rem}&[data-size=medium] svg{width:1.25rem;height:1.25rem}}.bui-PasswordField .bui-InputWrapper[data-size=small] .bui-Input{padding-right:calc(2rem + var(--bui-passwordmanager-icon-width))}.bui-PasswordField .bui-InputWrapper[data-size=medium] .bui-Input{padding-right:calc(2.5rem + var(--bui-passwordmanager-icon-width))}.bui-InputIcon{left:var(--bui-space-3);margin-right:var(--bui-space-1);color:var(--bui-fg-primary);pointer-events:none;flex-shrink:0;transition:left .2s ease-in-out;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}}.bui-Input{padding:0 var(--bui-space-3);border-radius:var(--bui-radius-2);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-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(--bui-fg-secondary)}&[data-focused]{outline-color:var(--bui-border-pressed);outline-width:0}&[data-hovered]{border-color:var(--bui-border-hover)}&[data-focused]{border-color:var(--bui-border-pressed);outline-width:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-disabled]{opacity:.5;cursor:not-allowed;border:1px solid var(--bui-border-disabled)}}.bui-SearchField{flex:1 0;&[data-empty]{& .bui-InputClear{display:none}}&[data-start-collapsed=true]{flex:0 auto;padding:0;transition:flex-basis .3s ease-in-out;&[data-collapsed=true]{flex-basis:200px}&[data-collapsed=false]{cursor:pointer;&[data-size=medium]{flex-basis:2.5rem;height:2.5rem}&[data-size=small]{flex-basis:2rem;height:2rem}&[data-size=medium] .bui-Input{&::placeholder{opacity:0}}&[data-size=small] .bui-Input{&::placeholder{opacity:0}}& .bui-InputWrapper{& .bui-Input[data-icon]{padding-right:0}}}}}.bui-SearchField .bui-Input{transition:padding .3s ease-in-out,border-color .2s ease-in-out,outline-color .2s ease-in-out;&[data-hovered]{border-color:var(--bui-border-hover)}&[data-focused]{border-color:var(--bui-border-pressed);outline-width:0}}.bui-SearchField .bui-InputWrapper{& .bui-Input[data-icon]{padding-right:var(--bui-space-6)}}.bui-SearchField .bui-InputIcon{justify-content:center;display:flex;left:0;&[data-size=small]{width:var(--bui-space-8)}&[data-size=medium]{width:var(--bui-space-10)}}.bui-InputClear{cursor:pointer;color:var(--bui-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}.bui-InputClear:hover{color:var(--bui-fg-primary)}.bui-InputClear[data-size=small]{width:2rem;height:2rem}.bui-InputClear[data-size=medium]{width:2.5rem;height:2.5rem}.bui-InputClear svg{width:1rem;height:1rem}.bui-Skeleton{animation:var(--bui-animate-pulse);background-color:var(--bui-bg-surface-2);border-radius:var(--bui-radius-2)}.bui-Skeleton[data-rounded=true]{border-radius:var(--bui-radius-full)}.bui-Tooltip{background:var(--bui-bg-surface-1);border:1px solid var(--bui-gray-3);forced-color-adjust:none;padding:var(--bui-space-2)var(--bui-space-3);max-width:240px;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);color:var(--bui-fg-primary);border-radius:4px;outline:none;transition:transform .2s,opacity .2s;transform:translate(0,0);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}--tooltip-offset:var(--bui-space-3)&[data-placement=top]{margin-bottom:var(--tooltip-offset);--origin:translateY(4px)}&[data-placement=right]{margin-left:var(--tooltip-offset);--origin:translateX(-4px)}&[data-placement=bottom]{margin-top:var(--tooltip-offset);--origin:translateY(-4px)}&[data-placement=left]{margin-right:var(--tooltip-offset);--origin:translateX(4px)}}.bui-TooltipArrow{& svg{display:block;& path:first-child{fill:var(--bui-bg-surface-1)}& path:nth-child(2){fill:var(--bui-gray-3)}--tooltip-arrow-overlap:-2px}&[data-placement=top] svg{margin-top:var(--tooltip-arrow-overlap)}&[data-placement=bottom] svg{margin-bottom:var(--tooltip-arrow-overlap);transform:rotate(180deg)}&[data-placement=right] svg{margin-right:var(--tooltip-arrow-overlap);transform:rotate(90deg)}&[data-placement=left] svg{margin-left:var(--tooltip-arrow-overlap);transform:rotate(-90deg)}}[data-theme=dark]{& .bui-Tooltip{background:var(--bui-bg-surface-2);box-shadow:none;border:1px solid var(--bui-gray-4)}& .bui-TooltipArrow{& svg path:first-child{fill:var(--bui-bg-surface-2)}& svg path:nth-child(2){fill:var(--bui-gray-4)}}}.bui-ScrollAreaRoot{box-sizing:border-box;width:100%}.bui-ScrollAreaViewport{overscroll-behavior:contain;height:100%}.bui-ScrollAreaContent{padding-block:.75rem;flex-direction:column;gap:1rem;padding-left:1rem;padding-right:1.5rem;display:flex}.bui-ScrollAreaScrollbar{background-color:var(--bui-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}}.bui-ScrollAreaThumb{border-radius:inherit;background-color:var(--bui-scrollbar-thumb);width:100%}.bui-Select[data-invalid]{& .bui-SelectTrigger{border-color:var(--bui-fg-danger)}}.bui-SelectTrigger{box-sizing:border-box;border-radius:var(--bui-radius-3);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);cursor:pointer;justify-content:space-between;align-items:center;gap:var(--bui-space-2);width:100%;display:flex;& svg{color:var(--bui-fg-secondary);flex-shrink:0}&[data-size=small]{height:2rem;padding-inline:var(--bui-space-3)}&[data-size=medium]{height:3rem;padding-inline:var(--bui-space-4)}&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium] svg{width:1.25rem;height:1.25rem}&::placeholder{color:var(--bui-fg-secondary)}&:hover{border-color:var(--bui-border-hover);transition:border-color .2s ease-in-out,outline-color .2s ease-in-out}&:focus-visible{border-color:var(--bui-border-pressed);outline:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-invalid]:hover,&[data-invalid]:focus-visible{border-width:2px}&[disabled]{cursor:not-allowed;border-color:var(--bui-border-disabled);color:var(--bui-fg-disabled)}&[disabled] .bui-SelectValue{color:var(--bui-fg-disabled)}&[data-popup-open] .bui-SelectIcon{transform:rotate(180deg)}}.bui-SelectValue{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);text-align:left;overflow:hidden;& .bui-SelectItemIndicator{display:none}&[disabled]{color:var(--bui-fg-disabled)}}.bui-SelectItem{width:var(--anchor-width);padding-block:var(--bui-space-2);padding-left:var(--bui-space-3);padding-right:var(--bui-space-4);color:var(--bui-fg-primary);border-radius:var(--bui-radius-3);cursor:pointer;user-select:none;font-size:var(--bui-font-size-3);align-items:center;gap:var(--bui-space-1);outline:none;grid-template-columns:1rem 1fr;grid-template-areas:"icon text";display:grid;position:relative;&[data-focused]{z-index:0;color:var(--bui-fg-primary);position:relative}&[data-focused]:before{content:"";z-index:-1;background-color:var(--bui-bg-tint-hover);border-radius:.25rem;position:absolute;inset-block:0;inset-inline:.25rem}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled)}&[data-selected] .bui-SelectItemIndicator{opacity:1}}.bui-SelectItemIndicator{opacity:0;grid-area:icon;justify-content:center;align-items:center;transition:opacity .2s ease-in-out;display:flex}.bui-SelectItemLabel{flex:1;grid-area:text}.bui-Switch{align-items:center;gap:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary);cursor:pointer;display:flex;position:relative;&[data-pressed] .bui-SwitchIndicator{&:before{background:var(--bui-fg-solid)}}&[data-selected]{& .bui-SwitchIndicator{background:var(--bui-bg-solid);&:before{background:var(--bui-fg-solid);transform:translate(100%)}}&[data-pressed]{& .indicator{background:var(--bui-gray-3)}}}&[data-focus-visible] .bui-SwitchIndicator{outline-offset:2px;outline:2px solid}}.bui-SwitchIndicator{background:var(--bui-gray-3);border:2px;border-radius:1.143rem;width:2rem;height:1.143rem;transition:all .2s;&:before{content:"";background:var(--bui-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/docs-ui/src/app/page.mdx b/docs-ui/src/app/page.mdx index f31cf4524e..ffd3bc9dcb 100644 --- a/docs-ui/src/app/page.mdx +++ b/docs-ui/src/app/page.mdx @@ -85,6 +85,11 @@ building it incrementally with not conflict with the existing theming system. description="A search field component to help you search for items." href="/components/search-field" /> + + +} + code={passwordFieldDefaultSnippet} +/> + +## Usage + + + +## API reference + + + +## Examples + +### Sizes + +We support two different sizes: `small`, `medium`. + +} + code={passwordFieldSizesSnippet} +/> + +### With description + +Here's a simple PasswordField with a description. + +} + code={passwordFieldDescriptionSnippet} +/> + + + + diff --git a/docs-ui/src/content/components/password-field.props.ts b/docs-ui/src/content/components/password-field.props.ts new file mode 100644 index 0000000000..493405b5fd --- /dev/null +++ b/docs-ui/src/content/components/password-field.props.ts @@ -0,0 +1,43 @@ +import { + classNamePropDefs, + stylePropDefs, + type PropDef, +} from '@/utils/propDefs'; + +export const inputPropDefs: Record = { + size: { + type: 'enum', + values: ['small', 'medium'], + default: 'small', + responsive: true, + }, + label: { + type: 'string', + }, + icon: { + type: 'enum', + values: ['ReactNode'], + }, + description: { + type: 'string', + }, + name: { + type: 'string', + required: true, + }, + ...classNamePropDefs, + ...stylePropDefs, +}; + +export const passwordFieldUsageSnippet = `import { PasswordField } from '@backstage/ui'; + +`; + +export const passwordFieldDefaultSnippet = ``; + +export const passwordFieldSizesSnippet = ` + } /> + } /> +`; + +export const passwordFieldDescriptionSnippet = ``; diff --git a/docs-ui/src/snippets/stories-snippets.tsx b/docs-ui/src/snippets/stories-snippets.tsx index 5aa5b8c7d9..5bba3384b5 100644 --- a/docs-ui/src/snippets/stories-snippets.tsx +++ b/docs-ui/src/snippets/stories-snippets.tsx @@ -28,6 +28,7 @@ import * as HeaderStories from '../../../packages/ui/src/components/Header/Heade import * as HeaderPageStories from '../../../packages/ui/src/components/HeaderPage/HeaderPage.stories'; import * as TableStories from '../../../packages/ui/src/components/Table/Table.stories'; import * as TagGroupStories from '../../../packages/ui/src/components/TagGroup/TagGroup.stories'; +import * as PasswordFieldStories from '../../../packages/ui/src/components/PasswordField/PasswordField.stories'; // Helper function to create snippet components // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -53,6 +54,8 @@ export const ContainerSnippet = createSnippetComponent(ContainerStories); export const GridSnippet = createSnippetComponent(GridStories); export const IconSnippet = createSnippetComponent(IconStories); export const TextFieldSnippet = createSnippetComponent(TextFieldStories); +export const PasswordFieldSnippet = + createSnippetComponent(PasswordFieldStories); export const TextSnippet = createSnippetComponent(TextStories); export const FlexSnippet = createSnippetComponent(FlexStories); export const SelectSnippet = createSnippetComponent(SelectStories); diff --git a/docs-ui/src/utils/changelog.ts b/docs-ui/src/utils/changelog.ts index a66997cf26..ef2e6c9fb9 100644 --- a/docs-ui/src/utils/changelog.ts +++ b/docs-ui/src/utils/changelog.ts @@ -25,7 +25,8 @@ export type Component = | 'radio-group' | 'card' | 'skeleton' - | 'header'; + | 'header' + | 'passwordfield'; export type Version = `${number}.${number}.${number}`; diff --git a/docs-ui/src/utils/data.ts b/docs-ui/src/utils/data.ts index 5e7305da28..c1a69e459b 100644 --- a/docs-ui/src/utils/data.ts +++ b/docs-ui/src/utils/data.ts @@ -126,6 +126,11 @@ export const components: Page[] = [ slug: 'menu', status: 'alpha', }, + { + title: 'PasswordField', + slug: 'password-field', + status: 'alpha', + }, { title: 'RadioGroup', slug: 'radio-group', diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index 2816ed7e8f..2d3397f4a1 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -1,6 +1,9 @@ /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ @layer base { - *, :before, :after { + + *, + :before, + :after { box-sizing: border-box; } @@ -15,11 +18,15 @@ margin: 0; } - b, strong { + b, + strong { font-weight: bolder; } - code, kbd, samp, pre { + code, + kbd, + samp, + pre { font-family: ui-monospace, SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace; font-size: 1em; } @@ -28,7 +35,8 @@ font-size: 80%; } - sub, sup { + sub, + sup { vertical-align: baseline; font-size: 75%; line-height: 0; @@ -47,14 +55,21 @@ border-color: currentColor; } - button, input, optgroup, select, textarea { + button, + input, + optgroup, + select, + textarea { margin: 0; font-family: inherit; font-size: 100%; line-height: 1.15; } - button, [type="button"], [type="reset"], [type="submit"] { + button, + [type="button"], + [type="reset"], + [type="submit"] { -webkit-appearance: button; } @@ -66,7 +81,8 @@ vertical-align: baseline; } - ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { + ::-webkit-inner-spin-button, + ::-webkit-outer-spin-button { height: auto; } @@ -157,7 +173,7 @@ padding: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-p { padding: var(--p-xs); } @@ -227,7 +243,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-p { padding: var(--p-sm); } @@ -297,7 +313,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-p { padding: var(--p-md); } @@ -367,7 +383,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-p { padding: var(--p-lg); } @@ -437,7 +453,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-p { padding: var(--p-xl); } @@ -575,7 +591,7 @@ padding-left: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-pl { padding-left: var(--pl-xs); } @@ -645,7 +661,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-pl { padding-left: var(--pl-sm); } @@ -715,7 +731,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-pl { padding-left: var(--pl-md); } @@ -785,7 +801,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-pl { padding-left: var(--pl-lg); } @@ -855,7 +871,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-pl { padding-left: var(--pl-xl); } @@ -993,7 +1009,7 @@ padding-right: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-pr { padding-right: var(--pr-xs); } @@ -1063,7 +1079,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-pr { padding-right: var(--pr-sm); } @@ -1133,7 +1149,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-pr { padding-right: var(--pr-md); } @@ -1203,7 +1219,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-pr { padding-right: var(--pr-lg); } @@ -1273,7 +1289,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-pr { padding-right: var(--pr-xl); } @@ -1411,7 +1427,7 @@ padding-top: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-pt { padding-top: var(--pt-xs); } @@ -1481,7 +1497,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-pt { padding-top: var(--pt-sm); } @@ -1551,7 +1567,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-pt { padding-top: var(--pt-md); } @@ -1621,7 +1637,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-pt { padding-top: var(--pt-lg); } @@ -1691,7 +1707,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-pt { padding-top: var(--pt-xl); } @@ -1829,7 +1845,7 @@ padding-bottom: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-pb { padding-bottom: var(--pb-xs); } @@ -1899,7 +1915,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-pb { padding-bottom: var(--pb-sm); } @@ -1969,7 +1985,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-pb { padding-bottom: var(--pb-md); } @@ -2039,7 +2055,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-pb { padding-bottom: var(--pb-lg); } @@ -2109,7 +2125,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-pb { padding-bottom: var(--pb-xl); } @@ -2264,7 +2280,7 @@ padding-bottom: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-py { padding-top: var(--py-xs); padding-bottom: var(--py-xs); @@ -2351,7 +2367,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-py { padding-top: var(--py-sm); padding-bottom: var(--py-sm); @@ -2438,7 +2454,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-py { padding-top: var(--py-md); padding-bottom: var(--py-md); @@ -2525,7 +2541,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-py { padding-top: var(--py-lg); padding-bottom: var(--py-lg); @@ -2612,7 +2628,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-py { padding-top: var(--py-xl); padding-bottom: var(--py-xl); @@ -2784,7 +2800,7 @@ padding-right: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-px { padding-left: var(--px-xs); padding-right: var(--px-xs); @@ -2871,7 +2887,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-px { padding-left: var(--px-sm); padding-right: var(--px-sm); @@ -2958,7 +2974,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-px { padding-left: var(--px-md); padding-right: var(--px-md); @@ -3045,7 +3061,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-px { padding-left: var(--px-lg); padding-right: var(--px-lg); @@ -3132,7 +3148,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-px { padding-left: var(--px-xl); padding-right: var(--px-xl); @@ -3287,7 +3303,7 @@ margin: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-m { margin: var(--p-xs); } @@ -3357,7 +3373,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-m { margin: var(--p-sm); } @@ -3427,7 +3443,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-m { margin: var(--p-md); } @@ -3497,7 +3513,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-m { margin: var(--p-lg); } @@ -3567,7 +3583,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-m { margin: var(--p-xl); } @@ -3705,7 +3721,7 @@ margin-left: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-ml { margin-left: var(--pl-xs); } @@ -3775,7 +3791,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-ml { margin-left: var(--pl-sm); } @@ -3845,7 +3861,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-ml { margin-left: var(--pl-md); } @@ -3915,7 +3931,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-ml { margin-left: var(--pl-lg); } @@ -3985,7 +4001,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-ml { margin-left: var(--pl-xl); } @@ -4123,7 +4139,7 @@ margin-right: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-mr { margin-right: var(--pr-xs); } @@ -4193,7 +4209,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-mr { margin-right: var(--pr-sm); } @@ -4263,7 +4279,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-mr { margin-right: var(--pr-md); } @@ -4333,7 +4349,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-mr { margin-right: var(--pr-lg); } @@ -4403,7 +4419,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-mr { margin-right: var(--pr-xl); } @@ -4541,7 +4557,7 @@ margin-top: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-mt { margin-top: var(--pt-xs); } @@ -4611,7 +4627,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-mt { margin-top: var(--pt-sm); } @@ -4681,7 +4697,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-mt { margin-top: var(--pt-md); } @@ -4751,7 +4767,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-mt { margin-top: var(--pt-lg); } @@ -4821,7 +4837,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-mt { margin-top: var(--pt-xl); } @@ -4959,7 +4975,7 @@ margin-bottom: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-mb { margin-bottom: var(--pb-xs); } @@ -5029,7 +5045,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-mb { margin-bottom: var(--pb-sm); } @@ -5099,7 +5115,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-mb { margin-bottom: var(--pb-md); } @@ -5169,7 +5185,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-mb { margin-bottom: var(--pb-lg); } @@ -5239,7 +5255,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-mb { margin-bottom: var(--pb-xl); } @@ -5394,7 +5410,7 @@ margin-bottom: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-my { margin-top: var(--py-xs); margin-bottom: var(--py-xs); @@ -5481,7 +5497,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-my { margin-top: var(--py-sm); margin-bottom: var(--py-sm); @@ -5568,7 +5584,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-my { margin-top: var(--py-md); margin-bottom: var(--py-md); @@ -5655,7 +5671,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-my { margin-top: var(--py-lg); margin-bottom: var(--py-lg); @@ -5742,7 +5758,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-my { margin-top: var(--py-xl); margin-bottom: var(--py-xl); @@ -5914,7 +5930,7 @@ margin-right: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-mx { margin-left: var(--px-xs); margin-right: var(--px-xs); @@ -6001,7 +6017,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-mx { margin-left: var(--px-sm); margin-right: var(--px-sm); @@ -6088,7 +6104,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-mx { margin-left: var(--px-md); margin-right: var(--px-md); @@ -6175,7 +6191,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-mx { margin-left: var(--px-lg); margin-right: var(--px-lg); @@ -6262,7 +6278,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-mx { margin-left: var(--px-xl); margin-right: var(--px-xl); @@ -6365,7 +6381,7 @@ display: block; } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-display-none { display: none; } @@ -6383,7 +6399,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-display-none { display: none; } @@ -6401,7 +6417,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-display-none { display: none; } @@ -6419,7 +6435,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-display-none { display: none; } @@ -6437,7 +6453,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-display-none { display: none; } @@ -6467,7 +6483,7 @@ max-width: var(--max-width); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-w { width: var(--width); } @@ -6481,7 +6497,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-w { width: var(--width); } @@ -6495,7 +6511,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-w { width: var(--width); } @@ -6509,7 +6525,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-w { width: var(--width); } @@ -6523,7 +6539,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-w { width: var(--width); } @@ -6549,7 +6565,7 @@ max-height: var(--max-height); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-h { height: var(--height); } @@ -6563,7 +6579,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-h { height: var(--height); } @@ -6577,7 +6593,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-h { height: var(--height); } @@ -6591,7 +6607,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-h { height: var(--height); } @@ -6605,7 +6621,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-h { height: var(--height); } @@ -6639,7 +6655,7 @@ position: static; } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-position-absolute { position: absolute; } @@ -6661,7 +6677,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-position-absolute { position: absolute; } @@ -6683,7 +6699,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-position-absolute { position: absolute; } @@ -6705,7 +6721,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-position-absolute { position: absolute; } @@ -6727,7 +6743,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-position-absolute { position: absolute; } @@ -7017,7 +7033,7 @@ grid-row: span auto / span auto; } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -7287,7 +7303,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -7557,7 +7573,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -7827,7 +7843,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -8097,7 +8113,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -8435,7 +8451,7 @@ gap: var(--bui-space-14); } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-gap { gap: var(--gap-xs); } @@ -8505,7 +8521,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-gap { gap: var(--gap-sm); } @@ -8575,7 +8591,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-gap { gap: var(--gap-md); } @@ -8645,7 +8661,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-gap { gap: var(--gap-lg); } @@ -8715,7 +8731,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-gap { gap: var(--gap-xl); } @@ -8837,7 +8853,7 @@ flex-direction: column-reverse; } -@media (width >= 640px) { +@media (width >=640px) { .xs\:bui-align-start { align-items: start; } @@ -8887,7 +8903,7 @@ } } -@media (width >= 768px) { +@media (width >=768px) { .sm\:bui-align-start { align-items: start; } @@ -8937,7 +8953,7 @@ } } -@media (width >= 1024px) { +@media (width >=1024px) { .md\:bui-align-start { align-items: start; } @@ -8987,7 +9003,7 @@ } } -@media (width >= 1280px) { +@media (width >=1280px) { .lg\:bui-align-start { align-items: start; } @@ -9037,7 +9053,7 @@ } } -@media (width >= 1536px) { +@media (width >=1536px) { .xl\:bui-align-start { align-items: start; } @@ -9440,7 +9456,8 @@ overflow: auto; } -.bui-CardHeader, .bui-CardFooter { +.bui-CardHeader, +.bui-CardFooter { padding-inline: var(--bui-space-3); } @@ -9503,7 +9520,8 @@ display: flex; overflow: hidden; - &[data-starting-style], &[data-ending-style] { + &[data-starting-style], + &[data-ending-style] { height: 0; } } @@ -9515,7 +9533,7 @@ transition: padding .2s ease-in-out; } -@media (width >= 640px) { +@media (width >=640px) { .bui-Container { padding-inline: var(--bui-space-5); } @@ -9663,7 +9681,8 @@ margin-left: -8px; } -.bui-HeaderPageControls, .bui-HeaderPageBreadcrumbs { +.bui-HeaderPageControls, +.bui-HeaderPageBreadcrumbs { align-items: center; gap: var(--bui-space-2); flex-direction: row; @@ -9704,7 +9723,8 @@ display: flex; overflow: hidden; - &[data-entering], &[data-exiting] { + &[data-entering], + &[data-exiting] { transform: var(--origin); opacity: 0; } @@ -9760,7 +9780,8 @@ outline: none; display: flex; - &[data-focused], &[data-open] { + &[data-focused], + &[data-open] { background: var(--bui-bg-surface-2); color: var(--bui-fg-primary); } @@ -9775,7 +9796,7 @@ } &[data-has-submenu] { - & > .bui-MenuItemArrow { + &>.bui-MenuItemArrow { display: block; } } @@ -9800,7 +9821,7 @@ } &[data-selected] .bui-MenuItemListBoxCheck { - & > svg { + &>svg { opacity: 1; color: var(--bui-fg-primary); } @@ -9814,7 +9835,7 @@ height: 1rem; display: flex; - & > svg { + &>svg { opacity: 0; width: 1rem; height: 1rem; @@ -9826,7 +9847,7 @@ gap: var(--bui-space-2); display: flex; - & > svg { + &>svg { width: 1rem; height: 1rem; } @@ -9837,7 +9858,7 @@ height: 1rem; display: none; - & > svg { + &>svg { width: 1rem; height: 1rem; } @@ -9898,7 +9919,8 @@ align-items: center; display: flex; - &::-webkit-search-cancel-button, &::-webkit-search-decoration { + &::-webkit-search-cancel-button, + &::-webkit-search-decoration { -webkit-appearance: none; } } @@ -9919,7 +9941,7 @@ top: 0; bottom: 0; - & > svg { + &>svg { width: 1rem; height: 1rem; } @@ -10015,7 +10037,8 @@ } } - &[data-invalid]:before, &[data-invalid][data-selected]:before { + &[data-invalid]:before, + &[data-invalid][data-selected]:before { border-color: var(--bui-border-danger); } @@ -10109,7 +10132,8 @@ display: inline-flex; } -.bui-TableCellIcon, .bui-TableCellIcon svg { +.bui-TableCellIcon, +.bui-TableCellIcon svg { color: var(--bui-fg-primary); align-items: center; display: inline-flex; @@ -10235,8 +10259,8 @@ .bui-TabActive { content: ""; - left: calc(var(--active-tab-left) + var(--bui-space-2)); - width: calc(var(--active-tab-width) - var(--bui-space-4)); + left: calc(var(--active-tab-left) + var(--bui-space-2)); + width: calc(var(--active-tab-width) - var(--bui-space-4)); background-color: var(--bui-fg-primary); height: 1px; transition: left var(--active-transition-duration) ease-out, opacity .15s ease-out, width var(--active-transition-duration) ease-out; @@ -10249,9 +10273,9 @@ .bui-TabHovered { content: ""; left: var(--hovered-tab-left); - top: calc(var(--hovered-tab-top) + 4px); + top: calc(var(--hovered-tab-top) + 4px); width: var(--hovered-tab-width); - height: calc(var(--hovered-tab-height) - 8px); + height: calc(var(--hovered-tab-height) - 8px); background-color: var(--bui-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; @@ -10419,7 +10443,11 @@ overflow: hidden; } -.bui-Text[data-as="span"], .bui-Text[data-as="label"], .bui-Text[data-as="strong"], .bui-Text[data-as="em"], .bui-Text[data-as="small"] { +.bui-Text[data-as="span"], +.bui-Text[data-as="label"], +.bui-Text[data-as="strong"], +.bui-Text[data-as="em"], +.bui-Text[data-as="small"] { display: inline-block; } @@ -10437,6 +10465,8 @@ flex-shrink: 0; width: 100%; display: flex; + /* Reserve space for browser/password manager icon (e.g. 1Password) */ + --bui-passwordmanager-icon-width: var(--bui-space-1); } .bui-InputWrapper { @@ -10484,6 +10514,35 @@ } } +.bui-InputVisibility { + background-color: transparent; + cursor: pointer; + border: none; + padding: 0; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + color: var(--bui-fg-primary); + + /* Size: small */ + &[data-size="small"] { width: 2rem; height: 2rem; } + &[data-size="small"] svg { width: 1rem; height: 1rem; } + + /* Size: medium */ + &[data-size="medium"] { width: 2.5rem; height: 2.5rem; } + &[data-size="medium"] svg { width: 1.25rem; height: 1.25rem; } +} + +/* Ensure input has enough right padding for our toggle + PM icon */ +.bui-PasswordField .bui-InputWrapper[data-size='small'] .bui-Input { + padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); +} + +.bui-PasswordField .bui-InputWrapper[data-size='medium'] .bui-Input { + padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); +} + .bui-InputIcon { left: var(--bui-space-3); margin-right: var(--bui-space-1); @@ -10495,12 +10554,14 @@ top: 50%; transform: translateY(-50%); - &[data-size="small"], &[data-size="small"] svg { + &[data-size="small"], + &[data-size="small"] svg { width: 1rem; height: 1rem; } - &[data-size="medium"], &[data-size="medium"] svg { + &[data-size="medium"], + &[data-size="medium"] svg { width: 1.25rem; height: 1.25rem; } @@ -10522,7 +10583,8 @@ transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; display: flex; - &::-webkit-search-cancel-button, &::-webkit-search-decoration { + &::-webkit-search-cancel-button, + &::-webkit-search-decoration { -webkit-appearance: none; } @@ -10701,7 +10763,8 @@ transform: translate3d(0, 0, 0); box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a; - &[data-entering], &[data-exiting] { + &[data-entering], + &[data-exiting] { transform: var(--origin); opacity: 0; } @@ -10811,7 +10874,8 @@ transition: opacity .15s .3s; display: flex; - &[data-hovering], &[data-scrolling] { + &[data-hovering], + &[data-scrolling] { opacity: 1; transition-duration: 75ms; transition-delay: 0s; @@ -10892,7 +10956,8 @@ border-color: var(--bui-fg-danger); } - &[data-invalid]:hover, &[data-invalid]:focus-visible { + &[data-invalid]:hover, + &[data-invalid]:focus-visible { border-width: 2px; } @@ -11045,4 +11110,4 @@ transition: all .2s; display: block; } -} +} \ No newline at end of file diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 5d04bf8626..00dd6d4d42 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -643,6 +643,17 @@ export const componentDefinitions: { readonly inputWrapper: 'bui-InputWrapper'; readonly input: 'bui-Input'; readonly inputIcon: 'bui-InputIcon'; + readonly inputAction: 'bui-InputAction'; + }; + readonly dataAttributes: { + readonly invalid: readonly [true, false]; + readonly disabled: readonly [true, false]; + }; + }; + readonly PasswordField: { + readonly classNames: { + readonly root: 'bui-PasswordField'; + readonly inputVisibility: 'bui-InputVisibility'; }; readonly dataAttributes: { readonly invalid: readonly [true, false]; @@ -1760,6 +1771,7 @@ export interface TextFieldProps icon?: ReactNode; placeholder?: string; size?: 'small' | 'medium' | Partial>; + type?: 'text' | 'email' | 'tel' | 'url'; } // @public (undocumented) diff --git a/packages/ui/src/components/PasswordField/PasswordField.styles.css b/packages/ui/src/components/PasswordField/PasswordField.styles.css index e4d0d2f792..371d769ea6 100644 --- a/packages/ui/src/components/PasswordField/PasswordField.styles.css +++ b/packages/ui/src/components/PasswordField/PasswordField.styles.css @@ -20,122 +20,51 @@ font-family: var(--bui-font-regular); width: 100%; flex-shrink: 0; + /* Reserve space for browser/password manager icon (e.g. 1Password) */ + --bui-passwordmanager-icon-width: var(--bui-space-1); } -.bui-InputWrapper { - position: relative; - - &[data-size='small'] .bui-Input { - height: 2rem; - } - - &[data-size='medium'] .bui-Input { - height: 2.5rem; - } - - &[data-size='small'] .bui-Input[data-icon] { - padding-left: var(--bui-space-8); - } - - &[data-size='medium'] .bui-Input[data-icon] { - padding-left: var(--bui-space-9); - } -} - -.bui-InputIcon { +.bui-InputVisibility { position: absolute; - left: var(--bui-space-3); - top: 50%; - transform: translateY(-50%); - margin-right: var(--bui-space-1); - color: var(--bui-fg-primary); - flex-shrink: 0; - pointer-events: none; - /* To animate the icon when the input is collapsed */ - transition: left 0.2s ease-in-out; - - &[data-size='small'], - &[data-size='small'] svg { - width: 1rem; - height: 1rem; - } - - &[data-size='medium'], - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; - } -} - -.bui-Input { + right: var(--bui-passwordmanager-icon-width); + top: 0; + bottom: 0; + background-color: transparent; + cursor: pointer; + border: none; + padding: 0; + margin: 0; display: flex; align-items: center; - padding: 0 var(--bui-space-3); - border-radius: var(--bui-radius-2); - border: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); + justify-content: center; color: var(--bui-fg-primary); - transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; - width: 100%; - height: 100%; - cursor: inherit; - &::-webkit-search-cancel-button, - &::-webkit-search-decoration { - -webkit-appearance: none; + /* Size: small */ + &[data-size='small'] { + width: 2rem; + height: 2rem; } - - &::placeholder { - color: var(--bui-fg-secondary); - } - - &[data-focused] { - outline-color: var(--bui-border-pressed); - outline-width: 0px; - } - - &[data-hovered] { - border-color: var(--bui-border-hover); - } - - &[data-focused] { - border-color: var(--bui-border-pressed); - outline-width: 0px; - } - - &[data-invalid] { - border-color: var(--bui-fg-danger); - } - - &[data-disabled] { - opacity: 0.5; - cursor: not-allowed; - border: 1px solid var(--bui-border-disabled); - } -} - -.bui-InputAction { - position: absolute; - right: var(--bui-space-1); - top: 50%; - transform: translateY(-50%); - color: var(--bui-fg-primary); - flex-shrink: 0; - /* To animate the icon when the input is collapsed */ - transition: right 0.2s ease-in-out; - - &[data-size='small'], &[data-size='small'] svg { width: 1rem; height: 1rem; } - &[data-size='medium'], + /* Size: medium */ + &[data-size='medium'] { + width: 2.5rem; + height: 2.5rem; + } &[data-size='medium'] svg { width: 1.25rem; height: 1.25rem; } } + +/* Ensure input has enough right padding for our toggle + PM icon */ +.bui-PasswordField .bui-InputWrapper[data-size='small'] .bui-Input { + padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); +} + +.bui-PasswordField .bui-InputWrapper[data-size='medium'] .bui-Input { + padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); +} diff --git a/packages/ui/src/components/PasswordField/PasswordField.tsx b/packages/ui/src/components/PasswordField/PasswordField.tsx index 46b907c010..fc5dae1088 100644 --- a/packages/ui/src/components/PasswordField/PasswordField.tsx +++ b/packages/ui/src/components/PasswordField/PasswordField.tsx @@ -15,15 +15,18 @@ */ import { forwardRef, useEffect, useState } from 'react'; -import { Input, TextField as AriaTextField } from 'react-aria-components'; +import { + Input, + TextField as AriaTextField, + Button as RAButton, +} from 'react-aria-components'; import clsx from 'clsx'; import { FieldLabel } from '../FieldLabel'; import { FieldError } from '../FieldError'; import type { PasswordFieldProps } from './types'; import { useStyles } from '../../hooks/useStyles'; -import { Icon } from '../Icon'; -import { ButtonIcon } from '../ButtonIcon'; +import { RiEyeLine, RiEyeOffLine } from '@remixicon/react'; /** @public */ export const PasswordField = forwardRef( @@ -50,9 +53,14 @@ export const PasswordField = forwardRef( } }, [label, ariaLabel, ariaLabelledBy]); - const { classNames, dataAttributes } = useStyles('PasswordField', { - size, - }); + const { classNames: passwordFieldClassNames, dataAttributes } = useStyles( + 'PasswordField', + { + size, + }, + ); + + const { classNames: textFieldClassNames } = useStyles('TextField', {}); // If a secondary label is provided, use it. Otherwise, use 'Required' if the field is required. const secondaryLabelText = @@ -63,10 +71,11 @@ export const PasswordField = forwardRef( return ( @@ -76,29 +85,33 @@ export const PasswordField = forwardRef( description={description} />
{icon && ( )} -
- + setIsVisible(v => !v)} - icon={} - /> + className={passwordFieldClassNames.inputVisibility} + > + {isVisible ? : } +
( } }, [label, ariaLabel, ariaLabelledBy]); - useEffect(() => { - const inputType = (props as { type?: string }).type; - if (inputType === 'search') { - console.warn( - 'TextField type="search" is deprecated. Use SearchField instead.', - ); - } - if (inputType === 'password') { - console.warn( - 'TextField type="password" is deprecated. Use PasswordField instead.', - ); - } - }, [props]); - const { classNames, dataAttributes } = useStyles('TextField', { size, }); diff --git a/packages/ui/src/components/TextField/types.ts b/packages/ui/src/components/TextField/types.ts index 0c34634e2d..b971ef8d26 100644 --- a/packages/ui/src/components/TextField/types.ts +++ b/packages/ui/src/components/TextField/types.ts @@ -27,18 +27,10 @@ export interface TextFieldProps * The HTML input type for the text field * * @remarks - * The values 'search' and 'password' are deprecated. Use `SearchField` for + * Use `SearchField` for * search inputs and `PasswordField` for password inputs. */ - type?: - | 'text' - | 'email' - | 'tel' - | 'url' - /** @deprecated Use `SearchField` instead */ - | 'search' - /** @deprecated Use `PasswordField` instead */ - | 'password'; + type?: 'text' | 'email' | 'tel' | 'url'; /** * An icon to render before the input */ diff --git a/packages/ui/src/utils/componentDefinitions.ts b/packages/ui/src/utils/componentDefinitions.ts index f67ee781dc..ff91831cc4 100644 --- a/packages/ui/src/utils/componentDefinitions.ts +++ b/packages/ui/src/utils/componentDefinitions.ts @@ -296,10 +296,7 @@ export const componentDefinitions = { PasswordField: { classNames: { root: 'bui-PasswordField', - inputWrapper: 'bui-InputWrapper', - input: 'bui-Input', - inputIcon: 'bui-InputIcon', - inputAction: 'bui-InputAction', + inputVisibility: 'bui-InputVisibility', }, dataAttributes: { invalid: [true, false] as const, From ba406d91f3250125cdc1c65efe85da79d8569e4d Mon Sep 17 00:00:00 2001 From: birdhb Date: Fri, 26 Sep 2025 11:43:13 +0100 Subject: [PATCH 048/244] Update eighty-cows-care.md Signed-off-by: birdhb --- .changeset/eighty-cows-care.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/eighty-cows-care.md b/.changeset/eighty-cows-care.md index 8fd5c0adb0..e03b364449 100644 --- a/.changeset/eighty-cows-care.md +++ b/.changeset/eighty-cows-care.md @@ -1,5 +1,5 @@ --- -'@backstage/ui': patch +'@backstage/ui': minor --- -Added PasswordField to BUI with default show/hide visibility on text input +Added PasswordField to BUI with default show/hide visibility on input From c953ee97882ebc9aceebbb86ce9454592b9afe13 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Fri, 26 Sep 2025 13:55:45 +0100 Subject: [PATCH 049/244] remove formatting on style css Signed-off-by: Hermione Bird --- packages/ui/css/styles.css | 312 +++++++++++++++++-------------------- 1 file changed, 139 insertions(+), 173 deletions(-) diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index 2d3397f4a1..0554276dc2 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -1,9 +1,6 @@ /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ @layer base { - - *, - :before, - :after { + *, :before, :after { box-sizing: border-box; } @@ -18,15 +15,11 @@ margin: 0; } - b, - strong { + b, strong { font-weight: bolder; } - code, - kbd, - samp, - pre { + code, kbd, samp, pre { font-family: ui-monospace, SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace; font-size: 1em; } @@ -35,8 +28,7 @@ font-size: 80%; } - sub, - sup { + sub, sup { vertical-align: baseline; font-size: 75%; line-height: 0; @@ -55,21 +47,14 @@ border-color: currentColor; } - button, - input, - optgroup, - select, - textarea { + button, input, optgroup, select, textarea { margin: 0; font-family: inherit; font-size: 100%; line-height: 1.15; } - button, - [type="button"], - [type="reset"], - [type="submit"] { + button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } @@ -81,8 +66,7 @@ vertical-align: baseline; } - ::-webkit-inner-spin-button, - ::-webkit-outer-spin-button { + ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { height: auto; } @@ -173,7 +157,7 @@ padding: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-p { padding: var(--p-xs); } @@ -243,7 +227,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-p { padding: var(--p-sm); } @@ -313,7 +297,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-p { padding: var(--p-md); } @@ -383,7 +367,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-p { padding: var(--p-lg); } @@ -453,7 +437,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-p { padding: var(--p-xl); } @@ -591,7 +575,7 @@ padding-left: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-pl { padding-left: var(--pl-xs); } @@ -661,7 +645,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-pl { padding-left: var(--pl-sm); } @@ -731,7 +715,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-pl { padding-left: var(--pl-md); } @@ -801,7 +785,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-pl { padding-left: var(--pl-lg); } @@ -871,7 +855,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-pl { padding-left: var(--pl-xl); } @@ -1009,7 +993,7 @@ padding-right: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-pr { padding-right: var(--pr-xs); } @@ -1079,7 +1063,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-pr { padding-right: var(--pr-sm); } @@ -1149,7 +1133,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-pr { padding-right: var(--pr-md); } @@ -1219,7 +1203,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-pr { padding-right: var(--pr-lg); } @@ -1289,7 +1273,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-pr { padding-right: var(--pr-xl); } @@ -1427,7 +1411,7 @@ padding-top: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-pt { padding-top: var(--pt-xs); } @@ -1497,7 +1481,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-pt { padding-top: var(--pt-sm); } @@ -1567,7 +1551,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-pt { padding-top: var(--pt-md); } @@ -1637,7 +1621,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-pt { padding-top: var(--pt-lg); } @@ -1707,7 +1691,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-pt { padding-top: var(--pt-xl); } @@ -1845,7 +1829,7 @@ padding-bottom: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-pb { padding-bottom: var(--pb-xs); } @@ -1915,7 +1899,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-pb { padding-bottom: var(--pb-sm); } @@ -1985,7 +1969,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-pb { padding-bottom: var(--pb-md); } @@ -2055,7 +2039,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-pb { padding-bottom: var(--pb-lg); } @@ -2125,7 +2109,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-pb { padding-bottom: var(--pb-xl); } @@ -2280,7 +2264,7 @@ padding-bottom: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-py { padding-top: var(--py-xs); padding-bottom: var(--py-xs); @@ -2367,7 +2351,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-py { padding-top: var(--py-sm); padding-bottom: var(--py-sm); @@ -2454,7 +2438,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-py { padding-top: var(--py-md); padding-bottom: var(--py-md); @@ -2541,7 +2525,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-py { padding-top: var(--py-lg); padding-bottom: var(--py-lg); @@ -2628,7 +2612,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-py { padding-top: var(--py-xl); padding-bottom: var(--py-xl); @@ -2800,7 +2784,7 @@ padding-right: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-px { padding-left: var(--px-xs); padding-right: var(--px-xs); @@ -2887,7 +2871,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-px { padding-left: var(--px-sm); padding-right: var(--px-sm); @@ -2974,7 +2958,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-px { padding-left: var(--px-md); padding-right: var(--px-md); @@ -3061,7 +3045,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-px { padding-left: var(--px-lg); padding-right: var(--px-lg); @@ -3148,7 +3132,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-px { padding-left: var(--px-xl); padding-right: var(--px-xl); @@ -3303,7 +3287,7 @@ margin: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-m { margin: var(--p-xs); } @@ -3373,7 +3357,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-m { margin: var(--p-sm); } @@ -3443,7 +3427,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-m { margin: var(--p-md); } @@ -3513,7 +3497,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-m { margin: var(--p-lg); } @@ -3583,7 +3567,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-m { margin: var(--p-xl); } @@ -3721,7 +3705,7 @@ margin-left: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-ml { margin-left: var(--pl-xs); } @@ -3791,7 +3775,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-ml { margin-left: var(--pl-sm); } @@ -3861,7 +3845,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-ml { margin-left: var(--pl-md); } @@ -3931,7 +3915,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-ml { margin-left: var(--pl-lg); } @@ -4001,7 +3985,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-ml { margin-left: var(--pl-xl); } @@ -4139,7 +4123,7 @@ margin-right: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-mr { margin-right: var(--pr-xs); } @@ -4209,7 +4193,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-mr { margin-right: var(--pr-sm); } @@ -4279,7 +4263,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-mr { margin-right: var(--pr-md); } @@ -4349,7 +4333,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-mr { margin-right: var(--pr-lg); } @@ -4419,7 +4403,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-mr { margin-right: var(--pr-xl); } @@ -4557,7 +4541,7 @@ margin-top: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-mt { margin-top: var(--pt-xs); } @@ -4627,7 +4611,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-mt { margin-top: var(--pt-sm); } @@ -4697,7 +4681,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-mt { margin-top: var(--pt-md); } @@ -4767,7 +4751,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-mt { margin-top: var(--pt-lg); } @@ -4837,7 +4821,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-mt { margin-top: var(--pt-xl); } @@ -4975,7 +4959,7 @@ margin-bottom: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-mb { margin-bottom: var(--pb-xs); } @@ -5045,7 +5029,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-mb { margin-bottom: var(--pb-sm); } @@ -5115,7 +5099,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-mb { margin-bottom: var(--pb-md); } @@ -5185,7 +5169,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-mb { margin-bottom: var(--pb-lg); } @@ -5255,7 +5239,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-mb { margin-bottom: var(--pb-xl); } @@ -5410,7 +5394,7 @@ margin-bottom: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-my { margin-top: var(--py-xs); margin-bottom: var(--py-xs); @@ -5497,7 +5481,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-my { margin-top: var(--py-sm); margin-bottom: var(--py-sm); @@ -5584,7 +5568,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-my { margin-top: var(--py-md); margin-bottom: var(--py-md); @@ -5671,7 +5655,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-my { margin-top: var(--py-lg); margin-bottom: var(--py-lg); @@ -5758,7 +5742,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-my { margin-top: var(--py-xl); margin-bottom: var(--py-xl); @@ -5930,7 +5914,7 @@ margin-right: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-mx { margin-left: var(--px-xs); margin-right: var(--px-xs); @@ -6017,7 +6001,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-mx { margin-left: var(--px-sm); margin-right: var(--px-sm); @@ -6104,7 +6088,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-mx { margin-left: var(--px-md); margin-right: var(--px-md); @@ -6191,7 +6175,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-mx { margin-left: var(--px-lg); margin-right: var(--px-lg); @@ -6278,7 +6262,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-mx { margin-left: var(--px-xl); margin-right: var(--px-xl); @@ -6381,7 +6365,7 @@ display: block; } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-display-none { display: none; } @@ -6399,7 +6383,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-display-none { display: none; } @@ -6417,7 +6401,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-display-none { display: none; } @@ -6435,7 +6419,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-display-none { display: none; } @@ -6453,7 +6437,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-display-none { display: none; } @@ -6483,7 +6467,7 @@ max-width: var(--max-width); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-w { width: var(--width); } @@ -6497,7 +6481,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-w { width: var(--width); } @@ -6511,7 +6495,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-w { width: var(--width); } @@ -6525,7 +6509,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-w { width: var(--width); } @@ -6539,7 +6523,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-w { width: var(--width); } @@ -6565,7 +6549,7 @@ max-height: var(--max-height); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-h { height: var(--height); } @@ -6579,7 +6563,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-h { height: var(--height); } @@ -6593,7 +6577,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-h { height: var(--height); } @@ -6607,7 +6591,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-h { height: var(--height); } @@ -6621,7 +6605,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-h { height: var(--height); } @@ -6655,7 +6639,7 @@ position: static; } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-position-absolute { position: absolute; } @@ -6677,7 +6661,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-position-absolute { position: absolute; } @@ -6699,7 +6683,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-position-absolute { position: absolute; } @@ -6721,7 +6705,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-position-absolute { position: absolute; } @@ -6743,7 +6727,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-position-absolute { position: absolute; } @@ -7033,7 +7017,7 @@ grid-row: span auto / span auto; } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -7303,7 +7287,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -7573,7 +7557,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -7843,7 +7827,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -8113,7 +8097,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } @@ -8451,7 +8435,7 @@ gap: var(--bui-space-14); } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-gap { gap: var(--gap-xs); } @@ -8521,7 +8505,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-gap { gap: var(--gap-sm); } @@ -8591,7 +8575,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-gap { gap: var(--gap-md); } @@ -8661,7 +8645,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-gap { gap: var(--gap-lg); } @@ -8731,7 +8715,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-gap { gap: var(--gap-xl); } @@ -8853,7 +8837,7 @@ flex-direction: column-reverse; } -@media (width >=640px) { +@media (width >= 640px) { .xs\:bui-align-start { align-items: start; } @@ -8903,7 +8887,7 @@ } } -@media (width >=768px) { +@media (width >= 768px) { .sm\:bui-align-start { align-items: start; } @@ -8953,7 +8937,7 @@ } } -@media (width >=1024px) { +@media (width >= 1024px) { .md\:bui-align-start { align-items: start; } @@ -9003,7 +8987,7 @@ } } -@media (width >=1280px) { +@media (width >= 1280px) { .lg\:bui-align-start { align-items: start; } @@ -9053,7 +9037,7 @@ } } -@media (width >=1536px) { +@media (width >= 1536px) { .xl\:bui-align-start { align-items: start; } @@ -9456,8 +9440,7 @@ overflow: auto; } -.bui-CardHeader, -.bui-CardFooter { +.bui-CardHeader, .bui-CardFooter { padding-inline: var(--bui-space-3); } @@ -9520,8 +9503,7 @@ display: flex; overflow: hidden; - &[data-starting-style], - &[data-ending-style] { + &[data-starting-style], &[data-ending-style] { height: 0; } } @@ -9533,7 +9515,7 @@ transition: padding .2s ease-in-out; } -@media (width >=640px) { +@media (width >= 640px) { .bui-Container { padding-inline: var(--bui-space-5); } @@ -9681,8 +9663,7 @@ margin-left: -8px; } -.bui-HeaderPageControls, -.bui-HeaderPageBreadcrumbs { +.bui-HeaderPageControls, .bui-HeaderPageBreadcrumbs { align-items: center; gap: var(--bui-space-2); flex-direction: row; @@ -9723,8 +9704,7 @@ display: flex; overflow: hidden; - &[data-entering], - &[data-exiting] { + &[data-entering], &[data-exiting] { transform: var(--origin); opacity: 0; } @@ -9780,8 +9760,7 @@ outline: none; display: flex; - &[data-focused], - &[data-open] { + &[data-focused], &[data-open] { background: var(--bui-bg-surface-2); color: var(--bui-fg-primary); } @@ -9796,7 +9775,7 @@ } &[data-has-submenu] { - &>.bui-MenuItemArrow { + & > .bui-MenuItemArrow { display: block; } } @@ -9821,7 +9800,7 @@ } &[data-selected] .bui-MenuItemListBoxCheck { - &>svg { + & > svg { opacity: 1; color: var(--bui-fg-primary); } @@ -9835,7 +9814,7 @@ height: 1rem; display: flex; - &>svg { + & > svg { opacity: 0; width: 1rem; height: 1rem; @@ -9847,7 +9826,7 @@ gap: var(--bui-space-2); display: flex; - &>svg { + & > svg { width: 1rem; height: 1rem; } @@ -9858,7 +9837,7 @@ height: 1rem; display: none; - &>svg { + & > svg { width: 1rem; height: 1rem; } @@ -9919,8 +9898,7 @@ align-items: center; display: flex; - &::-webkit-search-cancel-button, - &::-webkit-search-decoration { + &::-webkit-search-cancel-button, &::-webkit-search-decoration { -webkit-appearance: none; } } @@ -9941,7 +9919,7 @@ top: 0; bottom: 0; - &>svg { + & > svg { width: 1rem; height: 1rem; } @@ -10037,8 +10015,7 @@ } } - &[data-invalid]:before, - &[data-invalid][data-selected]:before { + &[data-invalid]:before, &[data-invalid][data-selected]:before { border-color: var(--bui-border-danger); } @@ -10132,8 +10109,7 @@ display: inline-flex; } -.bui-TableCellIcon, -.bui-TableCellIcon svg { +.bui-TableCellIcon, .bui-TableCellIcon svg { color: var(--bui-fg-primary); align-items: center; display: inline-flex; @@ -10259,8 +10235,8 @@ .bui-TabActive { content: ""; - left: calc(var(--active-tab-left) + var(--bui-space-2)); - width: calc(var(--active-tab-width) - var(--bui-space-4)); + left: calc(var(--active-tab-left) + var(--bui-space-2)); + width: calc(var(--active-tab-width) - var(--bui-space-4)); background-color: var(--bui-fg-primary); height: 1px; transition: left var(--active-transition-duration) ease-out, opacity .15s ease-out, width var(--active-transition-duration) ease-out; @@ -10273,9 +10249,9 @@ .bui-TabHovered { content: ""; left: var(--hovered-tab-left); - top: calc(var(--hovered-tab-top) + 4px); + top: calc(var(--hovered-tab-top) + 4px); width: var(--hovered-tab-width); - height: calc(var(--hovered-tab-height) - 8px); + height: calc(var(--hovered-tab-height) - 8px); background-color: var(--bui-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; @@ -10443,11 +10419,7 @@ overflow: hidden; } -.bui-Text[data-as="span"], -.bui-Text[data-as="label"], -.bui-Text[data-as="strong"], -.bui-Text[data-as="em"], -.bui-Text[data-as="small"] { +.bui-Text[data-as="span"], .bui-Text[data-as="label"], .bui-Text[data-as="strong"], .bui-Text[data-as="em"], .bui-Text[data-as="small"] { display: inline-block; } @@ -10554,14 +10526,12 @@ top: 50%; transform: translateY(-50%); - &[data-size="small"], - &[data-size="small"] svg { + &[data-size="small"], &[data-size="small"] svg { width: 1rem; height: 1rem; } - &[data-size="medium"], - &[data-size="medium"] svg { + &[data-size="medium"], &[data-size="medium"] svg { width: 1.25rem; height: 1.25rem; } @@ -10583,8 +10553,7 @@ transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; display: flex; - &::-webkit-search-cancel-button, - &::-webkit-search-decoration { + &::-webkit-search-cancel-button, &::-webkit-search-decoration { -webkit-appearance: none; } @@ -10763,8 +10732,7 @@ transform: translate3d(0, 0, 0); box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a; - &[data-entering], - &[data-exiting] { + &[data-entering], &[data-exiting] { transform: var(--origin); opacity: 0; } @@ -10874,8 +10842,7 @@ transition: opacity .15s .3s; display: flex; - &[data-hovering], - &[data-scrolling] { + &[data-hovering], &[data-scrolling] { opacity: 1; transition-duration: 75ms; transition-delay: 0s; @@ -10956,8 +10923,7 @@ border-color: var(--bui-fg-danger); } - &[data-invalid]:hover, - &[data-invalid]:focus-visible { + &[data-invalid]:hover, &[data-invalid]:focus-visible { border-width: 2px; } @@ -11110,4 +11076,4 @@ transition: all .2s; display: block; } -} \ No newline at end of file +} From b5ee96aaaec19213bdd2ad9875ed07a3f4e2be50 Mon Sep 17 00:00:00 2001 From: birdhb Date: Fri, 26 Sep 2025 14:30:13 +0100 Subject: [PATCH 050/244] Update eighty-cows-care.md Signed-off-by: birdhb --- .changeset/eighty-cows-care.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eighty-cows-care.md b/.changeset/eighty-cows-care.md index e03b364449..73ec239b36 100644 --- a/.changeset/eighty-cows-care.md +++ b/.changeset/eighty-cows-care.md @@ -2,4 +2,4 @@ '@backstage/ui': minor --- -Added PasswordField to BUI with default show/hide visibility on input +**Breaking** We are adding a new component `PasswordField`. We will be removing support for types `password` and `search` on `TextField`. From 683574f888860c1fff2ea693ee797d60f680295d Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Fri, 26 Sep 2025 15:28:01 +0100 Subject: [PATCH 051/244] format componentDefinitions Signed-off-by: Hermione Bird --- packages/ui/report.api.md | 16 ++++++---------- packages/ui/src/utils/componentDefinitions.ts | 16 ++++++---------- 2 files changed, 12 insertions(+), 20 deletions(-) diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 00dd6d4d42..c3aca2718d 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -525,6 +525,12 @@ export const componentDefinitions: { readonly emptyState: 'bui-MenuEmptyState'; }; }; + readonly PasswordField: { + readonly classNames: { + readonly root: 'bui-PasswordField'; + readonly inputVisibility: 'bui-InputVisibility'; + }; + }; readonly Popover: { readonly classNames: { readonly root: 'bui-Popover'; @@ -650,16 +656,6 @@ export const componentDefinitions: { readonly disabled: readonly [true, false]; }; }; - readonly PasswordField: { - readonly classNames: { - readonly root: 'bui-PasswordField'; - readonly inputVisibility: 'bui-InputVisibility'; - }; - readonly dataAttributes: { - readonly invalid: readonly [true, false]; - readonly disabled: readonly [true, false]; - }; - }; readonly Tooltip: { readonly classNames: { readonly tooltip: 'bui-Tooltip'; diff --git a/packages/ui/src/utils/componentDefinitions.ts b/packages/ui/src/utils/componentDefinitions.ts index ff91831cc4..931bfacca7 100644 --- a/packages/ui/src/utils/componentDefinitions.ts +++ b/packages/ui/src/utils/componentDefinitions.ts @@ -174,6 +174,12 @@ export const componentDefinitions = { emptyState: 'bui-MenuEmptyState', }, }, + PasswordField: { + classNames: { + root: 'bui-PasswordField', + inputVisibility: 'bui-InputVisibility', + }, + }, Popover: { classNames: { root: 'bui-Popover', @@ -293,16 +299,6 @@ export const componentDefinitions = { disabled: [true, false] as const, }, }, - PasswordField: { - classNames: { - root: 'bui-PasswordField', - inputVisibility: 'bui-InputVisibility', - }, - dataAttributes: { - invalid: [true, false] as const, - disabled: [true, false] as const, - }, - }, Tooltip: { classNames: { tooltip: 'bui-Tooltip', From 9912c21afa29287a2f2507b389efcaff1db388d2 Mon Sep 17 00:00:00 2001 From: Hermione Bird Date: Fri, 26 Sep 2025 15:40:19 +0100 Subject: [PATCH 052/244] fix ci install build bui Signed-off-by: Hermione Bird --- docs-ui/public/theme-backstage.css | 2 +- packages/ui/css/styles.css | 117 +++++++++++++---------------- 2 files changed, 54 insertions(+), 65 deletions(-) diff --git a/docs-ui/public/theme-backstage.css b/docs-ui/public/theme-backstage.css index 69cd0dbd31..9d9c282f5c 100644 --- a/docs-ui/public/theme-backstage.css +++ b/docs-ui/public/theme-backstage.css @@ -1,2 +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}}.bui-p{padding:var(--p)}.bui-p-0\.5{padding:var(--bui-space-0_5)}.bui-p-1{padding:var(--bui-space-1)}.bui-p-1\.5{padding:var(--bui-space-1_5)}.bui-p-2{padding:var(--bui-space-2)}.bui-p-3{padding:var(--bui-space-3)}.bui-p-4{padding:var(--bui-space-4)}.bui-p-5{padding:var(--bui-space-5)}.bui-p-6{padding:var(--bui-space-6)}.bui-p-7{padding:var(--bui-space-7)}.bui-p-8{padding:var(--bui-space-8)}.bui-p-9{padding:var(--bui-space-9)}.bui-p-10{padding:var(--bui-space-10)}.bui-p-11{padding:var(--bui-space-11)}.bui-p-12{padding:var(--bui-space-12)}.bui-p-13{padding:var(--bui-space-13)}.bui-p-14{padding:var(--bui-space-14)}@media (width>=640px){.xs\:bui-p{padding:var(--p-xs)}.xs\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xs\:bui-p-1{padding:var(--bui-space-1)}.xs\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xs\:bui-p-2{padding:var(--bui-space-2)}.xs\:bui-p-3{padding:var(--bui-space-3)}.xs\:bui-p-4{padding:var(--bui-space-4)}.xs\:bui-p-5{padding:var(--bui-space-5)}.xs\:bui-p-6{padding:var(--bui-space-6)}.xs\:bui-p-7{padding:var(--bui-space-7)}.xs\:bui-p-8{padding:var(--bui-space-8)}.xs\:bui-p-9{padding:var(--bui-space-9)}.xs\:bui-p-10{padding:var(--bui-space-10)}.xs\:bui-p-11{padding:var(--bui-space-11)}.xs\:bui-p-12{padding:var(--bui-space-12)}.xs\:bui-p-13{padding:var(--bui-space-13)}.xs\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-p{padding:var(--p-sm)}.sm\:bui-p-0\.5{padding:var(--bui-space-0_5)}.sm\:bui-p-1{padding:var(--bui-space-1)}.sm\:bui-p-1\.5{padding:var(--bui-space-1_5)}.sm\:bui-p-2{padding:var(--bui-space-2)}.sm\:bui-p-3{padding:var(--bui-space-3)}.sm\:bui-p-4{padding:var(--bui-space-4)}.sm\:bui-p-5{padding:var(--bui-space-5)}.sm\:bui-p-6{padding:var(--bui-space-6)}.sm\:bui-p-7{padding:var(--bui-space-7)}.sm\:bui-p-8{padding:var(--bui-space-8)}.sm\:bui-p-9{padding:var(--bui-space-9)}.sm\:bui-p-10{padding:var(--bui-space-10)}.sm\:bui-p-11{padding:var(--bui-space-11)}.sm\:bui-p-12{padding:var(--bui-space-12)}.sm\:bui-p-13{padding:var(--bui-space-13)}.sm\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-p{padding:var(--p-md)}.md\:bui-p-0\.5{padding:var(--bui-space-0_5)}.md\:bui-p-1{padding:var(--bui-space-1)}.md\:bui-p-1\.5{padding:var(--bui-space-1_5)}.md\:bui-p-2{padding:var(--bui-space-2)}.md\:bui-p-3{padding:var(--bui-space-3)}.md\:bui-p-4{padding:var(--bui-space-4)}.md\:bui-p-5{padding:var(--bui-space-5)}.md\:bui-p-6{padding:var(--bui-space-6)}.md\:bui-p-7{padding:var(--bui-space-7)}.md\:bui-p-8{padding:var(--bui-space-8)}.md\:bui-p-9{padding:var(--bui-space-9)}.md\:bui-p-10{padding:var(--bui-space-10)}.md\:bui-p-11{padding:var(--bui-space-11)}.md\:bui-p-12{padding:var(--bui-space-12)}.md\:bui-p-13{padding:var(--bui-space-13)}.md\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-p{padding:var(--p-lg)}.lg\:bui-p-0\.5{padding:var(--bui-space-0_5)}.lg\:bui-p-1{padding:var(--bui-space-1)}.lg\:bui-p-1\.5{padding:var(--bui-space-1_5)}.lg\:bui-p-2{padding:var(--bui-space-2)}.lg\:bui-p-3{padding:var(--bui-space-3)}.lg\:bui-p-4{padding:var(--bui-space-4)}.lg\:bui-p-5{padding:var(--bui-space-5)}.lg\:bui-p-6{padding:var(--bui-space-6)}.lg\:bui-p-7{padding:var(--bui-space-7)}.lg\:bui-p-8{padding:var(--bui-space-8)}.lg\:bui-p-9{padding:var(--bui-space-9)}.lg\:bui-p-10{padding:var(--bui-space-10)}.lg\:bui-p-11{padding:var(--bui-space-11)}.lg\:bui-p-12{padding:var(--bui-space-12)}.lg\:bui-p-13{padding:var(--bui-space-13)}.lg\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-p{padding:var(--p-xl)}.xl\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xl\:bui-p-1{padding:var(--bui-space-1)}.xl\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xl\:bui-p-2{padding:var(--bui-space-2)}.xl\:bui-p-3{padding:var(--bui-space-3)}.xl\:bui-p-4{padding:var(--bui-space-4)}.xl\:bui-p-5{padding:var(--bui-space-5)}.xl\:bui-p-6{padding:var(--bui-space-6)}.xl\:bui-p-7{padding:var(--bui-space-7)}.xl\:bui-p-8{padding:var(--bui-space-8)}.xl\:bui-p-9{padding:var(--bui-space-9)}.xl\:bui-p-10{padding:var(--bui-space-10)}.xl\:bui-p-11{padding:var(--bui-space-11)}.xl\:bui-p-12{padding:var(--bui-space-12)}.xl\:bui-p-13{padding:var(--bui-space-13)}.xl\:bui-p-14{padding:var(--bui-space-14)}}.bui-pl{padding-left:var(--pl)}.bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.bui-pl-1{padding-left:var(--bui-space-1)}.bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.bui-pl-2{padding-left:var(--bui-space-2)}.bui-pl-3{padding-left:var(--bui-space-3)}.bui-pl-4{padding-left:var(--bui-space-4)}.bui-pl-5{padding-left:var(--bui-space-5)}.bui-pl-6{padding-left:var(--bui-space-6)}.bui-pl-7{padding-left:var(--bui-space-7)}.bui-pl-8{padding-left:var(--bui-space-8)}.bui-pl-9{padding-left:var(--bui-space-9)}.bui-pl-10{padding-left:var(--bui-space-10)}.bui-pl-11{padding-left:var(--bui-space-11)}.bui-pl-12{padding-left:var(--bui-space-12)}.bui-pl-13{padding-left:var(--bui-space-13)}.bui-pl-14{padding-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pl{padding-left:var(--pl-xs)}.xs\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xs\:bui-pl-1{padding-left:var(--bui-space-1)}.xs\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xs\:bui-pl-2{padding-left:var(--bui-space-2)}.xs\:bui-pl-3{padding-left:var(--bui-space-3)}.xs\:bui-pl-4{padding-left:var(--bui-space-4)}.xs\:bui-pl-5{padding-left:var(--bui-space-5)}.xs\:bui-pl-6{padding-left:var(--bui-space-6)}.xs\:bui-pl-7{padding-left:var(--bui-space-7)}.xs\:bui-pl-8{padding-left:var(--bui-space-8)}.xs\:bui-pl-9{padding-left:var(--bui-space-9)}.xs\:bui-pl-10{padding-left:var(--bui-space-10)}.xs\:bui-pl-11{padding-left:var(--bui-space-11)}.xs\:bui-pl-12{padding-left:var(--bui-space-12)}.xs\:bui-pl-13{padding-left:var(--bui-space-13)}.xs\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pl{padding-left:var(--pl-sm)}.sm\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.sm\:bui-pl-1{padding-left:var(--bui-space-1)}.sm\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.sm\:bui-pl-2{padding-left:var(--bui-space-2)}.sm\:bui-pl-3{padding-left:var(--bui-space-3)}.sm\:bui-pl-4{padding-left:var(--bui-space-4)}.sm\:bui-pl-5{padding-left:var(--bui-space-5)}.sm\:bui-pl-6{padding-left:var(--bui-space-6)}.sm\:bui-pl-7{padding-left:var(--bui-space-7)}.sm\:bui-pl-8{padding-left:var(--bui-space-8)}.sm\:bui-pl-9{padding-left:var(--bui-space-9)}.sm\:bui-pl-10{padding-left:var(--bui-space-10)}.sm\:bui-pl-11{padding-left:var(--bui-space-11)}.sm\:bui-pl-12{padding-left:var(--bui-space-12)}.sm\:bui-pl-13{padding-left:var(--bui-space-13)}.sm\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pl{padding-left:var(--pl-md)}.md\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.md\:bui-pl-1{padding-left:var(--bui-space-1)}.md\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.md\:bui-pl-2{padding-left:var(--bui-space-2)}.md\:bui-pl-3{padding-left:var(--bui-space-3)}.md\:bui-pl-4{padding-left:var(--bui-space-4)}.md\:bui-pl-5{padding-left:var(--bui-space-5)}.md\:bui-pl-6{padding-left:var(--bui-space-6)}.md\:bui-pl-7{padding-left:var(--bui-space-7)}.md\:bui-pl-8{padding-left:var(--bui-space-8)}.md\:bui-pl-9{padding-left:var(--bui-space-9)}.md\:bui-pl-10{padding-left:var(--bui-space-10)}.md\:bui-pl-11{padding-left:var(--bui-space-11)}.md\:bui-pl-12{padding-left:var(--bui-space-12)}.md\:bui-pl-13{padding-left:var(--bui-space-13)}.md\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pl{padding-left:var(--pl-lg)}.lg\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.lg\:bui-pl-1{padding-left:var(--bui-space-1)}.lg\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.lg\:bui-pl-2{padding-left:var(--bui-space-2)}.lg\:bui-pl-3{padding-left:var(--bui-space-3)}.lg\:bui-pl-4{padding-left:var(--bui-space-4)}.lg\:bui-pl-5{padding-left:var(--bui-space-5)}.lg\:bui-pl-6{padding-left:var(--bui-space-6)}.lg\:bui-pl-7{padding-left:var(--bui-space-7)}.lg\:bui-pl-8{padding-left:var(--bui-space-8)}.lg\:bui-pl-9{padding-left:var(--bui-space-9)}.lg\:bui-pl-10{padding-left:var(--bui-space-10)}.lg\:bui-pl-11{padding-left:var(--bui-space-11)}.lg\:bui-pl-12{padding-left:var(--bui-space-12)}.lg\:bui-pl-13{padding-left:var(--bui-space-13)}.lg\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pl{padding-left:var(--pl-xl)}.xl\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xl\:bui-pl-1{padding-left:var(--bui-space-1)}.xl\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xl\:bui-pl-2{padding-left:var(--bui-space-2)}.xl\:bui-pl-3{padding-left:var(--bui-space-3)}.xl\:bui-pl-4{padding-left:var(--bui-space-4)}.xl\:bui-pl-5{padding-left:var(--bui-space-5)}.xl\:bui-pl-6{padding-left:var(--bui-space-6)}.xl\:bui-pl-7{padding-left:var(--bui-space-7)}.xl\:bui-pl-8{padding-left:var(--bui-space-8)}.xl\:bui-pl-9{padding-left:var(--bui-space-9)}.xl\:bui-pl-10{padding-left:var(--bui-space-10)}.xl\:bui-pl-11{padding-left:var(--bui-space-11)}.xl\:bui-pl-12{padding-left:var(--bui-space-12)}.xl\:bui-pl-13{padding-left:var(--bui-space-13)}.xl\:bui-pl-14{padding-left:var(--bui-space-14)}}.bui-pr{padding-right:var(--pr)}.bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.bui-pr-1{padding-right:var(--bui-space-1)}.bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.bui-pr-2{padding-right:var(--bui-space-2)}.bui-pr-3{padding-right:var(--bui-space-3)}.bui-pr-4{padding-right:var(--bui-space-4)}.bui-pr-5{padding-right:var(--bui-space-5)}.bui-pr-6{padding-right:var(--bui-space-6)}.bui-pr-7{padding-right:var(--bui-space-7)}.bui-pr-8{padding-right:var(--bui-space-8)}.bui-pr-9{padding-right:var(--bui-space-9)}.bui-pr-10{padding-right:var(--bui-space-10)}.bui-pr-11{padding-right:var(--bui-space-11)}.bui-pr-12{padding-right:var(--bui-space-12)}.bui-pr-13{padding-right:var(--bui-space-13)}.bui-pr-14{padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pr{padding-right:var(--pr-xs)}.xs\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xs\:bui-pr-1{padding-right:var(--bui-space-1)}.xs\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xs\:bui-pr-2{padding-right:var(--bui-space-2)}.xs\:bui-pr-3{padding-right:var(--bui-space-3)}.xs\:bui-pr-4{padding-right:var(--bui-space-4)}.xs\:bui-pr-5{padding-right:var(--bui-space-5)}.xs\:bui-pr-6{padding-right:var(--bui-space-6)}.xs\:bui-pr-7{padding-right:var(--bui-space-7)}.xs\:bui-pr-8{padding-right:var(--bui-space-8)}.xs\:bui-pr-9{padding-right:var(--bui-space-9)}.xs\:bui-pr-10{padding-right:var(--bui-space-10)}.xs\:bui-pr-11{padding-right:var(--bui-space-11)}.xs\:bui-pr-12{padding-right:var(--bui-space-12)}.xs\:bui-pr-13{padding-right:var(--bui-space-13)}.xs\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pr{padding-right:var(--pr-sm)}.sm\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.sm\:bui-pr-1{padding-right:var(--bui-space-1)}.sm\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.sm\:bui-pr-2{padding-right:var(--bui-space-2)}.sm\:bui-pr-3{padding-right:var(--bui-space-3)}.sm\:bui-pr-4{padding-right:var(--bui-space-4)}.sm\:bui-pr-5{padding-right:var(--bui-space-5)}.sm\:bui-pr-6{padding-right:var(--bui-space-6)}.sm\:bui-pr-7{padding-right:var(--bui-space-7)}.sm\:bui-pr-8{padding-right:var(--bui-space-8)}.sm\:bui-pr-9{padding-right:var(--bui-space-9)}.sm\:bui-pr-10{padding-right:var(--bui-space-10)}.sm\:bui-pr-11{padding-right:var(--bui-space-11)}.sm\:bui-pr-12{padding-right:var(--bui-space-12)}.sm\:bui-pr-13{padding-right:var(--bui-space-13)}.sm\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pr{padding-right:var(--pr-md)}.md\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.md\:bui-pr-1{padding-right:var(--bui-space-1)}.md\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.md\:bui-pr-2{padding-right:var(--bui-space-2)}.md\:bui-pr-3{padding-right:var(--bui-space-3)}.md\:bui-pr-4{padding-right:var(--bui-space-4)}.md\:bui-pr-5{padding-right:var(--bui-space-5)}.md\:bui-pr-6{padding-right:var(--bui-space-6)}.md\:bui-pr-7{padding-right:var(--bui-space-7)}.md\:bui-pr-8{padding-right:var(--bui-space-8)}.md\:bui-pr-9{padding-right:var(--bui-space-9)}.md\:bui-pr-10{padding-right:var(--bui-space-10)}.md\:bui-pr-11{padding-right:var(--bui-space-11)}.md\:bui-pr-12{padding-right:var(--bui-space-12)}.md\:bui-pr-13{padding-right:var(--bui-space-13)}.md\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pr{padding-right:var(--pr-lg)}.lg\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.lg\:bui-pr-1{padding-right:var(--bui-space-1)}.lg\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.lg\:bui-pr-2{padding-right:var(--bui-space-2)}.lg\:bui-pr-3{padding-right:var(--bui-space-3)}.lg\:bui-pr-4{padding-right:var(--bui-space-4)}.lg\:bui-pr-5{padding-right:var(--bui-space-5)}.lg\:bui-pr-6{padding-right:var(--bui-space-6)}.lg\:bui-pr-7{padding-right:var(--bui-space-7)}.lg\:bui-pr-8{padding-right:var(--bui-space-8)}.lg\:bui-pr-9{padding-right:var(--bui-space-9)}.lg\:bui-pr-10{padding-right:var(--bui-space-10)}.lg\:bui-pr-11{padding-right:var(--bui-space-11)}.lg\:bui-pr-12{padding-right:var(--bui-space-12)}.lg\:bui-pr-13{padding-right:var(--bui-space-13)}.lg\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pr{padding-right:var(--pr-xl)}.xl\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xl\:bui-pr-1{padding-right:var(--bui-space-1)}.xl\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xl\:bui-pr-2{padding-right:var(--bui-space-2)}.xl\:bui-pr-3{padding-right:var(--bui-space-3)}.xl\:bui-pr-4{padding-right:var(--bui-space-4)}.xl\:bui-pr-5{padding-right:var(--bui-space-5)}.xl\:bui-pr-6{padding-right:var(--bui-space-6)}.xl\:bui-pr-7{padding-right:var(--bui-space-7)}.xl\:bui-pr-8{padding-right:var(--bui-space-8)}.xl\:bui-pr-9{padding-right:var(--bui-space-9)}.xl\:bui-pr-10{padding-right:var(--bui-space-10)}.xl\:bui-pr-11{padding-right:var(--bui-space-11)}.xl\:bui-pr-12{padding-right:var(--bui-space-12)}.xl\:bui-pr-13{padding-right:var(--bui-space-13)}.xl\:bui-pr-14{padding-right:var(--bui-space-14)}}.bui-pt{padding-top:var(--pt)}.bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.bui-pt-1{padding-top:var(--bui-space-1)}.bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.bui-pt-2{padding-top:var(--bui-space-2)}.bui-pt-3{padding-top:var(--bui-space-3)}.bui-pt-4{padding-top:var(--bui-space-4)}.bui-pt-5{padding-top:var(--bui-space-5)}.bui-pt-6{padding-top:var(--bui-space-6)}.bui-pt-7{padding-top:var(--bui-space-7)}.bui-pt-8{padding-top:var(--bui-space-8)}.bui-pt-9{padding-top:var(--bui-space-9)}.bui-pt-10{padding-top:var(--bui-space-10)}.bui-pt-11{padding-top:var(--bui-space-11)}.bui-pt-12{padding-top:var(--bui-space-12)}.bui-pt-13{padding-top:var(--bui-space-13)}.bui-pt-14{padding-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pt{padding-top:var(--pt-xs)}.xs\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xs\:bui-pt-1{padding-top:var(--bui-space-1)}.xs\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xs\:bui-pt-2{padding-top:var(--bui-space-2)}.xs\:bui-pt-3{padding-top:var(--bui-space-3)}.xs\:bui-pt-4{padding-top:var(--bui-space-4)}.xs\:bui-pt-5{padding-top:var(--bui-space-5)}.xs\:bui-pt-6{padding-top:var(--bui-space-6)}.xs\:bui-pt-7{padding-top:var(--bui-space-7)}.xs\:bui-pt-8{padding-top:var(--bui-space-8)}.xs\:bui-pt-9{padding-top:var(--bui-space-9)}.xs\:bui-pt-10{padding-top:var(--bui-space-10)}.xs\:bui-pt-11{padding-top:var(--bui-space-11)}.xs\:bui-pt-12{padding-top:var(--bui-space-12)}.xs\:bui-pt-13{padding-top:var(--bui-space-13)}.xs\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pt{padding-top:var(--pt-sm)}.sm\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.sm\:bui-pt-1{padding-top:var(--bui-space-1)}.sm\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.sm\:bui-pt-2{padding-top:var(--bui-space-2)}.sm\:bui-pt-3{padding-top:var(--bui-space-3)}.sm\:bui-pt-4{padding-top:var(--bui-space-4)}.sm\:bui-pt-5{padding-top:var(--bui-space-5)}.sm\:bui-pt-6{padding-top:var(--bui-space-6)}.sm\:bui-pt-7{padding-top:var(--bui-space-7)}.sm\:bui-pt-8{padding-top:var(--bui-space-8)}.sm\:bui-pt-9{padding-top:var(--bui-space-9)}.sm\:bui-pt-10{padding-top:var(--bui-space-10)}.sm\:bui-pt-11{padding-top:var(--bui-space-11)}.sm\:bui-pt-12{padding-top:var(--bui-space-12)}.sm\:bui-pt-13{padding-top:var(--bui-space-13)}.sm\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pt{padding-top:var(--pt-md)}.md\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.md\:bui-pt-1{padding-top:var(--bui-space-1)}.md\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.md\:bui-pt-2{padding-top:var(--bui-space-2)}.md\:bui-pt-3{padding-top:var(--bui-space-3)}.md\:bui-pt-4{padding-top:var(--bui-space-4)}.md\:bui-pt-5{padding-top:var(--bui-space-5)}.md\:bui-pt-6{padding-top:var(--bui-space-6)}.md\:bui-pt-7{padding-top:var(--bui-space-7)}.md\:bui-pt-8{padding-top:var(--bui-space-8)}.md\:bui-pt-9{padding-top:var(--bui-space-9)}.md\:bui-pt-10{padding-top:var(--bui-space-10)}.md\:bui-pt-11{padding-top:var(--bui-space-11)}.md\:bui-pt-12{padding-top:var(--bui-space-12)}.md\:bui-pt-13{padding-top:var(--bui-space-13)}.md\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pt{padding-top:var(--pt-lg)}.lg\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.lg\:bui-pt-1{padding-top:var(--bui-space-1)}.lg\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.lg\:bui-pt-2{padding-top:var(--bui-space-2)}.lg\:bui-pt-3{padding-top:var(--bui-space-3)}.lg\:bui-pt-4{padding-top:var(--bui-space-4)}.lg\:bui-pt-5{padding-top:var(--bui-space-5)}.lg\:bui-pt-6{padding-top:var(--bui-space-6)}.lg\:bui-pt-7{padding-top:var(--bui-space-7)}.lg\:bui-pt-8{padding-top:var(--bui-space-8)}.lg\:bui-pt-9{padding-top:var(--bui-space-9)}.lg\:bui-pt-10{padding-top:var(--bui-space-10)}.lg\:bui-pt-11{padding-top:var(--bui-space-11)}.lg\:bui-pt-12{padding-top:var(--bui-space-12)}.lg\:bui-pt-13{padding-top:var(--bui-space-13)}.lg\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pt{padding-top:var(--pt-xl)}.xl\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xl\:bui-pt-1{padding-top:var(--bui-space-1)}.xl\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xl\:bui-pt-2{padding-top:var(--bui-space-2)}.xl\:bui-pt-3{padding-top:var(--bui-space-3)}.xl\:bui-pt-4{padding-top:var(--bui-space-4)}.xl\:bui-pt-5{padding-top:var(--bui-space-5)}.xl\:bui-pt-6{padding-top:var(--bui-space-6)}.xl\:bui-pt-7{padding-top:var(--bui-space-7)}.xl\:bui-pt-8{padding-top:var(--bui-space-8)}.xl\:bui-pt-9{padding-top:var(--bui-space-9)}.xl\:bui-pt-10{padding-top:var(--bui-space-10)}.xl\:bui-pt-11{padding-top:var(--bui-space-11)}.xl\:bui-pt-12{padding-top:var(--bui-space-12)}.xl\:bui-pt-13{padding-top:var(--bui-space-13)}.xl\:bui-pt-14{padding-top:var(--bui-space-14)}}.bui-pb{padding-bottom:var(--pb)}.bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.bui-pb-1{padding-bottom:var(--bui-space-1)}.bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.bui-pb-2{padding-bottom:var(--bui-space-2)}.bui-pb-3{padding-bottom:var(--bui-space-3)}.bui-pb-4{padding-bottom:var(--bui-space-4)}.bui-pb-5{padding-bottom:var(--bui-space-5)}.bui-pb-6{padding-bottom:var(--bui-space-6)}.bui-pb-7{padding-bottom:var(--bui-space-7)}.bui-pb-8{padding-bottom:var(--bui-space-8)}.bui-pb-9{padding-bottom:var(--bui-space-9)}.bui-pb-10{padding-bottom:var(--bui-space-10)}.bui-pb-11{padding-bottom:var(--bui-space-11)}.bui-pb-12{padding-bottom:var(--bui-space-12)}.bui-pb-13{padding-bottom:var(--bui-space-13)}.bui-pb-14{padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pb{padding-bottom:var(--pb-xs)}.xs\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xs\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xs\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xs\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xs\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xs\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xs\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xs\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xs\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xs\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xs\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xs\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xs\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xs\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xs\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xs\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pb{padding-bottom:var(--pb-sm)}.sm\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.sm\:bui-pb-1{padding-bottom:var(--bui-space-1)}.sm\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.sm\:bui-pb-2{padding-bottom:var(--bui-space-2)}.sm\:bui-pb-3{padding-bottom:var(--bui-space-3)}.sm\:bui-pb-4{padding-bottom:var(--bui-space-4)}.sm\:bui-pb-5{padding-bottom:var(--bui-space-5)}.sm\:bui-pb-6{padding-bottom:var(--bui-space-6)}.sm\:bui-pb-7{padding-bottom:var(--bui-space-7)}.sm\:bui-pb-8{padding-bottom:var(--bui-space-8)}.sm\:bui-pb-9{padding-bottom:var(--bui-space-9)}.sm\:bui-pb-10{padding-bottom:var(--bui-space-10)}.sm\:bui-pb-11{padding-bottom:var(--bui-space-11)}.sm\:bui-pb-12{padding-bottom:var(--bui-space-12)}.sm\:bui-pb-13{padding-bottom:var(--bui-space-13)}.sm\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pb{padding-bottom:var(--pb-md)}.md\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.md\:bui-pb-1{padding-bottom:var(--bui-space-1)}.md\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.md\:bui-pb-2{padding-bottom:var(--bui-space-2)}.md\:bui-pb-3{padding-bottom:var(--bui-space-3)}.md\:bui-pb-4{padding-bottom:var(--bui-space-4)}.md\:bui-pb-5{padding-bottom:var(--bui-space-5)}.md\:bui-pb-6{padding-bottom:var(--bui-space-6)}.md\:bui-pb-7{padding-bottom:var(--bui-space-7)}.md\:bui-pb-8{padding-bottom:var(--bui-space-8)}.md\:bui-pb-9{padding-bottom:var(--bui-space-9)}.md\:bui-pb-10{padding-bottom:var(--bui-space-10)}.md\:bui-pb-11{padding-bottom:var(--bui-space-11)}.md\:bui-pb-12{padding-bottom:var(--bui-space-12)}.md\:bui-pb-13{padding-bottom:var(--bui-space-13)}.md\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pb{padding-bottom:var(--pb-lg)}.lg\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.lg\:bui-pb-1{padding-bottom:var(--bui-space-1)}.lg\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.lg\:bui-pb-2{padding-bottom:var(--bui-space-2)}.lg\:bui-pb-3{padding-bottom:var(--bui-space-3)}.lg\:bui-pb-4{padding-bottom:var(--bui-space-4)}.lg\:bui-pb-5{padding-bottom:var(--bui-space-5)}.lg\:bui-pb-6{padding-bottom:var(--bui-space-6)}.lg\:bui-pb-7{padding-bottom:var(--bui-space-7)}.lg\:bui-pb-8{padding-bottom:var(--bui-space-8)}.lg\:bui-pb-9{padding-bottom:var(--bui-space-9)}.lg\:bui-pb-10{padding-bottom:var(--bui-space-10)}.lg\:bui-pb-11{padding-bottom:var(--bui-space-11)}.lg\:bui-pb-12{padding-bottom:var(--bui-space-12)}.lg\:bui-pb-13{padding-bottom:var(--bui-space-13)}.lg\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pb{padding-bottom:var(--pb-xl)}.xl\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xl\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xl\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xl\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xl\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xl\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xl\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xl\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xl\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xl\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xl\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xl\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xl\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xl\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xl\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xl\:bui-pb-14{padding-bottom:var(--bui-space-14)}}.bui-py{padding-top:var(--py);padding-bottom:var(--py)}.bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-py{padding-top:var(--py-xs);padding-bottom:var(--py-xs)}.xs\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xs\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xs\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xs\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xs\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xs\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xs\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xs\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xs\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xs\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xs\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xs\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xs\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xs\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xs\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xs\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-py{padding-top:var(--py-sm);padding-bottom:var(--py-sm)}.sm\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.sm\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.sm\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.sm\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.sm\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.sm\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.sm\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.sm\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.sm\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.sm\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.sm\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.sm\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.sm\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.sm\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.sm\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.sm\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-py{padding-top:var(--py-md);padding-bottom:var(--py-md)}.md\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.md\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.md\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.md\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.md\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.md\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.md\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.md\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.md\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.md\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.md\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.md\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.md\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.md\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.md\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.md\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-py{padding-top:var(--py-lg);padding-bottom:var(--py-lg)}.lg\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.lg\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.lg\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.lg\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.lg\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.lg\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.lg\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.lg\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.lg\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.lg\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.lg\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.lg\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.lg\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.lg\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.lg\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.lg\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-py{padding-top:var(--py-xl);padding-bottom:var(--py-xl)}.xl\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xl\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xl\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xl\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xl\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xl\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xl\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xl\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xl\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xl\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xl\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xl\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xl\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xl\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xl\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xl\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}.bui-px{padding-left:var(--px);padding-right:var(--px)}.bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-px{padding-left:var(--px-xs);padding-right:var(--px-xs)}.xs\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xs\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xs\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xs\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xs\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xs\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xs\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xs\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xs\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xs\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xs\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xs\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xs\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xs\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xs\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xs\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-px{padding-left:var(--px-sm);padding-right:var(--px-sm)}.sm\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.sm\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.sm\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.sm\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.sm\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.sm\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.sm\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.sm\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.sm\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.sm\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.sm\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.sm\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.sm\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.sm\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.sm\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.sm\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-px{padding-left:var(--px-md);padding-right:var(--px-md)}.md\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.md\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.md\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.md\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.md\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.md\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.md\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.md\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.md\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.md\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.md\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.md\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.md\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.md\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.md\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.md\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-px{padding-left:var(--px-lg);padding-right:var(--px-lg)}.lg\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.lg\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.lg\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.lg\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.lg\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.lg\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.lg\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.lg\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.lg\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.lg\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.lg\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.lg\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.lg\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.lg\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.lg\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.lg\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-px{padding-left:var(--px-xl);padding-right:var(--px-xl)}.xl\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xl\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xl\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xl\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xl\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xl\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xl\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xl\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xl\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xl\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xl\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xl\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xl\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xl\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xl\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xl\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}.bui-m{margin:var(--m)}.bui-m-0\.5{margin:var(--bui-space-0_5)}.bui-m-1{margin:var(--bui-space-1)}.bui-m-1\.5{margin:var(--bui-space-1_5)}.bui-m-2{margin:var(--bui-space-2)}.bui-m-3{margin:var(--bui-space-3)}.bui-m-4{margin:var(--bui-space-4)}.bui-m-5{margin:var(--bui-space-5)}.bui-m-6{margin:var(--bui-space-6)}.bui-m-7{margin:var(--bui-space-7)}.bui-m-8{margin:var(--bui-space-8)}.bui-m-9{margin:var(--bui-space-9)}.bui-m-10{margin:var(--bui-space-10)}.bui-m-11{margin:var(--bui-space-11)}.bui-m-12{margin:var(--bui-space-12)}.bui-m-13{margin:var(--bui-space-13)}.bui-m-14{margin:var(--bui-space-14)}@media (width>=640px){.xs\:bui-m{margin:var(--p-xs)}.xs\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xs\:bui-m-1{margin:var(--bui-space-1)}.xs\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xs\:bui-m-2{margin:var(--bui-space-2)}.xs\:bui-m-3{margin:var(--bui-space-3)}.xs\:bui-m-4{margin:var(--bui-space-4)}.xs\:bui-m-5{margin:var(--bui-space-5)}.xs\:bui-m-6{margin:var(--bui-space-6)}.xs\:bui-m-7{margin:var(--bui-space-7)}.xs\:bui-m-8{margin:var(--bui-space-8)}.xs\:bui-m-9{margin:var(--bui-space-9)}.xs\:bui-m-10{margin:var(--bui-space-10)}.xs\:bui-m-11{margin:var(--bui-space-11)}.xs\:bui-m-12{margin:var(--bui-space-12)}.xs\:bui-m-13{margin:var(--bui-space-13)}.xs\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-m{margin:var(--p-sm)}.sm\:bui-m-0\.5{margin:var(--bui-space-0_5)}.sm\:bui-m-1{margin:var(--bui-space-1)}.sm\:bui-m-1\.5{margin:var(--bui-space-1_5)}.sm\:bui-m-2{margin:var(--bui-space-2)}.sm\:bui-m-3{margin:var(--bui-space-3)}.sm\:bui-m-4{margin:var(--bui-space-4)}.sm\:bui-m-5{margin:var(--bui-space-5)}.sm\:bui-m-6{margin:var(--bui-space-6)}.sm\:bui-m-7{margin:var(--bui-space-7)}.sm\:bui-m-8{margin:var(--bui-space-8)}.sm\:bui-m-9{margin:var(--bui-space-9)}.sm\:bui-m-10{margin:var(--bui-space-10)}.sm\:bui-m-11{margin:var(--bui-space-11)}.sm\:bui-m-12{margin:var(--bui-space-12)}.sm\:bui-m-13{margin:var(--bui-space-13)}.sm\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-m{margin:var(--p-md)}.md\:bui-m-0\.5{margin:var(--bui-space-0_5)}.md\:bui-m-1{margin:var(--bui-space-1)}.md\:bui-m-1\.5{margin:var(--bui-space-1_5)}.md\:bui-m-2{margin:var(--bui-space-2)}.md\:bui-m-3{margin:var(--bui-space-3)}.md\:bui-m-4{margin:var(--bui-space-4)}.md\:bui-m-5{margin:var(--bui-space-5)}.md\:bui-m-6{margin:var(--bui-space-6)}.md\:bui-m-7{margin:var(--bui-space-7)}.md\:bui-m-8{margin:var(--bui-space-8)}.md\:bui-m-9{margin:var(--bui-space-9)}.md\:bui-m-10{margin:var(--bui-space-10)}.md\:bui-m-11{margin:var(--bui-space-11)}.md\:bui-m-12{margin:var(--bui-space-12)}.md\:bui-m-13{margin:var(--bui-space-13)}.md\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-m{margin:var(--p-lg)}.lg\:bui-m-0\.5{margin:var(--bui-space-0_5)}.lg\:bui-m-1{margin:var(--bui-space-1)}.lg\:bui-m-1\.5{margin:var(--bui-space-1_5)}.lg\:bui-m-2{margin:var(--bui-space-2)}.lg\:bui-m-3{margin:var(--bui-space-3)}.lg\:bui-m-4{margin:var(--bui-space-4)}.lg\:bui-m-5{margin:var(--bui-space-5)}.lg\:bui-m-6{margin:var(--bui-space-6)}.lg\:bui-m-7{margin:var(--bui-space-7)}.lg\:bui-m-8{margin:var(--bui-space-8)}.lg\:bui-m-9{margin:var(--bui-space-9)}.lg\:bui-m-10{margin:var(--bui-space-10)}.lg\:bui-m-11{margin:var(--bui-space-11)}.lg\:bui-m-12{margin:var(--bui-space-12)}.lg\:bui-m-13{margin:var(--bui-space-13)}.lg\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-m{margin:var(--p-xl)}.xl\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xl\:bui-m-1{margin:var(--bui-space-1)}.xl\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xl\:bui-m-2{margin:var(--bui-space-2)}.xl\:bui-m-3{margin:var(--bui-space-3)}.xl\:bui-m-4{margin:var(--bui-space-4)}.xl\:bui-m-5{margin:var(--bui-space-5)}.xl\:bui-m-6{margin:var(--bui-space-6)}.xl\:bui-m-7{margin:var(--bui-space-7)}.xl\:bui-m-8{margin:var(--bui-space-8)}.xl\:bui-m-9{margin:var(--bui-space-9)}.xl\:bui-m-10{margin:var(--bui-space-10)}.xl\:bui-m-11{margin:var(--bui-space-11)}.xl\:bui-m-12{margin:var(--bui-space-12)}.xl\:bui-m-13{margin:var(--bui-space-13)}.xl\:bui-m-14{margin:var(--bui-space-14)}}.bui-ml{margin-left:var(--ml)}.bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.bui-ml-1{margin-left:var(--bui-space-1)}.bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.bui-ml-2{margin-left:var(--bui-space-2)}.bui-ml-3{margin-left:var(--bui-space-3)}.bui-ml-4{margin-left:var(--bui-space-4)}.bui-ml-5{margin-left:var(--bui-space-5)}.bui-ml-6{margin-left:var(--bui-space-6)}.bui-ml-7{margin-left:var(--bui-space-7)}.bui-ml-8{margin-left:var(--bui-space-8)}.bui-ml-9{margin-left:var(--bui-space-9)}.bui-ml-10{margin-left:var(--bui-space-10)}.bui-ml-11{margin-left:var(--bui-space-11)}.bui-ml-12{margin-left:var(--bui-space-12)}.bui-ml-13{margin-left:var(--bui-space-13)}.bui-ml-14{margin-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-ml{margin-left:var(--pl-xs)}.xs\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xs\:bui-ml-1{margin-left:var(--bui-space-1)}.xs\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xs\:bui-ml-2{margin-left:var(--bui-space-2)}.xs\:bui-ml-3{margin-left:var(--bui-space-3)}.xs\:bui-ml-4{margin-left:var(--bui-space-4)}.xs\:bui-ml-5{margin-left:var(--bui-space-5)}.xs\:bui-ml-6{margin-left:var(--bui-space-6)}.xs\:bui-ml-7{margin-left:var(--bui-space-7)}.xs\:bui-ml-8{margin-left:var(--bui-space-8)}.xs\:bui-ml-9{margin-left:var(--bui-space-9)}.xs\:bui-ml-10{margin-left:var(--bui-space-10)}.xs\:bui-ml-11{margin-left:var(--bui-space-11)}.xs\:bui-ml-12{margin-left:var(--bui-space-12)}.xs\:bui-ml-13{margin-left:var(--bui-space-13)}.xs\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-ml{margin-left:var(--pl-sm)}.sm\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.sm\:bui-ml-1{margin-left:var(--bui-space-1)}.sm\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.sm\:bui-ml-2{margin-left:var(--bui-space-2)}.sm\:bui-ml-3{margin-left:var(--bui-space-3)}.sm\:bui-ml-4{margin-left:var(--bui-space-4)}.sm\:bui-ml-5{margin-left:var(--bui-space-5)}.sm\:bui-ml-6{margin-left:var(--bui-space-6)}.sm\:bui-ml-7{margin-left:var(--bui-space-7)}.sm\:bui-ml-8{margin-left:var(--bui-space-8)}.sm\:bui-ml-9{margin-left:var(--bui-space-9)}.sm\:bui-ml-10{margin-left:var(--bui-space-10)}.sm\:bui-ml-11{margin-left:var(--bui-space-11)}.sm\:bui-ml-12{margin-left:var(--bui-space-12)}.sm\:bui-ml-13{margin-left:var(--bui-space-13)}.sm\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-ml{margin-left:var(--pl-md)}.md\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.md\:bui-ml-1{margin-left:var(--bui-space-1)}.md\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.md\:bui-ml-2{margin-left:var(--bui-space-2)}.md\:bui-ml-3{margin-left:var(--bui-space-3)}.md\:bui-ml-4{margin-left:var(--bui-space-4)}.md\:bui-ml-5{margin-left:var(--bui-space-5)}.md\:bui-ml-6{margin-left:var(--bui-space-6)}.md\:bui-ml-7{margin-left:var(--bui-space-7)}.md\:bui-ml-8{margin-left:var(--bui-space-8)}.md\:bui-ml-9{margin-left:var(--bui-space-9)}.md\:bui-ml-10{margin-left:var(--bui-space-10)}.md\:bui-ml-11{margin-left:var(--bui-space-11)}.md\:bui-ml-12{margin-left:var(--bui-space-12)}.md\:bui-ml-13{margin-left:var(--bui-space-13)}.md\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-ml{margin-left:var(--pl-lg)}.lg\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.lg\:bui-ml-1{margin-left:var(--bui-space-1)}.lg\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.lg\:bui-ml-2{margin-left:var(--bui-space-2)}.lg\:bui-ml-3{margin-left:var(--bui-space-3)}.lg\:bui-ml-4{margin-left:var(--bui-space-4)}.lg\:bui-ml-5{margin-left:var(--bui-space-5)}.lg\:bui-ml-6{margin-left:var(--bui-space-6)}.lg\:bui-ml-7{margin-left:var(--bui-space-7)}.lg\:bui-ml-8{margin-left:var(--bui-space-8)}.lg\:bui-ml-9{margin-left:var(--bui-space-9)}.lg\:bui-ml-10{margin-left:var(--bui-space-10)}.lg\:bui-ml-11{margin-left:var(--bui-space-11)}.lg\:bui-ml-12{margin-left:var(--bui-space-12)}.lg\:bui-ml-13{margin-left:var(--bui-space-13)}.lg\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-ml{margin-left:var(--pl-xl)}.xl\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xl\:bui-ml-1{margin-left:var(--bui-space-1)}.xl\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xl\:bui-ml-2{margin-left:var(--bui-space-2)}.xl\:bui-ml-3{margin-left:var(--bui-space-3)}.xl\:bui-ml-4{margin-left:var(--bui-space-4)}.xl\:bui-ml-5{margin-left:var(--bui-space-5)}.xl\:bui-ml-6{margin-left:var(--bui-space-6)}.xl\:bui-ml-7{margin-left:var(--bui-space-7)}.xl\:bui-ml-8{margin-left:var(--bui-space-8)}.xl\:bui-ml-9{margin-left:var(--bui-space-9)}.xl\:bui-ml-10{margin-left:var(--bui-space-10)}.xl\:bui-ml-11{margin-left:var(--bui-space-11)}.xl\:bui-ml-12{margin-left:var(--bui-space-12)}.xl\:bui-ml-13{margin-left:var(--bui-space-13)}.xl\:bui-ml-14{margin-left:var(--bui-space-14)}}.bui-mr{margin-right:var(--mr)}.bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.bui-mr-1{margin-right:var(--bui-space-1)}.bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.bui-mr-2{margin-right:var(--bui-space-2)}.bui-mr-3{margin-right:var(--bui-space-3)}.bui-mr-4{margin-right:var(--bui-space-4)}.bui-mr-5{margin-right:var(--bui-space-5)}.bui-mr-6{margin-right:var(--bui-space-6)}.bui-mr-7{margin-right:var(--bui-space-7)}.bui-mr-8{margin-right:var(--bui-space-8)}.bui-mr-9{margin-right:var(--bui-space-9)}.bui-mr-10{margin-right:var(--bui-space-10)}.bui-mr-11{margin-right:var(--bui-space-11)}.bui-mr-12{margin-right:var(--bui-space-12)}.bui-mr-13{margin-right:var(--bui-space-13)}.bui-mr-14{margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mr{margin-right:var(--pr-xs)}.xs\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xs\:bui-mr-1{margin-right:var(--bui-space-1)}.xs\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xs\:bui-mr-2{margin-right:var(--bui-space-2)}.xs\:bui-mr-3{margin-right:var(--bui-space-3)}.xs\:bui-mr-4{margin-right:var(--bui-space-4)}.xs\:bui-mr-5{margin-right:var(--bui-space-5)}.xs\:bui-mr-6{margin-right:var(--bui-space-6)}.xs\:bui-mr-7{margin-right:var(--bui-space-7)}.xs\:bui-mr-8{margin-right:var(--bui-space-8)}.xs\:bui-mr-9{margin-right:var(--bui-space-9)}.xs\:bui-mr-10{margin-right:var(--bui-space-10)}.xs\:bui-mr-11{margin-right:var(--bui-space-11)}.xs\:bui-mr-12{margin-right:var(--bui-space-12)}.xs\:bui-mr-13{margin-right:var(--bui-space-13)}.xs\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mr{margin-right:var(--pr-sm)}.sm\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.sm\:bui-mr-1{margin-right:var(--bui-space-1)}.sm\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.sm\:bui-mr-2{margin-right:var(--bui-space-2)}.sm\:bui-mr-3{margin-right:var(--bui-space-3)}.sm\:bui-mr-4{margin-right:var(--bui-space-4)}.sm\:bui-mr-5{margin-right:var(--bui-space-5)}.sm\:bui-mr-6{margin-right:var(--bui-space-6)}.sm\:bui-mr-7{margin-right:var(--bui-space-7)}.sm\:bui-mr-8{margin-right:var(--bui-space-8)}.sm\:bui-mr-9{margin-right:var(--bui-space-9)}.sm\:bui-mr-10{margin-right:var(--bui-space-10)}.sm\:bui-mr-11{margin-right:var(--bui-space-11)}.sm\:bui-mr-12{margin-right:var(--bui-space-12)}.sm\:bui-mr-13{margin-right:var(--bui-space-13)}.sm\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mr{margin-right:var(--pr-md)}.md\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.md\:bui-mr-1{margin-right:var(--bui-space-1)}.md\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.md\:bui-mr-2{margin-right:var(--bui-space-2)}.md\:bui-mr-3{margin-right:var(--bui-space-3)}.md\:bui-mr-4{margin-right:var(--bui-space-4)}.md\:bui-mr-5{margin-right:var(--bui-space-5)}.md\:bui-mr-6{margin-right:var(--bui-space-6)}.md\:bui-mr-7{margin-right:var(--bui-space-7)}.md\:bui-mr-8{margin-right:var(--bui-space-8)}.md\:bui-mr-9{margin-right:var(--bui-space-9)}.md\:bui-mr-10{margin-right:var(--bui-space-10)}.md\:bui-mr-11{margin-right:var(--bui-space-11)}.md\:bui-mr-12{margin-right:var(--bui-space-12)}.md\:bui-mr-13{margin-right:var(--bui-space-13)}.md\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mr{margin-right:var(--pr-lg)}.lg\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.lg\:bui-mr-1{margin-right:var(--bui-space-1)}.lg\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.lg\:bui-mr-2{margin-right:var(--bui-space-2)}.lg\:bui-mr-3{margin-right:var(--bui-space-3)}.lg\:bui-mr-4{margin-right:var(--bui-space-4)}.lg\:bui-mr-5{margin-right:var(--bui-space-5)}.lg\:bui-mr-6{margin-right:var(--bui-space-6)}.lg\:bui-mr-7{margin-right:var(--bui-space-7)}.lg\:bui-mr-8{margin-right:var(--bui-space-8)}.lg\:bui-mr-9{margin-right:var(--bui-space-9)}.lg\:bui-mr-10{margin-right:var(--bui-space-10)}.lg\:bui-mr-11{margin-right:var(--bui-space-11)}.lg\:bui-mr-12{margin-right:var(--bui-space-12)}.lg\:bui-mr-13{margin-right:var(--bui-space-13)}.lg\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mr{margin-right:var(--pr-xl)}.xl\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xl\:bui-mr-1{margin-right:var(--bui-space-1)}.xl\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xl\:bui-mr-2{margin-right:var(--bui-space-2)}.xl\:bui-mr-3{margin-right:var(--bui-space-3)}.xl\:bui-mr-4{margin-right:var(--bui-space-4)}.xl\:bui-mr-5{margin-right:var(--bui-space-5)}.xl\:bui-mr-6{margin-right:var(--bui-space-6)}.xl\:bui-mr-7{margin-right:var(--bui-space-7)}.xl\:bui-mr-8{margin-right:var(--bui-space-8)}.xl\:bui-mr-9{margin-right:var(--bui-space-9)}.xl\:bui-mr-10{margin-right:var(--bui-space-10)}.xl\:bui-mr-11{margin-right:var(--bui-space-11)}.xl\:bui-mr-12{margin-right:var(--bui-space-12)}.xl\:bui-mr-13{margin-right:var(--bui-space-13)}.xl\:bui-mr-14{margin-right:var(--bui-space-14)}}.bui-mt{margin-top:var(--mt)}.bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.bui-mt-1{margin-top:var(--bui-space-1)}.bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.bui-mt-2{margin-top:var(--bui-space-2)}.bui-mt-3{margin-top:var(--bui-space-3)}.bui-mt-4{margin-top:var(--bui-space-4)}.bui-mt-5{margin-top:var(--bui-space-5)}.bui-mt-6{margin-top:var(--bui-space-6)}.bui-mt-7{margin-top:var(--bui-space-7)}.bui-mt-8{margin-top:var(--bui-space-8)}.bui-mt-9{margin-top:var(--bui-space-9)}.bui-mt-10{margin-top:var(--bui-space-10)}.bui-mt-11{margin-top:var(--bui-space-11)}.bui-mt-12{margin-top:var(--bui-space-12)}.bui-mt-13{margin-top:var(--bui-space-13)}.bui-mt-14{margin-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mt{margin-top:var(--pt-xs)}.xs\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xs\:bui-mt-1{margin-top:var(--bui-space-1)}.xs\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xs\:bui-mt-2{margin-top:var(--bui-space-2)}.xs\:bui-mt-3{margin-top:var(--bui-space-3)}.xs\:bui-mt-4{margin-top:var(--bui-space-4)}.xs\:bui-mt-5{margin-top:var(--bui-space-5)}.xs\:bui-mt-6{margin-top:var(--bui-space-6)}.xs\:bui-mt-7{margin-top:var(--bui-space-7)}.xs\:bui-mt-8{margin-top:var(--bui-space-8)}.xs\:bui-mt-9{margin-top:var(--bui-space-9)}.xs\:bui-mt-10{margin-top:var(--bui-space-10)}.xs\:bui-mt-11{margin-top:var(--bui-space-11)}.xs\:bui-mt-12{margin-top:var(--bui-space-12)}.xs\:bui-mt-13{margin-top:var(--bui-space-13)}.xs\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mt{margin-top:var(--pt-sm)}.sm\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.sm\:bui-mt-1{margin-top:var(--bui-space-1)}.sm\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.sm\:bui-mt-2{margin-top:var(--bui-space-2)}.sm\:bui-mt-3{margin-top:var(--bui-space-3)}.sm\:bui-mt-4{margin-top:var(--bui-space-4)}.sm\:bui-mt-5{margin-top:var(--bui-space-5)}.sm\:bui-mt-6{margin-top:var(--bui-space-6)}.sm\:bui-mt-7{margin-top:var(--bui-space-7)}.sm\:bui-mt-8{margin-top:var(--bui-space-8)}.sm\:bui-mt-9{margin-top:var(--bui-space-9)}.sm\:bui-mt-10{margin-top:var(--bui-space-10)}.sm\:bui-mt-11{margin-top:var(--bui-space-11)}.sm\:bui-mt-12{margin-top:var(--bui-space-12)}.sm\:bui-mt-13{margin-top:var(--bui-space-13)}.sm\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mt{margin-top:var(--pt-md)}.md\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.md\:bui-mt-1{margin-top:var(--bui-space-1)}.md\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.md\:bui-mt-2{margin-top:var(--bui-space-2)}.md\:bui-mt-3{margin-top:var(--bui-space-3)}.md\:bui-mt-4{margin-top:var(--bui-space-4)}.md\:bui-mt-5{margin-top:var(--bui-space-5)}.md\:bui-mt-6{margin-top:var(--bui-space-6)}.md\:bui-mt-7{margin-top:var(--bui-space-7)}.md\:bui-mt-8{margin-top:var(--bui-space-8)}.md\:bui-mt-9{margin-top:var(--bui-space-9)}.md\:bui-mt-10{margin-top:var(--bui-space-10)}.md\:bui-mt-11{margin-top:var(--bui-space-11)}.md\:bui-mt-12{margin-top:var(--bui-space-12)}.md\:bui-mt-13{margin-top:var(--bui-space-13)}.md\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mt{margin-top:var(--pt-lg)}.lg\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.lg\:bui-mt-1{margin-top:var(--bui-space-1)}.lg\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.lg\:bui-mt-2{margin-top:var(--bui-space-2)}.lg\:bui-mt-3{margin-top:var(--bui-space-3)}.lg\:bui-mt-4{margin-top:var(--bui-space-4)}.lg\:bui-mt-5{margin-top:var(--bui-space-5)}.lg\:bui-mt-6{margin-top:var(--bui-space-6)}.lg\:bui-mt-7{margin-top:var(--bui-space-7)}.lg\:bui-mt-8{margin-top:var(--bui-space-8)}.lg\:bui-mt-9{margin-top:var(--bui-space-9)}.lg\:bui-mt-10{margin-top:var(--bui-space-10)}.lg\:bui-mt-11{margin-top:var(--bui-space-11)}.lg\:bui-mt-12{margin-top:var(--bui-space-12)}.lg\:bui-mt-13{margin-top:var(--bui-space-13)}.lg\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mt{margin-top:var(--pt-xl)}.xl\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xl\:bui-mt-1{margin-top:var(--bui-space-1)}.xl\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xl\:bui-mt-2{margin-top:var(--bui-space-2)}.xl\:bui-mt-3{margin-top:var(--bui-space-3)}.xl\:bui-mt-4{margin-top:var(--bui-space-4)}.xl\:bui-mt-5{margin-top:var(--bui-space-5)}.xl\:bui-mt-6{margin-top:var(--bui-space-6)}.xl\:bui-mt-7{margin-top:var(--bui-space-7)}.xl\:bui-mt-8{margin-top:var(--bui-space-8)}.xl\:bui-mt-9{margin-top:var(--bui-space-9)}.xl\:bui-mt-10{margin-top:var(--bui-space-10)}.xl\:bui-mt-11{margin-top:var(--bui-space-11)}.xl\:bui-mt-12{margin-top:var(--bui-space-12)}.xl\:bui-mt-13{margin-top:var(--bui-space-13)}.xl\:bui-mt-14{margin-top:var(--bui-space-14)}}.bui-mb{margin-bottom:var(--mb)}.bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.bui-mb-1{margin-bottom:var(--bui-space-1)}.bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.bui-mb-2{margin-bottom:var(--bui-space-2)}.bui-mb-3{margin-bottom:var(--bui-space-3)}.bui-mb-4{margin-bottom:var(--bui-space-4)}.bui-mb-5{margin-bottom:var(--bui-space-5)}.bui-mb-6{margin-bottom:var(--bui-space-6)}.bui-mb-7{margin-bottom:var(--bui-space-7)}.bui-mb-8{margin-bottom:var(--bui-space-8)}.bui-mb-9{margin-bottom:var(--bui-space-9)}.bui-mb-10{margin-bottom:var(--bui-space-10)}.bui-mb-11{margin-bottom:var(--bui-space-11)}.bui-mb-12{margin-bottom:var(--bui-space-12)}.bui-mb-13{margin-bottom:var(--bui-space-13)}.bui-mb-14{margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mb{margin-bottom:var(--pb-xs)}.xs\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xs\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xs\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xs\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xs\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xs\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xs\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xs\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xs\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xs\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xs\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xs\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xs\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xs\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xs\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xs\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mb{margin-bottom:var(--pb-sm)}.sm\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.sm\:bui-mb-1{margin-bottom:var(--bui-space-1)}.sm\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.sm\:bui-mb-2{margin-bottom:var(--bui-space-2)}.sm\:bui-mb-3{margin-bottom:var(--bui-space-3)}.sm\:bui-mb-4{margin-bottom:var(--bui-space-4)}.sm\:bui-mb-5{margin-bottom:var(--bui-space-5)}.sm\:bui-mb-6{margin-bottom:var(--bui-space-6)}.sm\:bui-mb-7{margin-bottom:var(--bui-space-7)}.sm\:bui-mb-8{margin-bottom:var(--bui-space-8)}.sm\:bui-mb-9{margin-bottom:var(--bui-space-9)}.sm\:bui-mb-10{margin-bottom:var(--bui-space-10)}.sm\:bui-mb-11{margin-bottom:var(--bui-space-11)}.sm\:bui-mb-12{margin-bottom:var(--bui-space-12)}.sm\:bui-mb-13{margin-bottom:var(--bui-space-13)}.sm\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mb{margin-bottom:var(--pb-md)}.md\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.md\:bui-mb-1{margin-bottom:var(--bui-space-1)}.md\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.md\:bui-mb-2{margin-bottom:var(--bui-space-2)}.md\:bui-mb-3{margin-bottom:var(--bui-space-3)}.md\:bui-mb-4{margin-bottom:var(--bui-space-4)}.md\:bui-mb-5{margin-bottom:var(--bui-space-5)}.md\:bui-mb-6{margin-bottom:var(--bui-space-6)}.md\:bui-mb-7{margin-bottom:var(--bui-space-7)}.md\:bui-mb-8{margin-bottom:var(--bui-space-8)}.md\:bui-mb-9{margin-bottom:var(--bui-space-9)}.md\:bui-mb-10{margin-bottom:var(--bui-space-10)}.md\:bui-mb-11{margin-bottom:var(--bui-space-11)}.md\:bui-mb-12{margin-bottom:var(--bui-space-12)}.md\:bui-mb-13{margin-bottom:var(--bui-space-13)}.md\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mb{margin-bottom:var(--pb-lg)}.lg\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.lg\:bui-mb-1{margin-bottom:var(--bui-space-1)}.lg\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.lg\:bui-mb-2{margin-bottom:var(--bui-space-2)}.lg\:bui-mb-3{margin-bottom:var(--bui-space-3)}.lg\:bui-mb-4{margin-bottom:var(--bui-space-4)}.lg\:bui-mb-5{margin-bottom:var(--bui-space-5)}.lg\:bui-mb-6{margin-bottom:var(--bui-space-6)}.lg\:bui-mb-7{margin-bottom:var(--bui-space-7)}.lg\:bui-mb-8{margin-bottom:var(--bui-space-8)}.lg\:bui-mb-9{margin-bottom:var(--bui-space-9)}.lg\:bui-mb-10{margin-bottom:var(--bui-space-10)}.lg\:bui-mb-11{margin-bottom:var(--bui-space-11)}.lg\:bui-mb-12{margin-bottom:var(--bui-space-12)}.lg\:bui-mb-13{margin-bottom:var(--bui-space-13)}.lg\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mb{margin-bottom:var(--pb-xl)}.xl\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xl\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xl\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xl\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xl\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xl\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xl\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xl\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xl\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xl\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xl\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xl\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xl\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xl\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xl\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xl\:bui-mb-14{margin-bottom:var(--bui-space-14)}}.bui-my{margin-top:var(--my);margin-bottom:var(--my)}.bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-my{margin-top:var(--py-xs);margin-bottom:var(--py-xs)}.xs\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xs\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xs\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xs\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xs\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xs\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xs\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xs\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xs\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xs\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xs\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xs\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xs\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xs\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xs\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xs\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-my{margin-top:var(--py-sm);margin-bottom:var(--py-sm)}.sm\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.sm\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.sm\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.sm\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.sm\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.sm\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.sm\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.sm\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.sm\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.sm\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.sm\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.sm\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.sm\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.sm\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.sm\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.sm\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-my{margin-top:var(--py-md);margin-bottom:var(--py-md)}.md\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.md\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.md\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.md\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.md\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.md\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.md\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.md\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.md\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.md\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.md\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.md\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.md\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.md\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.md\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.md\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-my{margin-top:var(--py-lg);margin-bottom:var(--py-lg)}.lg\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.lg\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.lg\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.lg\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.lg\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.lg\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.lg\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.lg\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.lg\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.lg\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.lg\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.lg\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.lg\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.lg\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.lg\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.lg\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-my{margin-top:var(--py-xl);margin-bottom:var(--py-xl)}.xl\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xl\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xl\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xl\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xl\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xl\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xl\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xl\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xl\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xl\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xl\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xl\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xl\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xl\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xl\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xl\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}.bui-mx{margin-left:var(--mx);margin-right:var(--mx)}.bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mx{margin-left:var(--px-xs);margin-right:var(--px-xs)}.xs\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xs\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xs\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xs\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xs\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xs\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xs\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xs\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xs\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xs\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xs\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xs\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xs\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xs\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xs\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xs\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mx{margin-left:var(--px-sm);margin-right:var(--px-sm)}.sm\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.sm\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.sm\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.sm\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.sm\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.sm\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.sm\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.sm\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.sm\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.sm\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.sm\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.sm\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.sm\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.sm\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.sm\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.sm\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mx{margin-left:var(--px-md);margin-right:var(--px-md)}.md\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.md\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.md\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.md\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.md\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.md\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.md\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.md\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.md\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.md\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.md\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.md\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.md\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.md\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.md\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.md\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mx{margin-left:var(--px-lg);margin-right:var(--px-lg)}.lg\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.lg\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.lg\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.lg\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.lg\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.lg\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.lg\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.lg\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.lg\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.lg\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.lg\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.lg\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.lg\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.lg\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.lg\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.lg\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mx{margin-left:var(--px-xl);margin-right:var(--px-xl)}.xl\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xl\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xl\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xl\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xl\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xl\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xl\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xl\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xl\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xl\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xl\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xl\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xl\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xl\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xl\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xl\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}.bui-display-none{display:none}.bui-display-inline{display:inline}.bui-display-inline-block{display:inline-block}.bui-display-block{display:block}@media (width>=640px){.xs\:bui-display-none{display:none}.xs\:bui-display-inline{display:inline}.xs\:bui-display-inline-block{display:inline-block}.xs\:bui-display-block{display:block}}@media (width>=768px){.sm\:bui-display-none{display:none}.sm\:bui-display-inline{display:inline}.sm\:bui-display-inline-block{display:inline-block}.sm\:bui-display-block{display:block}}@media (width>=1024px){.md\:bui-display-none{display:none}.md\:bui-display-inline{display:inline}.md\:bui-display-inline-block{display:inline-block}.md\:bui-display-block{display:block}}@media (width>=1280px){.lg\:bui-display-none{display:none}.lg\:bui-display-inline{display:inline}.lg\:bui-display-inline-block{display:inline-block}.lg\:bui-display-block{display:block}}@media (width>=1536px){.xl\:bui-display-none{display:none}.xl\:bui-display-inline{display:inline}.xl\:bui-display-inline-block{display:inline-block}.xl\:bui-display-block{display:block}}.bui-w{width:var(--width)}.bui-min-w{min-width:var(--min-width)}.bui-max-w{max-width:var(--max-width)}@media (width>=640px){.xs\:bui-w{width:var(--width)}.xs\:bui-min-w{min-width:var(--min-width)}.xs\:bui-max-w{max-width:var(--max-width)}}@media (width>=768px){.sm\:bui-w{width:var(--width)}.sm\:bui-min-w{min-width:var(--min-width)}.sm\:bui-max-w{max-width:var(--max-width)}}@media (width>=1024px){.md\:bui-w{width:var(--width)}.md\:bui-min-w{min-width:var(--min-width)}.md\:bui-max-w{max-width:var(--max-width)}}@media (width>=1280px){.lg\:bui-w{width:var(--width)}.lg\:bui-min-w{min-width:var(--min-width)}.lg\:bui-max-w{max-width:var(--max-width)}}@media (width>=1536px){.xl\:bui-w{width:var(--width)}.xl\:bui-min-w{min-width:var(--min-width)}.xl\:bui-max-w{max-width:var(--max-width)}}.bui-h{height:var(--height)}.bui-min-h{min-height:var(--min-height)}.bui-max-h{max-height:var(--max-height)}@media (width>=640px){.xs\:bui-h{height:var(--height)}.xs\:bui-min-h{min-height:var(--min-height)}.xs\:bui-max-h{max-height:var(--max-height)}}@media (width>=768px){.sm\:bui-h{height:var(--height)}.sm\:bui-min-h{min-height:var(--min-height)}.sm\:bui-max-h{max-height:var(--max-height)}}@media (width>=1024px){.md\:bui-h{height:var(--height)}.md\:bui-min-h{min-height:var(--min-height)}.md\:bui-max-h{max-height:var(--max-height)}}@media (width>=1280px){.lg\:bui-h{height:var(--height)}.lg\:bui-min-h{min-height:var(--min-height)}.lg\:bui-max-h{max-height:var(--max-height)}}@media (width>=1536px){.xl\:bui-h{height:var(--height)}.xl\:bui-min-h{min-height:var(--min-height)}.xl\:bui-max-h{max-height:var(--max-height)}}.bui-position-absolute{position:absolute}.bui-position-fixed{position:fixed}.bui-position-sticky{position:sticky}.bui-position-relative{position:relative}.bui-position-static{position:static}@media (width>=640px){.xs\:bui-position-absolute{position:absolute}.xs\:bui-position-fixed{position:fixed}.xs\:bui-position-sticky{position:sticky}.xs\:bui-position-relative{position:relative}.xs\:bui-position-static{position:static}}@media (width>=768px){.sm\:bui-position-absolute{position:absolute}.sm\:bui-position-fixed{position:fixed}.sm\:bui-position-sticky{position:sticky}.sm\:bui-position-relative{position:relative}.sm\:bui-position-static{position:static}}@media (width>=1024px){.md\:bui-position-absolute{position:absolute}.md\:bui-position-fixed{position:fixed}.md\:bui-position-sticky{position:sticky}.md\:bui-position-relative{position:relative}.md\:bui-position-static{position:static}}@media (width>=1280px){.lg\:bui-position-absolute{position:absolute}.lg\:bui-position-fixed{position:fixed}.lg\:bui-position-sticky{position:sticky}.lg\:bui-position-relative{position:relative}.lg\:bui-position-static{position:static}}@media (width>=1536px){.xl\:bui-position-absolute{position:absolute}.xl\:bui-position-fixed{position:fixed}.xl\:bui-position-sticky{position:sticky}.xl\:bui-position-relative{position:relative}.xl\:bui-position-static{position:static}}.bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.bui-col-span-1{grid-column:span 1/span 1}.bui-col-span-2{grid-column:span 2/span 2}.bui-col-span-3{grid-column:span 3/span 3}.bui-col-span-4{grid-column:span 4/span 4}.bui-col-span-5{grid-column:span 5/span 5}.bui-col-span-6{grid-column:span 6/span 6}.bui-col-span-7{grid-column:span 7/span 7}.bui-col-span-8{grid-column:span 8/span 8}.bui-col-span-9{grid-column:span 9/span 9}.bui-col-span-10{grid-column:span 10/span 10}.bui-col-span-11{grid-column:span 11/span 11}.bui-col-span-12{grid-column:span 12/span 12}.bui-col-span-auto{grid-column:span auto/span auto}.bui-col-start-1{grid-column-start:1}.bui-col-start-2{grid-column-start:2}.bui-col-start-3{grid-column-start:3}.bui-col-start-4{grid-column-start:4}.bui-col-start-5{grid-column-start:5}.bui-col-start-6{grid-column-start:6}.bui-col-start-7{grid-column-start:7}.bui-col-start-8{grid-column-start:8}.bui-col-start-9{grid-column-start:9}.bui-col-start-10{grid-column-start:10}.bui-col-start-11{grid-column-start:11}.bui-col-start-12{grid-column-start:12}.bui-col-start-13{grid-column-start:13}.bui-col-start-auto{grid-column-start:auto}.bui-col-end-1{grid-column-end:1}.bui-col-end-2{grid-column-end:2}.bui-col-end-3{grid-column-end:3}.bui-col-end-4{grid-column-end:4}.bui-col-end-5{grid-column-end:5}.bui-col-end-6{grid-column-end:6}.bui-col-end-7{grid-column-end:7}.bui-col-end-8{grid-column-end:8}.bui-col-end-9{grid-column-end:9}.bui-col-end-10{grid-column-end:10}.bui-col-end-11{grid-column-end:11}.bui-col-end-12{grid-column-end:12}.bui-col-end-13{grid-column-end:13}.bui-col-end-auto{grid-column-end:auto}.bui-row-span-1{grid-row:span 1/span 1}.bui-row-span-2{grid-row:span 2/span 2}.bui-row-span-3{grid-row:span 3/span 3}.bui-row-span-4{grid-row:span 4/span 4}.bui-row-span-5{grid-row:span 5/span 5}.bui-row-span-6{grid-row:span 6/span 6}.bui-row-span-7{grid-row:span 7/span 7}.bui-row-span-8{grid-row:span 8/span 8}.bui-row-span-9{grid-row:span 9/span 9}.bui-row-span-10{grid-row:span 10/span 10}.bui-row-span-11{grid-row:span 11/span 11}.bui-row-span-12{grid-row:span 12/span 12}.bui-row-span-auto{grid-row:span auto/span auto}@media (width>=640px){.xs\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xs\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xs\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xs\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xs\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xs\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xs\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xs\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xs\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xs\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xs\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xs\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xs\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xs\:bui-col-span-1{grid-column:span 1/span 1}.xs\:bui-col-span-2{grid-column:span 2/span 2}.xs\:bui-col-span-3{grid-column:span 3/span 3}.xs\:bui-col-span-4{grid-column:span 4/span 4}.xs\:bui-col-span-5{grid-column:span 5/span 5}.xs\:bui-col-span-6{grid-column:span 6/span 6}.xs\:bui-col-span-7{grid-column:span 7/span 7}.xs\:bui-col-span-8{grid-column:span 8/span 8}.xs\:bui-col-span-9{grid-column:span 9/span 9}.xs\:bui-col-span-10{grid-column:span 10/span 10}.xs\:bui-col-span-11{grid-column:span 11/span 11}.xs\:bui-col-span-12{grid-column:span 12/span 12}.xs\:bui-col-span-auto{grid-column:span auto/span auto}.xs\:bui-col-start-1{grid-column-start:1}.xs\:bui-col-start-2{grid-column-start:2}.xs\:bui-col-start-3{grid-column-start:3}.xs\:bui-col-start-4{grid-column-start:4}.xs\:bui-col-start-5{grid-column-start:5}.xs\:bui-col-start-6{grid-column-start:6}.xs\:bui-col-start-7{grid-column-start:7}.xs\:bui-col-start-8{grid-column-start:8}.xs\:bui-col-start-9{grid-column-start:9}.xs\:bui-col-start-10{grid-column-start:10}.xs\:bui-col-start-11{grid-column-start:11}.xs\:bui-col-start-12{grid-column-start:12}.xs\:bui-col-start-13{grid-column-start:13}.xs\:bui-col-start-auto{grid-column-start:auto}.xs\:bui-col-end-1{grid-column-end:1}.xs\:bui-col-end-2{grid-column-end:2}.xs\:bui-col-end-3{grid-column-end:3}.xs\:bui-col-end-4{grid-column-end:4}.xs\:bui-col-end-5{grid-column-end:5}.xs\:bui-col-end-6{grid-column-end:6}.xs\:bui-col-end-7{grid-column-end:7}.xs\:bui-col-end-8{grid-column-end:8}.xs\:bui-col-end-9{grid-column-end:9}.xs\:bui-col-end-10{grid-column-end:10}.xs\:bui-col-end-11{grid-column-end:11}.xs\:bui-col-end-12{grid-column-end:12}.xs\:bui-col-end-13{grid-column-end:13}.xs\:bui-col-end-auto{grid-column-end:auto}.xs\:bui-row-span-1{grid-row:span 1/span 1}.xs\:bui-row-span-2{grid-row:span 2/span 2}.xs\:bui-row-span-3{grid-row:span 3/span 3}.xs\:bui-row-span-4{grid-row:span 4/span 4}.xs\:bui-row-span-5{grid-row:span 5/span 5}.xs\:bui-row-span-6{grid-row:span 6/span 6}.xs\:bui-row-span-7{grid-row:span 7/span 7}.xs\:bui-row-span-8{grid-row:span 8/span 8}.xs\:bui-row-span-9{grid-row:span 9/span 9}.xs\:bui-row-span-10{grid-row:span 10/span 10}.xs\:bui-row-span-11{grid-row:span 11/span 11}.xs\:bui-row-span-12{grid-row:span 12/span 12}.xs\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=768px){.sm\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.sm\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:bui-col-span-1{grid-column:span 1/span 1}.sm\:bui-col-span-2{grid-column:span 2/span 2}.sm\:bui-col-span-3{grid-column:span 3/span 3}.sm\:bui-col-span-4{grid-column:span 4/span 4}.sm\:bui-col-span-5{grid-column:span 5/span 5}.sm\:bui-col-span-6{grid-column:span 6/span 6}.sm\:bui-col-span-7{grid-column:span 7/span 7}.sm\:bui-col-span-8{grid-column:span 8/span 8}.sm\:bui-col-span-9{grid-column:span 9/span 9}.sm\:bui-col-span-10{grid-column:span 10/span 10}.sm\:bui-col-span-11{grid-column:span 11/span 11}.sm\:bui-col-span-12{grid-column:span 12/span 12}.sm\:bui-col-span-auto{grid-column:span auto/span auto}.sm\:bui-col-start-1{grid-column-start:1}.sm\:bui-col-start-2{grid-column-start:2}.sm\:bui-col-start-3{grid-column-start:3}.sm\:bui-col-start-4{grid-column-start:4}.sm\:bui-col-start-5{grid-column-start:5}.sm\:bui-col-start-6{grid-column-start:6}.sm\:bui-col-start-7{grid-column-start:7}.sm\:bui-col-start-8{grid-column-start:8}.sm\:bui-col-start-9{grid-column-start:9}.sm\:bui-col-start-10{grid-column-start:10}.sm\:bui-col-start-11{grid-column-start:11}.sm\:bui-col-start-12{grid-column-start:12}.sm\:bui-col-start-13{grid-column-start:13}.sm\:bui-col-start-auto{grid-column-start:auto}.sm\:bui-col-end-1{grid-column-end:1}.sm\:bui-col-end-2{grid-column-end:2}.sm\:bui-col-end-3{grid-column-end:3}.sm\:bui-col-end-4{grid-column-end:4}.sm\:bui-col-end-5{grid-column-end:5}.sm\:bui-col-end-6{grid-column-end:6}.sm\:bui-col-end-7{grid-column-end:7}.sm\:bui-col-end-8{grid-column-end:8}.sm\:bui-col-end-9{grid-column-end:9}.sm\:bui-col-end-10{grid-column-end:10}.sm\:bui-col-end-11{grid-column-end:11}.sm\:bui-col-end-12{grid-column-end:12}.sm\:bui-col-end-13{grid-column-end:13}.sm\:bui-col-end-auto{grid-column-end:auto}.sm\:bui-row-span-1{grid-row:span 1/span 1}.sm\:bui-row-span-2{grid-row:span 2/span 2}.sm\:bui-row-span-3{grid-row:span 3/span 3}.sm\:bui-row-span-4{grid-row:span 4/span 4}.sm\:bui-row-span-5{grid-row:span 5/span 5}.sm\:bui-row-span-6{grid-row:span 6/span 6}.sm\:bui-row-span-7{grid-row:span 7/span 7}.sm\:bui-row-span-8{grid-row:span 8/span 8}.sm\:bui-row-span-9{grid-row:span 9/span 9}.sm\:bui-row-span-10{grid-row:span 10/span 10}.sm\:bui-row-span-11{grid-row:span 11/span 11}.sm\:bui-row-span-12{grid-row:span 12/span 12}.sm\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1024px){.md\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.md\:bui-col-span-1{grid-column:span 1/span 1}.md\:bui-col-span-2{grid-column:span 2/span 2}.md\:bui-col-span-3{grid-column:span 3/span 3}.md\:bui-col-span-4{grid-column:span 4/span 4}.md\:bui-col-span-5{grid-column:span 5/span 5}.md\:bui-col-span-6{grid-column:span 6/span 6}.md\:bui-col-span-7{grid-column:span 7/span 7}.md\:bui-col-span-8{grid-column:span 8/span 8}.md\:bui-col-span-9{grid-column:span 9/span 9}.md\:bui-col-span-10{grid-column:span 10/span 10}.md\:bui-col-span-11{grid-column:span 11/span 11}.md\:bui-col-span-12{grid-column:span 12/span 12}.md\:bui-col-span-auto{grid-column:span auto/span auto}.md\:bui-col-start-1{grid-column-start:1}.md\:bui-col-start-2{grid-column-start:2}.md\:bui-col-start-3{grid-column-start:3}.md\:bui-col-start-4{grid-column-start:4}.md\:bui-col-start-5{grid-column-start:5}.md\:bui-col-start-6{grid-column-start:6}.md\:bui-col-start-7{grid-column-start:7}.md\:bui-col-start-8{grid-column-start:8}.md\:bui-col-start-9{grid-column-start:9}.md\:bui-col-start-10{grid-column-start:10}.md\:bui-col-start-11{grid-column-start:11}.md\:bui-col-start-12{grid-column-start:12}.md\:bui-col-start-13{grid-column-start:13}.md\:bui-col-start-auto{grid-column-start:auto}.md\:bui-col-end-1{grid-column-end:1}.md\:bui-col-end-2{grid-column-end:2}.md\:bui-col-end-3{grid-column-end:3}.md\:bui-col-end-4{grid-column-end:4}.md\:bui-col-end-5{grid-column-end:5}.md\:bui-col-end-6{grid-column-end:6}.md\:bui-col-end-7{grid-column-end:7}.md\:bui-col-end-8{grid-column-end:8}.md\:bui-col-end-9{grid-column-end:9}.md\:bui-col-end-10{grid-column-end:10}.md\:bui-col-end-11{grid-column-end:11}.md\:bui-col-end-12{grid-column-end:12}.md\:bui-col-end-13{grid-column-end:13}.md\:bui-col-end-auto{grid-column-end:auto}.md\:bui-row-span-1{grid-row:span 1/span 1}.md\:bui-row-span-2{grid-row:span 2/span 2}.md\:bui-row-span-3{grid-row:span 3/span 3}.md\:bui-row-span-4{grid-row:span 4/span 4}.md\:bui-row-span-5{grid-row:span 5/span 5}.md\:bui-row-span-6{grid-row:span 6/span 6}.md\:bui-row-span-7{grid-row:span 7/span 7}.md\:bui-row-span-8{grid-row:span 8/span 8}.md\:bui-row-span-9{grid-row:span 9/span 9}.md\:bui-row-span-10{grid-row:span 10/span 10}.md\:bui-row-span-11{grid-row:span 11/span 11}.md\:bui-row-span-12{grid-row:span 12/span 12}.md\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1280px){.lg\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.lg\:bui-col-span-1{grid-column:span 1/span 1}.lg\:bui-col-span-2{grid-column:span 2/span 2}.lg\:bui-col-span-3{grid-column:span 3/span 3}.lg\:bui-col-span-4{grid-column:span 4/span 4}.lg\:bui-col-span-5{grid-column:span 5/span 5}.lg\:bui-col-span-6{grid-column:span 6/span 6}.lg\:bui-col-span-7{grid-column:span 7/span 7}.lg\:bui-col-span-8{grid-column:span 8/span 8}.lg\:bui-col-span-9{grid-column:span 9/span 9}.lg\:bui-col-span-10{grid-column:span 10/span 10}.lg\:bui-col-span-11{grid-column:span 11/span 11}.lg\:bui-col-span-12{grid-column:span 12/span 12}.lg\:bui-col-span-auto{grid-column:span auto/span auto}.lg\:bui-col-start-1{grid-column-start:1}.lg\:bui-col-start-2{grid-column-start:2}.lg\:bui-col-start-3{grid-column-start:3}.lg\:bui-col-start-4{grid-column-start:4}.lg\:bui-col-start-5{grid-column-start:5}.lg\:bui-col-start-6{grid-column-start:6}.lg\:bui-col-start-7{grid-column-start:7}.lg\:bui-col-start-8{grid-column-start:8}.lg\:bui-col-start-9{grid-column-start:9}.lg\:bui-col-start-10{grid-column-start:10}.lg\:bui-col-start-11{grid-column-start:11}.lg\:bui-col-start-12{grid-column-start:12}.lg\:bui-col-start-13{grid-column-start:13}.lg\:bui-col-start-auto{grid-column-start:auto}.lg\:bui-col-end-1{grid-column-end:1}.lg\:bui-col-end-2{grid-column-end:2}.lg\:bui-col-end-3{grid-column-end:3}.lg\:bui-col-end-4{grid-column-end:4}.lg\:bui-col-end-5{grid-column-end:5}.lg\:bui-col-end-6{grid-column-end:6}.lg\:bui-col-end-7{grid-column-end:7}.lg\:bui-col-end-8{grid-column-end:8}.lg\:bui-col-end-9{grid-column-end:9}.lg\:bui-col-end-10{grid-column-end:10}.lg\:bui-col-end-11{grid-column-end:11}.lg\:bui-col-end-12{grid-column-end:12}.lg\:bui-col-end-13{grid-column-end:13}.lg\:bui-col-end-auto{grid-column-end:auto}.lg\:bui-row-span-1{grid-row:span 1/span 1}.lg\:bui-row-span-2{grid-row:span 2/span 2}.lg\:bui-row-span-3{grid-row:span 3/span 3}.lg\:bui-row-span-4{grid-row:span 4/span 4}.lg\:bui-row-span-5{grid-row:span 5/span 5}.lg\:bui-row-span-6{grid-row:span 6/span 6}.lg\:bui-row-span-7{grid-row:span 7/span 7}.lg\:bui-row-span-8{grid-row:span 8/span 8}.lg\:bui-row-span-9{grid-row:span 9/span 9}.lg\:bui-row-span-10{grid-row:span 10/span 10}.lg\:bui-row-span-11{grid-row:span 11/span 11}.lg\:bui-row-span-12{grid-row:span 12/span 12}.lg\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1536px){.xl\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xl\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xl\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xl\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xl\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xl\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xl\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xl\:bui-col-span-1{grid-column:span 1/span 1}.xl\:bui-col-span-2{grid-column:span 2/span 2}.xl\:bui-col-span-3{grid-column:span 3/span 3}.xl\:bui-col-span-4{grid-column:span 4/span 4}.xl\:bui-col-span-5{grid-column:span 5/span 5}.xl\:bui-col-span-6{grid-column:span 6/span 6}.xl\:bui-col-span-7{grid-column:span 7/span 7}.xl\:bui-col-span-8{grid-column:span 8/span 8}.xl\:bui-col-span-9{grid-column:span 9/span 9}.xl\:bui-col-span-10{grid-column:span 10/span 10}.xl\:bui-col-span-11{grid-column:span 11/span 11}.xl\:bui-col-span-12{grid-column:span 12/span 12}.xl\:bui-col-span-auto{grid-column:span auto/span auto}.xl\:bui-col-start-1{grid-column-start:1}.xl\:bui-col-start-2{grid-column-start:2}.xl\:bui-col-start-3{grid-column-start:3}.xl\:bui-col-start-4{grid-column-start:4}.xl\:bui-col-start-5{grid-column-start:5}.xl\:bui-col-start-6{grid-column-start:6}.xl\:bui-col-start-7{grid-column-start:7}.xl\:bui-col-start-8{grid-column-start:8}.xl\:bui-col-start-9{grid-column-start:9}.xl\:bui-col-start-10{grid-column-start:10}.xl\:bui-col-start-11{grid-column-start:11}.xl\:bui-col-start-12{grid-column-start:12}.xl\:bui-col-start-13{grid-column-start:13}.xl\:bui-col-start-auto{grid-column-start:auto}.xl\:bui-col-end-1{grid-column-end:1}.xl\:bui-col-end-2{grid-column-end:2}.xl\:bui-col-end-3{grid-column-end:3}.xl\:bui-col-end-4{grid-column-end:4}.xl\:bui-col-end-5{grid-column-end:5}.xl\:bui-col-end-6{grid-column-end:6}.xl\:bui-col-end-7{grid-column-end:7}.xl\:bui-col-end-8{grid-column-end:8}.xl\:bui-col-end-9{grid-column-end:9}.xl\:bui-col-end-10{grid-column-end:10}.xl\:bui-col-end-11{grid-column-end:11}.xl\:bui-col-end-12{grid-column-end:12}.xl\:bui-col-end-13{grid-column-end:13}.xl\:bui-col-end-auto{grid-column-end:auto}.xl\:bui-row-span-1{grid-row:span 1/span 1}.xl\:bui-row-span-2{grid-row:span 2/span 2}.xl\:bui-row-span-3{grid-row:span 3/span 3}.xl\:bui-row-span-4{grid-row:span 4/span 4}.xl\:bui-row-span-5{grid-row:span 5/span 5}.xl\:bui-row-span-6{grid-row:span 6/span 6}.xl\:bui-row-span-7{grid-row:span 7/span 7}.xl\:bui-row-span-8{grid-row:span 8/span 8}.xl\:bui-row-span-9{grid-row:span 9/span 9}.xl\:bui-row-span-10{grid-row:span 10/span 10}.xl\:bui-row-span-11{grid-row:span 11/span 11}.xl\:bui-row-span-12{grid-row:span 12/span 12}.xl\:bui-row-span-auto{grid-row:span auto/span auto}}.bui-gap{gap:var(--gap)}.bui-gap-0\.5{gap:var(--bui-space-0_5)}.bui-gap-1{gap:var(--bui-space-1)}.bui-gap-1\.5{gap:var(--bui-space-1_5)}.bui-gap-2{gap:var(--bui-space-2)}.bui-gap-3{gap:var(--bui-space-3)}.bui-gap-4{gap:var(--bui-space-4)}.bui-gap-5{gap:var(--bui-space-5)}.bui-gap-6{gap:var(--bui-space-6)}.bui-gap-7{gap:var(--bui-space-7)}.bui-gap-8{gap:var(--bui-space-8)}.bui-gap-9{gap:var(--bui-space-9)}.bui-gap-10{gap:var(--bui-space-10)}.bui-gap-11{gap:var(--bui-space-11)}.bui-gap-12{gap:var(--bui-space-12)}.bui-gap-13{gap:var(--bui-space-13)}.bui-gap-14{gap:var(--bui-space-14)}@media (width>=640px){.xs\:bui-gap{gap:var(--gap-xs)}.xs\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xs\:bui-gap-1{gap:var(--bui-space-1)}.xs\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xs\:bui-gap-2{gap:var(--bui-space-2)}.xs\:bui-gap-3{gap:var(--bui-space-3)}.xs\:bui-gap-4{gap:var(--bui-space-4)}.xs\:bui-gap-5{gap:var(--bui-space-5)}.xs\:bui-gap-6{gap:var(--bui-space-6)}.xs\:bui-gap-7{gap:var(--bui-space-7)}.xs\:bui-gap-8{gap:var(--bui-space-8)}.xs\:bui-gap-9{gap:var(--bui-space-9)}.xs\:bui-gap-10{gap:var(--bui-space-10)}.xs\:bui-gap-11{gap:var(--bui-space-11)}.xs\:bui-gap-12{gap:var(--bui-space-12)}.xs\:bui-gap-13{gap:var(--bui-space-13)}.xs\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-gap{gap:var(--gap-sm)}.sm\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.sm\:bui-gap-1{gap:var(--bui-space-1)}.sm\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.sm\:bui-gap-2{gap:var(--bui-space-2)}.sm\:bui-gap-3{gap:var(--bui-space-3)}.sm\:bui-gap-4{gap:var(--bui-space-4)}.sm\:bui-gap-5{gap:var(--bui-space-5)}.sm\:bui-gap-6{gap:var(--bui-space-6)}.sm\:bui-gap-7{gap:var(--bui-space-7)}.sm\:bui-gap-8{gap:var(--bui-space-8)}.sm\:bui-gap-9{gap:var(--bui-space-9)}.sm\:bui-gap-10{gap:var(--bui-space-10)}.sm\:bui-gap-11{gap:var(--bui-space-11)}.sm\:bui-gap-12{gap:var(--bui-space-12)}.sm\:bui-gap-13{gap:var(--bui-space-13)}.sm\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-gap{gap:var(--gap-md)}.md\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.md\:bui-gap-1{gap:var(--bui-space-1)}.md\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.md\:bui-gap-2{gap:var(--bui-space-2)}.md\:bui-gap-3{gap:var(--bui-space-3)}.md\:bui-gap-4{gap:var(--bui-space-4)}.md\:bui-gap-5{gap:var(--bui-space-5)}.md\:bui-gap-6{gap:var(--bui-space-6)}.md\:bui-gap-7{gap:var(--bui-space-7)}.md\:bui-gap-8{gap:var(--bui-space-8)}.md\:bui-gap-9{gap:var(--bui-space-9)}.md\:bui-gap-10{gap:var(--bui-space-10)}.md\:bui-gap-11{gap:var(--bui-space-11)}.md\:bui-gap-12{gap:var(--bui-space-12)}.md\:bui-gap-13{gap:var(--bui-space-13)}.md\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-gap{gap:var(--gap-lg)}.lg\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.lg\:bui-gap-1{gap:var(--bui-space-1)}.lg\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.lg\:bui-gap-2{gap:var(--bui-space-2)}.lg\:bui-gap-3{gap:var(--bui-space-3)}.lg\:bui-gap-4{gap:var(--bui-space-4)}.lg\:bui-gap-5{gap:var(--bui-space-5)}.lg\:bui-gap-6{gap:var(--bui-space-6)}.lg\:bui-gap-7{gap:var(--bui-space-7)}.lg\:bui-gap-8{gap:var(--bui-space-8)}.lg\:bui-gap-9{gap:var(--bui-space-9)}.lg\:bui-gap-10{gap:var(--bui-space-10)}.lg\:bui-gap-11{gap:var(--bui-space-11)}.lg\:bui-gap-12{gap:var(--bui-space-12)}.lg\:bui-gap-13{gap:var(--bui-space-13)}.lg\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-gap{gap:var(--gap-xl)}.xl\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xl\:bui-gap-1{gap:var(--bui-space-1)}.xl\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xl\:bui-gap-2{gap:var(--bui-space-2)}.xl\:bui-gap-3{gap:var(--bui-space-3)}.xl\:bui-gap-4{gap:var(--bui-space-4)}.xl\:bui-gap-5{gap:var(--bui-space-5)}.xl\:bui-gap-6{gap:var(--bui-space-6)}.xl\:bui-gap-7{gap:var(--bui-space-7)}.xl\:bui-gap-8{gap:var(--bui-space-8)}.xl\:bui-gap-9{gap:var(--bui-space-9)}.xl\:bui-gap-10{gap:var(--bui-space-10)}.xl\:bui-gap-11{gap:var(--bui-space-11)}.xl\:bui-gap-12{gap:var(--bui-space-12)}.xl\:bui-gap-13{gap:var(--bui-space-13)}.xl\:bui-gap-14{gap:var(--bui-space-14)}}.bui-align-start{align-items:start}.bui-align-center{align-items:center}.bui-align-end{align-items:end}.bui-align-baseline{align-items:baseline}.bui-align-stretch{align-items:stretch}.bui-jc-start{justify-content:start}.bui-jc-center{justify-content:center}.bui-jc-end{justify-content:end}.bui-jc-between{justify-content:space-between}.bui-fd-row{flex-direction:row}.bui-fd-column{flex-direction:column}.bui-fd-row-reverse{flex-direction:row-reverse}.bui-fd-column-reverse{flex-direction:column-reverse}@media (width>=640px){.xs\:bui-align-start{align-items:start}.xs\:bui-align-center{align-items:center}.xs\:bui-align-end{align-items:end}.xs\:bui-align-stretch{align-items:stretch}.xs\:bui-jc-start{justify-content:start}.xs\:bui-jc-center{justify-content:center}.xs\:bui-jc-end{justify-content:end}.xs\:bui-jc-between{justify-content:space-between}.xs\:bui-fd-row{flex-direction:row}.xs\:bui-fd-column{flex-direction:column}.xs\:bui-fd-row-reverse{flex-direction:row-reverse}.xs\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=768px){.sm\:bui-align-start{align-items:start}.sm\:bui-align-center{align-items:center}.sm\:bui-align-end{align-items:end}.sm\:bui-align-stretch{align-items:stretch}.sm\:bui-jc-start{justify-content:start}.sm\:bui-jc-center{justify-content:center}.sm\:bui-jc-end{justify-content:end}.sm\:bui-jc-between{justify-content:space-between}.sm\:bui-fd-row{flex-direction:row}.sm\:bui-fd-column{flex-direction:column}.sm\:bui-fd-row-reverse{flex-direction:row-reverse}.sm\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1024px){.md\:bui-align-start{align-items:start}.md\:bui-align-center{align-items:center}.md\:bui-align-end{align-items:end}.md\:bui-align-stretch{align-items:stretch}.md\:bui-jc-start{justify-content:start}.md\:bui-jc-center{justify-content:center}.md\:bui-jc-end{justify-content:end}.md\:bui-jc-between{justify-content:space-between}.md\:bui-fd-row{flex-direction:row}.md\:bui-fd-column{flex-direction:column}.md\:bui-fd-row-reverse{flex-direction:row-reverse}.md\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1280px){.lg\:bui-align-start{align-items:start}.lg\:bui-align-center{align-items:center}.lg\:bui-align-end{align-items:end}.lg\:bui-align-stretch{align-items:stretch}.lg\:bui-jc-start{justify-content:start}.lg\:bui-jc-center{justify-content:center}.lg\:bui-jc-end{justify-content:end}.lg\:bui-jc-between{justify-content:space-between}.lg\:bui-fd-row{flex-direction:row}.lg\:bui-fd-column{flex-direction:column}.lg\:bui-fd-row-reverse{flex-direction:row-reverse}.lg\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1536px){.xl\:bui-align-start{align-items:start}.xl\:bui-align-center{align-items:center}.xl\:bui-align-end{align-items:end}.xl\:bui-align-stretch{align-items:stretch}.xl\:bui-jc-start{justify-content:start}.xl\:bui-jc-center{justify-content:center}.xl\:bui-jc-end{justify-content:end}.xl\:bui-jc-between{justify-content:space-between}.xl\:bui-fd-row{flex-direction:row}.xl\:bui-fd-column{flex-direction:column}.xl\:bui-fd-row-reverse{flex-direction:row-reverse}.xl\:bui-fd-column-reverse{flex-direction:column-reverse}}:where(a){color:inherit;text-decoration:none}@keyframes pulse{50%{opacity:.5}}:root{--bui-font-regular:system-ui;--bui-font-monospace:ui-monospace,"Menlo","Monaco","Consolas","Liberation Mono","Courier New",monospace;--bui-font-weight-regular:400;--bui-font-weight-bold:600;--bui-font-size-1:.625rem;--bui-font-size-2:.75rem;--bui-font-size-3:.875rem;--bui-font-size-4:1rem;--bui-font-size-5:1.25rem;--bui-font-size-6:1.5rem;--bui-font-size-7:2rem;--bui-font-size-8:3rem;--bui-font-size-9:4rem;--bui-font-size-10:5.75rem;--bui-space:.25rem;--bui-space-0_5:calc(var(--bui-space)*.5);--bui-space-1:var(--bui-space);--bui-space-1_5:calc(var(--bui-space)*1.5);--bui-space-2:calc(var(--bui-space)*2);--bui-space-3:calc(var(--bui-space)*3);--bui-space-4:calc(var(--bui-space)*4);--bui-space-5:calc(var(--bui-space)*5);--bui-space-6:calc(var(--bui-space)*6);--bui-space-7:calc(var(--bui-space)*7);--bui-space-8:calc(var(--bui-space)*8);--bui-space-9:calc(var(--bui-space)*9);--bui-space-10:calc(var(--bui-space)*10);--bui-space-11:calc(var(--bui-space)*11);--bui-space-12:calc(var(--bui-space)*12);--bui-space-13:calc(var(--bui-space)*13);--bui-space-14:calc(var(--bui-space)*14);--bui-radius-1:calc(.125rem);--bui-radius-2:calc(.25rem);--bui-radius-3:calc(.5rem);--bui-radius-4:calc(.75rem);--bui-radius-5:calc(1rem);--bui-radius-6:calc(1.25rem);--bui-radius-full:9999px;--bui-black:#000;--bui-white:#fff;--bui-gray-1:#f8f8f8;--bui-gray-2:#ececec;--bui-gray-3:#d9d9d9;--bui-gray-4:#c1c1c1;--bui-gray-5:#9e9e9e;--bui-gray-6:#8c8c8c;--bui-gray-7:#757575;--bui-gray-8:#595959;--bui-bg:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1f5493;--bui-bg-solid-hover:#163a66;--bui-bg-solid-pressed:#0f2b4e;--bui-bg-solid-disabled:#ebebeb;--bui-bg-tint:transparent;--bui-bg-tint-hover:#1f549366;--bui-bg-tint-pressed:#1f549399;--bui-bg-tint-disabled:#ebebeb;--bui-bg-danger:#feebe7;--bui-bg-warning:#fff2b2;--bui-bg-success:#e6f6eb;--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#1f5493;--bui-fg-link-hover:#1f2d5c;--bui-fg-disabled:#9e9e9e;--bui-fg-solid:var(--bui-white);--bui-fg-solid-disabled:#9c9c9c;--bui-fg-tint:#1f5493;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#0000001a;--bui-border-hover:#0003;--bui-border-pressed:#0006;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#a0a0a03b;--bui-scrollbar-thumb:#a0a0a0;--bui-animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite}[data-theme-mode=dark]{--bui-gray-1:#191919;--bui-gray-2:#242424;--bui-gray-3:#373737;--bui-gray-4:#464646;--bui-gray-5:#575757;--bui-gray-6:#7b7b7b;--bui-gray-7:#9e9e9e;--bui-gray-8:#b4b4b4;--bui-bg:#333;--bui-bg-surface-1:#424242;--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#9cc9ff;--bui-bg-solid-hover:#83b9fd;--bui-bg-solid-pressed:#83b9fd;--bui-bg-solid-disabled:#222;--bui-bg-tint:transparent;--bui-bg-tint-hover:#9cc9ff1f;--bui-bg-tint-pressed:#9cc9ff29;--bui-bg-tint-disabled:transparent;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#9cc9ff;--bui-fg-link-hover:#7eb5f7;--bui-fg-disabled:var(--bui-gray-7);--bui-fg-solid:#101821;--bui-fg-solid-disabled:var(--bui-gray-5);--bui-fg-tint:#9cc9ff;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#ffffff1f;--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#3636363a;--bui-scrollbar-thumb:#575757}.bui-AvatarRoot{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-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}.bui-AvatarRoot[data-size=small]{width:1.5rem;height:1.5rem}.bui-AvatarRoot[data-size=medium]{width:2rem;height:2rem}.bui-AvatarRoot[data-size=large]{width:3rem;height:3rem}.bui-AvatarImage{object-fit:cover;width:100%;height:100%}.bui-AvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-Box{font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary)}.bui-Button{user-select:none;font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-bold);cursor:pointer;border-radius:var(--bui-radius-2);justify-content:center;align-items:center;gap:var(--bui-space-1_5);border:none;flex-shrink:0;padding:0;display:inline-flex;&[data-disabled=true]{cursor:not-allowed}}.bui-Button[data-variant=primary]{background-color:var(--bui-bg-solid);color:var(--bui-fg-solid);&:hover{background-color:var(--bui-bg-solid-hover);transition:background-color .15s}&:active{background-color:var(--bui-bg-solid-pressed)}&:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled=true]{background-color:var(--bui-bg-solid-disabled);color:var(--bui-fg-solid-disabled)}}.bui-Button[data-variant=secondary]{background-color:var(--bui-bg-surface-1);box-shadow:inset 0 0 0 1px var(--bui-border);color:var(--bui-fg-primary);&:hover{box-shadow:inset 0 0 0 1px var(--bui-border-hover);transition:box-shadow .15s}&:active{box-shadow:inset 0 0 0 1px var(--bui-border-pressed)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{box-shadow:inset 0 0 0 1px var(--bui-border-disabled);color:var(--bui-fg-disabled)}}.bui-Button[data-variant=tertiary]{color:var(--bui-fg-primary);background-color:#0000;&:hover{background-color:var(--bui-bg-surface-1);transition:background-color .2s}&:active{background-color:var(--bui-bg-surface-2)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{color:var(--bui-fg-disabled);background-color:#0000}}.bui-Button[data-size=medium]{font-size:var(--bui-font-size-4);padding:0 var(--bui-space-3);height:2.5rem}.bui-Button[data-size=small]{font-size:var(--bui-font-size-3);padding:0 var(--bui-space-2);height:2rem}.bui-Button[data-size=small] svg{width:1rem;height:1rem}.bui-Button[data-size=medium] svg{width:1.25rem;height:1.25rem}.bui-ButtonIcon{justify-content:center;align-items:center}.bui-ButtonIcon[data-size=small]{width:2rem;padding:0}.bui-ButtonIcon[data-size=medium]{width:2.5rem;padding:0}.bui-Card{gap:var(--bui-space-3);background-color:var(--bui-bg-surface-1);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-3);color:var(--bui-fg-primary);border:1px solid var(--bui-border);flex-direction:column;width:100%;min-height:0;display:flex;overflow:hidden}.bui-CardBody{flex:1;min-height:0;overflow:auto}.bui-CardHeader,.bui-CardFooter{padding-inline:var(--bui-space-3)}.bui-CheckboxRoot{width:1rem;height:1rem;box-shadow:inset 0 0 0 1px var(--bui-border);cursor:pointer;background-color:var(--bui-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}.bui-CheckboxRoot:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px;transition:none}.bui-CheckboxRoot[data-checked]{background-color:var(--bui-bg-solid);box-shadow:none;color:var(--bui-fg-solid)}.bui-CheckboxLabel{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);user-select:none;flex-direction:row;display:flex;&:hover{& .bui-CheckboxRoot:not([data-checked]){box-shadow:inset 0 0 0 1px var(--bui-border-hover)}}}.bui-CheckboxIndicator{color:var(--bui-fg-solid);justify-content:center;align-items:center;display:flex}.bui-CollapsiblePanel{height:var(--collapsible-panel-height);transition:all .15s ease-out;display:flex;overflow:hidden;&[data-starting-style],&[data-ending-style]{height:0}}.bui-Container{max-width:120rem;padding-inline:var(--bui-space-4);margin-inline:auto;transition:padding .2s ease-in-out}@media (width>=640px){.bui-Container{padding-inline:var(--bui-space-5)}}.bui-FieldError{color:var(--bui-fg-danger);font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);margin-top:var(--bui-space-2);display:inline-block}.bui-FieldLabelWrapper{margin-bottom:var(--bui-space-3);gap:var(--bui-space-1);flex-direction:column;display:flex}.bui-FieldLabel{color:var(--bui-fg-primary);cursor:pointer;font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);margin-right:auto}.bui-FieldSecondaryLabel{color:var(--bui-fg-secondary);font-weight:var(--bui-font-weight-regular);margin-left:var(--bui-space-1)}.bui-FieldDescription{font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);color:var(--bui-fg-secondary);margin:0}.bui-Flex{min-width:0;display:flex}.bui-Grid{display:grid}.bui-HeaderToolbar{margin-bottom:var(--bui-space-6);&:before{content:"";background-color:var(--bui-bg);z-index:0;height:16px;position:absolute;top:0;left:0;right:0}&[data-has-tabs=true]{margin-bottom:0}}.bui-HeaderToolbarWrapper{z-index:1;background-color:var(--bui-bg-surface-1);padding-inline:var(--bui-space-5);border-bottom:1px solid var(--bui-border);color:var(--bui-fg-primary);flex-direction:row;justify-content:space-between;align-items:center;height:52px;display:flex;position:relative}.bui-HeaderToolbarContent{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-HeaderToolbarName{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);flex-direction:row;flex-shrink:0;display:flex}.bui-HeaderToolbarIcon{width:16px;height:16px;color:var(--bui-fg-primary);& svg{width:100%;height:100%}}.bui-HeaderToolbarControls{right:var(--bui-space-5);align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex;position:absolute;top:50%;transform:translateY(-50%)}.bui-HeaderTabsWrapper{margin-bottom:var(--bui-space-4);padding-inline:var(--bui-space-3);border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1)}.bui-HeaderPage{gap:var(--bui-space-1);margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6);flex-direction:column;display:flex}.bui-HeaderPageContent{flex-direction:row;justify-content:space-between;display:flex}.bui-HeaderPageTabsWrapper{margin-left:-8px}.bui-HeaderPageControls,.bui-HeaderPageBreadcrumbs{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-Icon{width:1rem;height:1rem}.bui-Link{font-family:var(--bui-font-regular);cursor:pointer;margin:0;padding:0;text-decoration-line:none;display:inline-block;&: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,currentColor 30%,transparent)}}.bui-MenuPopover{border:1px solid var(--bui-border);border-radius:var(--bui-radius-2);background:var(--bui-bg-surface-1);color:var(--bui-fg-primary);outline:none;flex-direction:column;min-height:0;transition:transform .2s,opacity .2s;display:flex;overflow:hidden;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}&[data-placement=top]{--origin:translateY(8px)}&[data-placement=bottom]{--origin:translateY(-8px)}&[data-placement=right]{--origin:translateX(-8px)}&[data-placement=left]{--origin:translateX(8px)}}.bui-MenuContent{max-height:inherit;box-sizing:border-box;padding:var(--bui-space-1);outline:none;min-width:150px;overflow:auto}.bui-MenuPopover .bui-ScrollAreaRoot{flex-direction:column;flex:1;height:100%;min-height:0;display:flex}.bui-MenuPopover .bui-ScrollAreaScrollbar{margin-inline:var(--bui-space-1_5)}.bui-MenuItem{height:2rem;padding-inline:var(--bui-space-2);border-radius:var(--bui-radius-2);cursor:default;color:var(--bui-fg-primary);font-size:var(--bui-font-size-3);justify-content:space-between;align-items:center;gap:var(--bui-space-6);outline:none;display:flex;&[data-focused],&[data-open]{background:var(--bui-bg-surface-2);color:var(--bui-fg-primary)}&[data-color=danger]{color:var(--bui-fg-danger)}&[data-color=danger][data-focused]{background:var(--bui-bg-danger);color:var(--bui-fg-danger)}&[data-has-submenu]{&>.bui-MenuItemArrow{display:block}}}.bui-MenuItemListBox{height:2rem;padding-inline:var(--bui-space-2);border-radius:var(--bui-radius-2);cursor:default;color:var(--bui-fg-primary);font-size:var(--bui-font-size-3);justify-content:space-between;align-items:center;gap:var(--bui-space-6);outline:none;display:flex;&:hover{background:var(--bui-bg-surface-2);color:var(--bui-fg-primary)}&[data-selected] .bui-MenuItemListBoxCheck{&>svg{opacity:1;color:var(--bui-fg-primary)}}}.bui-MenuItemListBoxCheck{justify-content:center;align-items:center;width:1rem;height:1rem;display:flex;&>svg{opacity:0;width:1rem;height:1rem}}.bui-MenuItemContent{align-items:center;gap:var(--bui-space-2);display:flex;&>svg{width:1rem;height:1rem}}.bui-MenuItemArrow{width:1rem;height:1rem;display:none;&>svg{width:1rem;height:1rem}}.bui-MenuSection{&:first-child .bui-MenuSectionHeader{padding-top:0}}.bui-MenuSectionHeader{height:2rem;padding-top:var(--bui-space-3);padding-left:var(--bui-space-2);color:var(--bui-fg-primary);font-size:var(--bui-font-size-1);letter-spacing:.05rem;text-transform:uppercase;align-items:center;font-weight:700;display:flex}.bui-MenuSeparator{background:var(--bui-border);height:1px;margin-inline:var(--bui-space-1_5);margin-block:var(--bui-space-1)}.bui-MenuSearchField{font-family:var(--bui-font-regular);flex-shrink:0;width:100%;position:relative;&[data-empty]{& .bui-MenuSearchFieldClear{display:none}}}.bui-MenuSearchFieldInput{padding:0 var(--bui-space-3);border:none;border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);width:100%;height:2rem;cursor:inherit;outline:none;align-items:center;display:flex;&::-webkit-search-cancel-button,&::-webkit-search-decoration{-webkit-appearance:none}}.bui-MenuSearchFieldClear{right:var(--bui-space-2);cursor:pointer;color:var(--bui-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;&>svg{width:1rem;height:1rem}}.bui-MenuEmptyState{padding:var(--bui-space-1);color:var(--bui-fg-secondary);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular)}.bui-Popover{background-color:var(--bui-bg-surface-1);border:1px solid var(--bui-border);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-1);margin-right:12px;overflow:scroll;box-shadow:0 4px 12px #0000001a}.bui-RadioGroup{color:var(--bui-fg-primary);flex-direction:column;display:flex}.bui-RadioGroup[data-orientation=horizontal] .bui-RadioGroupContent{gap:var(--bui-space-4);flex-direction:row}.bui-RadioGroupContent{gap:var(--bui-space-2);flex-direction:column;display:flex}.bui-Radio{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-2);color:var(--bui-fg-primary);forced-color-adjust:none;display:flex;position:relative;&:before{content:"";box-sizing:border-box;border:.125rem solid var(--bui-border);background:var(--bui-gray-1);border-radius:var(--bui-radius-full);width:1rem;height:1rem;transition:all .2s;display:block}&[data-pressed]:before{border-color:var(--bui-border)}&[data-selected]{&:before{border-color:var(--bui-bg-solid);border-width:.25rem}&[data-pressed]:before{border-color:var(--bui-bg-solid)}}&[data-focus-visible]:before{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}&[data-invalid]:before,&[data-invalid][data-selected]:before{border-color:var(--bui-border-danger)}&[data-disabled][data-invalid]{color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}}.bui-Table{caption-side:bottom;border-collapse:collapse;width:100%}.bui-TableHeader{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out}.bui-TableHead{text-align:left;padding:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary)}.bui-TableHeadSortButton{cursor:pointer;user-select:none;align-items:center;gap:var(--bui-space-1);display:inline-flex;&:hover svg{opacity:.5}& svg{opacity:0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}&[data-sort-order=asc] svg{opacity:1;transform:rotate(0)}&[data-sort-order=desc] svg{opacity:1;transform:rotate(180deg)}}.bui-TableBody{color:var(--bui-fg-primary)}.bui-TableRow{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out;&[data-react-aria-pressable=true]{cursor:pointer}}.bui-TableBody .bui-TableRow:hover{background-color:var(--bui-gray-2)}.bui-TableCell{padding:var(--bui-space-3);font-size:var(--bui-font-size-3);padding:var(--bui-space-3);font-size:var(--bui-font-size-3)}.bui-TableCellContentWrapper{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:inline-flex}.bui-TableCellIcon,.bui-TableCellIcon svg{color:var(--bui-fg-primary);align-items:center;display:inline-flex}.bui-TableCellContent{gap:var(--bui-space-0_5);flex-direction:column;display:flex}.bui-TableCellProfile{gap:var(--bui-space-2);flex-direction:row;align-items:center;display:flex}.bui-TableCellProfileAvatar{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-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}.bui-TableCellProfileAvatarImage{object-fit:cover;width:100%;height:100%}.bui-TableCellProfileAvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-DataTablePagination{padding-top:var(--bui-space-5);justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--left{justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--right{justify-content:space-between;align-items:center;gap:var(--bui-space-2);display:flex}.bui-DataTablePagination--select{min-width:10.5rem}.bui-Tabs{--active-tab-left:0px;--active-tab-right:0px;--active-tab-top:0px;--active-tab-bottom:0px;--active-tab-width:0px;--active-tab-height:0px;--active-transition-duration:0s;--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}.bui-TabList{flex-direction:row;display:flex}.bui-TabListWrapper{position:relative}.bui-Tab{font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-secondary);cursor:pointer;z-index:2;height:36px;padding-inline:var(--bui-space-2);justify-content:center;align-items:center;display:flex;position:relative;&[data-selected=true]{color:var(--bui-fg-primary)}}.bui-TabActive{content:"";left:calc(var(--active-tab-left) + var(--bui-space-2));width:calc(var(--active-tab-width) - var(--bui-space-4));background-color:var(--bui-fg-primary);height:1px;transition:left var(--active-transition-duration)ease-out,opacity .15s ease-out,width var(--active-transition-duration)ease-out;opacity:1;border-radius:4px;position:absolute;bottom:-1px}.bui-TabHovered{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(--bui-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}.bui-TabPanel{padding-inline:var(--bui-space-2);padding-top:var(--bui-space-4)}.bui-TagList{gap:var(--bui-space-2);flex-wrap:wrap;display:flex}.bui-Tag{color:var(--bui-fg-primary);background-color:var(--bui-gray-2);border-radius:var(--bui-radius-2);font-weight:var(--bui-font-weight-regular);justify-content:center;align-items:center;gap:var(--bui-space-1);box-sizing:border-box;transition-property:background-color,box-shadow,color;transition-duration:.2s;transition-timing-function:ease-in-out;display:flex}.bui-Tag[data-size=small]{height:26px;padding:0 var(--bui-space-2);font-size:var(--bui-font-size-1)}.bui-Tag[data-size=medium]{height:32px;padding:0 var(--bui-space-2);font-size:var(--bui-font-size-2)}.bui-Tag[data-hovered]{background-color:var(--bui-gray-3);cursor:pointer}.bui-Tag[data-focus-visible]{outline:2px solid var(--bui-ring);outline-offset:1px}.bui-Tag[data-selected]{box-shadow:inset 0 0 0 1px var(--bui-gray-8)}.bui-Tag[data-disabled]{color:var(--bui-fg-disabled);cursor:not-allowed}.bui-TagRemoveButton{cursor:pointer;color:var(--bui-fg-primary);background-color:#0000;border:none;width:1rem;height:1rem;margin:0;padding:0}.bui-TagIcon{justify-content:center;align-items:center;transition:color .2s ease-in-out;display:flex;& svg{width:1rem;height:1rem}}.bui-Text{font-family:var(--bui-font-regular);margin:0;padding:0}.bui-Text[data-variant=title-large]{font-size:var(--bui-font-size-8);line-height:140%}.bui-Text[data-variant=title-medium]{font-size:var(--bui-font-size-7);line-height:140%}.bui-Text[data-variant=title-small]{font-size:var(--bui-font-size-6);line-height:140%}.bui-Text[data-variant=title-x-small]{font-size:var(--bui-font-size-5);line-height:140%}.bui-Text[data-variant=body-large]{font-size:var(--bui-font-size-4);line-height:140%}.bui-Text[data-variant=body-medium]{font-size:var(--bui-font-size-3);line-height:140%}.bui-Text[data-variant=body-small]{font-size:var(--bui-font-size-2);line-height:140%}.bui-Text[data-variant=body-x-small]{font-size:var(--bui-font-size-1);line-height:140%}.bui-Text[data-weight=regular]{font-weight:var(--bui-font-weight-regular)}.bui-Text[data-weight=bold]{font-weight:var(--bui-font-weight-bold)}.bui-Text[data-color=primary]{color:var(--bui-fg-primary)}.bui-Text[data-color=secondary]{color:var(--bui-fg-secondary)}.bui-Text[data-color=danger]{color:var(--bui-fg-danger)}.bui-Text[data-color=warning]{color:var(--bui-fg-warning)}.bui-Text[data-color=success]{color:var(--bui-fg-success)}.bui-Text[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bui-Text[data-as=span],.bui-Text[data-as=label],.bui-Text[data-as=strong],.bui-Text[data-as=em],.bui-Text[data-as=small]{display:inline-block}.bui-TextField{font-family:var(--bui-font-regular);flex-direction:column;flex-shrink:0;width:100%;display:flex}.bui-PasswordField{font-family:var(--bui-font-regular);--bui-passwordmanager-icon-width:var(--bui-space-1);flex-direction:column;flex-shrink:0;width:100%;display:flex}.bui-InputWrapper{position:relative;&[data-size=small] .bui-Input{height:2rem}&[data-size=medium] .bui-Input{height:2.5rem}&[data-size=small] .bui-Input[data-icon]{padding-left:var(--bui-space-8)}&[data-size=medium] .bui-Input[data-icon]{padding-left:var(--bui-space-9)}}.bui-InputAction{right:var(--bui-space-1);color:var(--bui-fg-primary);flex-direction:row;flex-shrink:0;transition:right .2s ease-in-out;display:flex;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}}.bui-InputVisibility{cursor:pointer;color:var(--bui-fg-primary);background-color:#0000;border:none;justify-content:center;align-items:center;margin:0;padding:0;display:flex;&[data-size=small]{width:2rem;height:2rem}&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium]{width:2.5rem;height:2.5rem}&[data-size=medium] svg{width:1.25rem;height:1.25rem}}.bui-PasswordField .bui-InputWrapper[data-size=small] .bui-Input{padding-right:calc(2rem + var(--bui-passwordmanager-icon-width))}.bui-PasswordField .bui-InputWrapper[data-size=medium] .bui-Input{padding-right:calc(2.5rem + var(--bui-passwordmanager-icon-width))}.bui-InputIcon{left:var(--bui-space-3);margin-right:var(--bui-space-1);color:var(--bui-fg-primary);pointer-events:none;flex-shrink:0;transition:left .2s ease-in-out;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}}.bui-Input{padding:0 var(--bui-space-3);border-radius:var(--bui-radius-2);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-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(--bui-fg-secondary)}&[data-focused]{outline-color:var(--bui-border-pressed);outline-width:0}&[data-hovered]{border-color:var(--bui-border-hover)}&[data-focused]{border-color:var(--bui-border-pressed);outline-width:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-disabled]{opacity:.5;cursor:not-allowed;border:1px solid var(--bui-border-disabled)}}.bui-SearchField{flex:1 0;&[data-empty]{& .bui-InputClear{display:none}}&[data-start-collapsed=true]{flex:0 auto;padding:0;transition:flex-basis .3s ease-in-out;&[data-collapsed=true]{flex-basis:200px}&[data-collapsed=false]{cursor:pointer;&[data-size=medium]{flex-basis:2.5rem;height:2.5rem}&[data-size=small]{flex-basis:2rem;height:2rem}&[data-size=medium] .bui-Input{&::placeholder{opacity:0}}&[data-size=small] .bui-Input{&::placeholder{opacity:0}}& .bui-InputWrapper{& .bui-Input[data-icon]{padding-right:0}}}}}.bui-SearchField .bui-Input{transition:padding .3s ease-in-out,border-color .2s ease-in-out,outline-color .2s ease-in-out;&[data-hovered]{border-color:var(--bui-border-hover)}&[data-focused]{border-color:var(--bui-border-pressed);outline-width:0}}.bui-SearchField .bui-InputWrapper{& .bui-Input[data-icon]{padding-right:var(--bui-space-6)}}.bui-SearchField .bui-InputIcon{justify-content:center;display:flex;left:0;&[data-size=small]{width:var(--bui-space-8)}&[data-size=medium]{width:var(--bui-space-10)}}.bui-InputClear{cursor:pointer;color:var(--bui-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}.bui-InputClear:hover{color:var(--bui-fg-primary)}.bui-InputClear[data-size=small]{width:2rem;height:2rem}.bui-InputClear[data-size=medium]{width:2.5rem;height:2.5rem}.bui-InputClear svg{width:1rem;height:1rem}.bui-Skeleton{animation:var(--bui-animate-pulse);background-color:var(--bui-bg-surface-2);border-radius:var(--bui-radius-2)}.bui-Skeleton[data-rounded=true]{border-radius:var(--bui-radius-full)}.bui-Tooltip{background:var(--bui-bg-surface-1);border:1px solid var(--bui-gray-3);forced-color-adjust:none;padding:var(--bui-space-2)var(--bui-space-3);max-width:240px;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);color:var(--bui-fg-primary);border-radius:4px;outline:none;transition:transform .2s,opacity .2s;transform:translate(0,0);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}--tooltip-offset:var(--bui-space-3)&[data-placement=top]{margin-bottom:var(--tooltip-offset);--origin:translateY(4px)}&[data-placement=right]{margin-left:var(--tooltip-offset);--origin:translateX(-4px)}&[data-placement=bottom]{margin-top:var(--tooltip-offset);--origin:translateY(-4px)}&[data-placement=left]{margin-right:var(--tooltip-offset);--origin:translateX(4px)}}.bui-TooltipArrow{& svg{display:block;& path:first-child{fill:var(--bui-bg-surface-1)}& path:nth-child(2){fill:var(--bui-gray-3)}--tooltip-arrow-overlap:-2px}&[data-placement=top] svg{margin-top:var(--tooltip-arrow-overlap)}&[data-placement=bottom] svg{margin-bottom:var(--tooltip-arrow-overlap);transform:rotate(180deg)}&[data-placement=right] svg{margin-right:var(--tooltip-arrow-overlap);transform:rotate(90deg)}&[data-placement=left] svg{margin-left:var(--tooltip-arrow-overlap);transform:rotate(-90deg)}}[data-theme=dark]{& .bui-Tooltip{background:var(--bui-bg-surface-2);box-shadow:none;border:1px solid var(--bui-gray-4)}& .bui-TooltipArrow{& svg path:first-child{fill:var(--bui-bg-surface-2)}& svg path:nth-child(2){fill:var(--bui-gray-4)}}}.bui-ScrollAreaRoot{box-sizing:border-box;width:100%}.bui-ScrollAreaViewport{overscroll-behavior:contain;height:100%}.bui-ScrollAreaContent{padding-block:.75rem;flex-direction:column;gap:1rem;padding-left:1rem;padding-right:1.5rem;display:flex}.bui-ScrollAreaScrollbar{background-color:var(--bui-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}}.bui-ScrollAreaThumb{border-radius:inherit;background-color:var(--bui-scrollbar-thumb);width:100%}.bui-Select[data-invalid]{& .bui-SelectTrigger{border-color:var(--bui-fg-danger)}}.bui-SelectTrigger{box-sizing:border-box;border-radius:var(--bui-radius-3);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);cursor:pointer;justify-content:space-between;align-items:center;gap:var(--bui-space-2);width:100%;display:flex;& svg{color:var(--bui-fg-secondary);flex-shrink:0}&[data-size=small]{height:2rem;padding-inline:var(--bui-space-3)}&[data-size=medium]{height:3rem;padding-inline:var(--bui-space-4)}&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium] svg{width:1.25rem;height:1.25rem}&::placeholder{color:var(--bui-fg-secondary)}&:hover{border-color:var(--bui-border-hover);transition:border-color .2s ease-in-out,outline-color .2s ease-in-out}&:focus-visible{border-color:var(--bui-border-pressed);outline:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-invalid]:hover,&[data-invalid]:focus-visible{border-width:2px}&[disabled]{cursor:not-allowed;border-color:var(--bui-border-disabled);color:var(--bui-fg-disabled)}&[disabled] .bui-SelectValue{color:var(--bui-fg-disabled)}&[data-popup-open] .bui-SelectIcon{transform:rotate(180deg)}}.bui-SelectValue{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);text-align:left;overflow:hidden;& .bui-SelectItemIndicator{display:none}&[disabled]{color:var(--bui-fg-disabled)}}.bui-SelectItem{width:var(--anchor-width);padding-block:var(--bui-space-2);padding-left:var(--bui-space-3);padding-right:var(--bui-space-4);color:var(--bui-fg-primary);border-radius:var(--bui-radius-3);cursor:pointer;user-select:none;font-size:var(--bui-font-size-3);align-items:center;gap:var(--bui-space-1);outline:none;grid-template-columns:1rem 1fr;grid-template-areas:"icon text";display:grid;position:relative;&[data-focused]{z-index:0;color:var(--bui-fg-primary);position:relative}&[data-focused]:before{content:"";z-index:-1;background-color:var(--bui-bg-tint-hover);border-radius:.25rem;position:absolute;inset-block:0;inset-inline:.25rem}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled)}&[data-selected] .bui-SelectItemIndicator{opacity:1}}.bui-SelectItemIndicator{opacity:0;grid-area:icon;justify-content:center;align-items:center;transition:opacity .2s ease-in-out;display:flex}.bui-SelectItemLabel{flex:1;grid-area:text}.bui-Switch{align-items:center;gap:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary);cursor:pointer;display:flex;position:relative;&[data-pressed] .bui-SwitchIndicator{&:before{background:var(--bui-fg-solid)}}&[data-selected]{& .bui-SwitchIndicator{background:var(--bui-bg-solid);&:before{background:var(--bui-fg-solid);transform:translate(100%)}}&[data-pressed]{& .indicator{background:var(--bui-gray-3)}}}&[data-focus-visible] .bui-SwitchIndicator{outline-offset:2px;outline:2px solid}}.bui-SwitchIndicator{background:var(--bui-gray-3);border:2px;border-radius:1.143rem;width:2rem;height:1.143rem;transition:all .2s;&:before{content:"";background:var(--bui-fg-solid);border-radius:16px;width:.857rem;height:.857rem;margin:.143rem;transition:all .2s;display:block}} \ No newline at end of file +@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}}.bui-p{padding:var(--p)}.bui-p-0\.5{padding:var(--bui-space-0_5)}.bui-p-1{padding:var(--bui-space-1)}.bui-p-1\.5{padding:var(--bui-space-1_5)}.bui-p-2{padding:var(--bui-space-2)}.bui-p-3{padding:var(--bui-space-3)}.bui-p-4{padding:var(--bui-space-4)}.bui-p-5{padding:var(--bui-space-5)}.bui-p-6{padding:var(--bui-space-6)}.bui-p-7{padding:var(--bui-space-7)}.bui-p-8{padding:var(--bui-space-8)}.bui-p-9{padding:var(--bui-space-9)}.bui-p-10{padding:var(--bui-space-10)}.bui-p-11{padding:var(--bui-space-11)}.bui-p-12{padding:var(--bui-space-12)}.bui-p-13{padding:var(--bui-space-13)}.bui-p-14{padding:var(--bui-space-14)}@media (width>=640px){.xs\:bui-p{padding:var(--p-xs)}.xs\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xs\:bui-p-1{padding:var(--bui-space-1)}.xs\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xs\:bui-p-2{padding:var(--bui-space-2)}.xs\:bui-p-3{padding:var(--bui-space-3)}.xs\:bui-p-4{padding:var(--bui-space-4)}.xs\:bui-p-5{padding:var(--bui-space-5)}.xs\:bui-p-6{padding:var(--bui-space-6)}.xs\:bui-p-7{padding:var(--bui-space-7)}.xs\:bui-p-8{padding:var(--bui-space-8)}.xs\:bui-p-9{padding:var(--bui-space-9)}.xs\:bui-p-10{padding:var(--bui-space-10)}.xs\:bui-p-11{padding:var(--bui-space-11)}.xs\:bui-p-12{padding:var(--bui-space-12)}.xs\:bui-p-13{padding:var(--bui-space-13)}.xs\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-p{padding:var(--p-sm)}.sm\:bui-p-0\.5{padding:var(--bui-space-0_5)}.sm\:bui-p-1{padding:var(--bui-space-1)}.sm\:bui-p-1\.5{padding:var(--bui-space-1_5)}.sm\:bui-p-2{padding:var(--bui-space-2)}.sm\:bui-p-3{padding:var(--bui-space-3)}.sm\:bui-p-4{padding:var(--bui-space-4)}.sm\:bui-p-5{padding:var(--bui-space-5)}.sm\:bui-p-6{padding:var(--bui-space-6)}.sm\:bui-p-7{padding:var(--bui-space-7)}.sm\:bui-p-8{padding:var(--bui-space-8)}.sm\:bui-p-9{padding:var(--bui-space-9)}.sm\:bui-p-10{padding:var(--bui-space-10)}.sm\:bui-p-11{padding:var(--bui-space-11)}.sm\:bui-p-12{padding:var(--bui-space-12)}.sm\:bui-p-13{padding:var(--bui-space-13)}.sm\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-p{padding:var(--p-md)}.md\:bui-p-0\.5{padding:var(--bui-space-0_5)}.md\:bui-p-1{padding:var(--bui-space-1)}.md\:bui-p-1\.5{padding:var(--bui-space-1_5)}.md\:bui-p-2{padding:var(--bui-space-2)}.md\:bui-p-3{padding:var(--bui-space-3)}.md\:bui-p-4{padding:var(--bui-space-4)}.md\:bui-p-5{padding:var(--bui-space-5)}.md\:bui-p-6{padding:var(--bui-space-6)}.md\:bui-p-7{padding:var(--bui-space-7)}.md\:bui-p-8{padding:var(--bui-space-8)}.md\:bui-p-9{padding:var(--bui-space-9)}.md\:bui-p-10{padding:var(--bui-space-10)}.md\:bui-p-11{padding:var(--bui-space-11)}.md\:bui-p-12{padding:var(--bui-space-12)}.md\:bui-p-13{padding:var(--bui-space-13)}.md\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-p{padding:var(--p-lg)}.lg\:bui-p-0\.5{padding:var(--bui-space-0_5)}.lg\:bui-p-1{padding:var(--bui-space-1)}.lg\:bui-p-1\.5{padding:var(--bui-space-1_5)}.lg\:bui-p-2{padding:var(--bui-space-2)}.lg\:bui-p-3{padding:var(--bui-space-3)}.lg\:bui-p-4{padding:var(--bui-space-4)}.lg\:bui-p-5{padding:var(--bui-space-5)}.lg\:bui-p-6{padding:var(--bui-space-6)}.lg\:bui-p-7{padding:var(--bui-space-7)}.lg\:bui-p-8{padding:var(--bui-space-8)}.lg\:bui-p-9{padding:var(--bui-space-9)}.lg\:bui-p-10{padding:var(--bui-space-10)}.lg\:bui-p-11{padding:var(--bui-space-11)}.lg\:bui-p-12{padding:var(--bui-space-12)}.lg\:bui-p-13{padding:var(--bui-space-13)}.lg\:bui-p-14{padding:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-p{padding:var(--p-xl)}.xl\:bui-p-0\.5{padding:var(--bui-space-0_5)}.xl\:bui-p-1{padding:var(--bui-space-1)}.xl\:bui-p-1\.5{padding:var(--bui-space-1_5)}.xl\:bui-p-2{padding:var(--bui-space-2)}.xl\:bui-p-3{padding:var(--bui-space-3)}.xl\:bui-p-4{padding:var(--bui-space-4)}.xl\:bui-p-5{padding:var(--bui-space-5)}.xl\:bui-p-6{padding:var(--bui-space-6)}.xl\:bui-p-7{padding:var(--bui-space-7)}.xl\:bui-p-8{padding:var(--bui-space-8)}.xl\:bui-p-9{padding:var(--bui-space-9)}.xl\:bui-p-10{padding:var(--bui-space-10)}.xl\:bui-p-11{padding:var(--bui-space-11)}.xl\:bui-p-12{padding:var(--bui-space-12)}.xl\:bui-p-13{padding:var(--bui-space-13)}.xl\:bui-p-14{padding:var(--bui-space-14)}}.bui-pl{padding-left:var(--pl)}.bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.bui-pl-1{padding-left:var(--bui-space-1)}.bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.bui-pl-2{padding-left:var(--bui-space-2)}.bui-pl-3{padding-left:var(--bui-space-3)}.bui-pl-4{padding-left:var(--bui-space-4)}.bui-pl-5{padding-left:var(--bui-space-5)}.bui-pl-6{padding-left:var(--bui-space-6)}.bui-pl-7{padding-left:var(--bui-space-7)}.bui-pl-8{padding-left:var(--bui-space-8)}.bui-pl-9{padding-left:var(--bui-space-9)}.bui-pl-10{padding-left:var(--bui-space-10)}.bui-pl-11{padding-left:var(--bui-space-11)}.bui-pl-12{padding-left:var(--bui-space-12)}.bui-pl-13{padding-left:var(--bui-space-13)}.bui-pl-14{padding-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pl{padding-left:var(--pl-xs)}.xs\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xs\:bui-pl-1{padding-left:var(--bui-space-1)}.xs\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xs\:bui-pl-2{padding-left:var(--bui-space-2)}.xs\:bui-pl-3{padding-left:var(--bui-space-3)}.xs\:bui-pl-4{padding-left:var(--bui-space-4)}.xs\:bui-pl-5{padding-left:var(--bui-space-5)}.xs\:bui-pl-6{padding-left:var(--bui-space-6)}.xs\:bui-pl-7{padding-left:var(--bui-space-7)}.xs\:bui-pl-8{padding-left:var(--bui-space-8)}.xs\:bui-pl-9{padding-left:var(--bui-space-9)}.xs\:bui-pl-10{padding-left:var(--bui-space-10)}.xs\:bui-pl-11{padding-left:var(--bui-space-11)}.xs\:bui-pl-12{padding-left:var(--bui-space-12)}.xs\:bui-pl-13{padding-left:var(--bui-space-13)}.xs\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pl{padding-left:var(--pl-sm)}.sm\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.sm\:bui-pl-1{padding-left:var(--bui-space-1)}.sm\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.sm\:bui-pl-2{padding-left:var(--bui-space-2)}.sm\:bui-pl-3{padding-left:var(--bui-space-3)}.sm\:bui-pl-4{padding-left:var(--bui-space-4)}.sm\:bui-pl-5{padding-left:var(--bui-space-5)}.sm\:bui-pl-6{padding-left:var(--bui-space-6)}.sm\:bui-pl-7{padding-left:var(--bui-space-7)}.sm\:bui-pl-8{padding-left:var(--bui-space-8)}.sm\:bui-pl-9{padding-left:var(--bui-space-9)}.sm\:bui-pl-10{padding-left:var(--bui-space-10)}.sm\:bui-pl-11{padding-left:var(--bui-space-11)}.sm\:bui-pl-12{padding-left:var(--bui-space-12)}.sm\:bui-pl-13{padding-left:var(--bui-space-13)}.sm\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pl{padding-left:var(--pl-md)}.md\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.md\:bui-pl-1{padding-left:var(--bui-space-1)}.md\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.md\:bui-pl-2{padding-left:var(--bui-space-2)}.md\:bui-pl-3{padding-left:var(--bui-space-3)}.md\:bui-pl-4{padding-left:var(--bui-space-4)}.md\:bui-pl-5{padding-left:var(--bui-space-5)}.md\:bui-pl-6{padding-left:var(--bui-space-6)}.md\:bui-pl-7{padding-left:var(--bui-space-7)}.md\:bui-pl-8{padding-left:var(--bui-space-8)}.md\:bui-pl-9{padding-left:var(--bui-space-9)}.md\:bui-pl-10{padding-left:var(--bui-space-10)}.md\:bui-pl-11{padding-left:var(--bui-space-11)}.md\:bui-pl-12{padding-left:var(--bui-space-12)}.md\:bui-pl-13{padding-left:var(--bui-space-13)}.md\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pl{padding-left:var(--pl-lg)}.lg\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.lg\:bui-pl-1{padding-left:var(--bui-space-1)}.lg\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.lg\:bui-pl-2{padding-left:var(--bui-space-2)}.lg\:bui-pl-3{padding-left:var(--bui-space-3)}.lg\:bui-pl-4{padding-left:var(--bui-space-4)}.lg\:bui-pl-5{padding-left:var(--bui-space-5)}.lg\:bui-pl-6{padding-left:var(--bui-space-6)}.lg\:bui-pl-7{padding-left:var(--bui-space-7)}.lg\:bui-pl-8{padding-left:var(--bui-space-8)}.lg\:bui-pl-9{padding-left:var(--bui-space-9)}.lg\:bui-pl-10{padding-left:var(--bui-space-10)}.lg\:bui-pl-11{padding-left:var(--bui-space-11)}.lg\:bui-pl-12{padding-left:var(--bui-space-12)}.lg\:bui-pl-13{padding-left:var(--bui-space-13)}.lg\:bui-pl-14{padding-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pl{padding-left:var(--pl-xl)}.xl\:bui-pl-0\.5{padding-left:var(--bui-space-0_5)}.xl\:bui-pl-1{padding-left:var(--bui-space-1)}.xl\:bui-pl-1\.5{padding-left:var(--bui-space-1_5)}.xl\:bui-pl-2{padding-left:var(--bui-space-2)}.xl\:bui-pl-3{padding-left:var(--bui-space-3)}.xl\:bui-pl-4{padding-left:var(--bui-space-4)}.xl\:bui-pl-5{padding-left:var(--bui-space-5)}.xl\:bui-pl-6{padding-left:var(--bui-space-6)}.xl\:bui-pl-7{padding-left:var(--bui-space-7)}.xl\:bui-pl-8{padding-left:var(--bui-space-8)}.xl\:bui-pl-9{padding-left:var(--bui-space-9)}.xl\:bui-pl-10{padding-left:var(--bui-space-10)}.xl\:bui-pl-11{padding-left:var(--bui-space-11)}.xl\:bui-pl-12{padding-left:var(--bui-space-12)}.xl\:bui-pl-13{padding-left:var(--bui-space-13)}.xl\:bui-pl-14{padding-left:var(--bui-space-14)}}.bui-pr{padding-right:var(--pr)}.bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.bui-pr-1{padding-right:var(--bui-space-1)}.bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.bui-pr-2{padding-right:var(--bui-space-2)}.bui-pr-3{padding-right:var(--bui-space-3)}.bui-pr-4{padding-right:var(--bui-space-4)}.bui-pr-5{padding-right:var(--bui-space-5)}.bui-pr-6{padding-right:var(--bui-space-6)}.bui-pr-7{padding-right:var(--bui-space-7)}.bui-pr-8{padding-right:var(--bui-space-8)}.bui-pr-9{padding-right:var(--bui-space-9)}.bui-pr-10{padding-right:var(--bui-space-10)}.bui-pr-11{padding-right:var(--bui-space-11)}.bui-pr-12{padding-right:var(--bui-space-12)}.bui-pr-13{padding-right:var(--bui-space-13)}.bui-pr-14{padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pr{padding-right:var(--pr-xs)}.xs\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xs\:bui-pr-1{padding-right:var(--bui-space-1)}.xs\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xs\:bui-pr-2{padding-right:var(--bui-space-2)}.xs\:bui-pr-3{padding-right:var(--bui-space-3)}.xs\:bui-pr-4{padding-right:var(--bui-space-4)}.xs\:bui-pr-5{padding-right:var(--bui-space-5)}.xs\:bui-pr-6{padding-right:var(--bui-space-6)}.xs\:bui-pr-7{padding-right:var(--bui-space-7)}.xs\:bui-pr-8{padding-right:var(--bui-space-8)}.xs\:bui-pr-9{padding-right:var(--bui-space-9)}.xs\:bui-pr-10{padding-right:var(--bui-space-10)}.xs\:bui-pr-11{padding-right:var(--bui-space-11)}.xs\:bui-pr-12{padding-right:var(--bui-space-12)}.xs\:bui-pr-13{padding-right:var(--bui-space-13)}.xs\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pr{padding-right:var(--pr-sm)}.sm\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.sm\:bui-pr-1{padding-right:var(--bui-space-1)}.sm\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.sm\:bui-pr-2{padding-right:var(--bui-space-2)}.sm\:bui-pr-3{padding-right:var(--bui-space-3)}.sm\:bui-pr-4{padding-right:var(--bui-space-4)}.sm\:bui-pr-5{padding-right:var(--bui-space-5)}.sm\:bui-pr-6{padding-right:var(--bui-space-6)}.sm\:bui-pr-7{padding-right:var(--bui-space-7)}.sm\:bui-pr-8{padding-right:var(--bui-space-8)}.sm\:bui-pr-9{padding-right:var(--bui-space-9)}.sm\:bui-pr-10{padding-right:var(--bui-space-10)}.sm\:bui-pr-11{padding-right:var(--bui-space-11)}.sm\:bui-pr-12{padding-right:var(--bui-space-12)}.sm\:bui-pr-13{padding-right:var(--bui-space-13)}.sm\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pr{padding-right:var(--pr-md)}.md\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.md\:bui-pr-1{padding-right:var(--bui-space-1)}.md\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.md\:bui-pr-2{padding-right:var(--bui-space-2)}.md\:bui-pr-3{padding-right:var(--bui-space-3)}.md\:bui-pr-4{padding-right:var(--bui-space-4)}.md\:bui-pr-5{padding-right:var(--bui-space-5)}.md\:bui-pr-6{padding-right:var(--bui-space-6)}.md\:bui-pr-7{padding-right:var(--bui-space-7)}.md\:bui-pr-8{padding-right:var(--bui-space-8)}.md\:bui-pr-9{padding-right:var(--bui-space-9)}.md\:bui-pr-10{padding-right:var(--bui-space-10)}.md\:bui-pr-11{padding-right:var(--bui-space-11)}.md\:bui-pr-12{padding-right:var(--bui-space-12)}.md\:bui-pr-13{padding-right:var(--bui-space-13)}.md\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pr{padding-right:var(--pr-lg)}.lg\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.lg\:bui-pr-1{padding-right:var(--bui-space-1)}.lg\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.lg\:bui-pr-2{padding-right:var(--bui-space-2)}.lg\:bui-pr-3{padding-right:var(--bui-space-3)}.lg\:bui-pr-4{padding-right:var(--bui-space-4)}.lg\:bui-pr-5{padding-right:var(--bui-space-5)}.lg\:bui-pr-6{padding-right:var(--bui-space-6)}.lg\:bui-pr-7{padding-right:var(--bui-space-7)}.lg\:bui-pr-8{padding-right:var(--bui-space-8)}.lg\:bui-pr-9{padding-right:var(--bui-space-9)}.lg\:bui-pr-10{padding-right:var(--bui-space-10)}.lg\:bui-pr-11{padding-right:var(--bui-space-11)}.lg\:bui-pr-12{padding-right:var(--bui-space-12)}.lg\:bui-pr-13{padding-right:var(--bui-space-13)}.lg\:bui-pr-14{padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pr{padding-right:var(--pr-xl)}.xl\:bui-pr-0\.5{padding-right:var(--bui-space-0_5)}.xl\:bui-pr-1{padding-right:var(--bui-space-1)}.xl\:bui-pr-1\.5{padding-right:var(--bui-space-1_5)}.xl\:bui-pr-2{padding-right:var(--bui-space-2)}.xl\:bui-pr-3{padding-right:var(--bui-space-3)}.xl\:bui-pr-4{padding-right:var(--bui-space-4)}.xl\:bui-pr-5{padding-right:var(--bui-space-5)}.xl\:bui-pr-6{padding-right:var(--bui-space-6)}.xl\:bui-pr-7{padding-right:var(--bui-space-7)}.xl\:bui-pr-8{padding-right:var(--bui-space-8)}.xl\:bui-pr-9{padding-right:var(--bui-space-9)}.xl\:bui-pr-10{padding-right:var(--bui-space-10)}.xl\:bui-pr-11{padding-right:var(--bui-space-11)}.xl\:bui-pr-12{padding-right:var(--bui-space-12)}.xl\:bui-pr-13{padding-right:var(--bui-space-13)}.xl\:bui-pr-14{padding-right:var(--bui-space-14)}}.bui-pt{padding-top:var(--pt)}.bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.bui-pt-1{padding-top:var(--bui-space-1)}.bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.bui-pt-2{padding-top:var(--bui-space-2)}.bui-pt-3{padding-top:var(--bui-space-3)}.bui-pt-4{padding-top:var(--bui-space-4)}.bui-pt-5{padding-top:var(--bui-space-5)}.bui-pt-6{padding-top:var(--bui-space-6)}.bui-pt-7{padding-top:var(--bui-space-7)}.bui-pt-8{padding-top:var(--bui-space-8)}.bui-pt-9{padding-top:var(--bui-space-9)}.bui-pt-10{padding-top:var(--bui-space-10)}.bui-pt-11{padding-top:var(--bui-space-11)}.bui-pt-12{padding-top:var(--bui-space-12)}.bui-pt-13{padding-top:var(--bui-space-13)}.bui-pt-14{padding-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pt{padding-top:var(--pt-xs)}.xs\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xs\:bui-pt-1{padding-top:var(--bui-space-1)}.xs\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xs\:bui-pt-2{padding-top:var(--bui-space-2)}.xs\:bui-pt-3{padding-top:var(--bui-space-3)}.xs\:bui-pt-4{padding-top:var(--bui-space-4)}.xs\:bui-pt-5{padding-top:var(--bui-space-5)}.xs\:bui-pt-6{padding-top:var(--bui-space-6)}.xs\:bui-pt-7{padding-top:var(--bui-space-7)}.xs\:bui-pt-8{padding-top:var(--bui-space-8)}.xs\:bui-pt-9{padding-top:var(--bui-space-9)}.xs\:bui-pt-10{padding-top:var(--bui-space-10)}.xs\:bui-pt-11{padding-top:var(--bui-space-11)}.xs\:bui-pt-12{padding-top:var(--bui-space-12)}.xs\:bui-pt-13{padding-top:var(--bui-space-13)}.xs\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pt{padding-top:var(--pt-sm)}.sm\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.sm\:bui-pt-1{padding-top:var(--bui-space-1)}.sm\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.sm\:bui-pt-2{padding-top:var(--bui-space-2)}.sm\:bui-pt-3{padding-top:var(--bui-space-3)}.sm\:bui-pt-4{padding-top:var(--bui-space-4)}.sm\:bui-pt-5{padding-top:var(--bui-space-5)}.sm\:bui-pt-6{padding-top:var(--bui-space-6)}.sm\:bui-pt-7{padding-top:var(--bui-space-7)}.sm\:bui-pt-8{padding-top:var(--bui-space-8)}.sm\:bui-pt-9{padding-top:var(--bui-space-9)}.sm\:bui-pt-10{padding-top:var(--bui-space-10)}.sm\:bui-pt-11{padding-top:var(--bui-space-11)}.sm\:bui-pt-12{padding-top:var(--bui-space-12)}.sm\:bui-pt-13{padding-top:var(--bui-space-13)}.sm\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pt{padding-top:var(--pt-md)}.md\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.md\:bui-pt-1{padding-top:var(--bui-space-1)}.md\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.md\:bui-pt-2{padding-top:var(--bui-space-2)}.md\:bui-pt-3{padding-top:var(--bui-space-3)}.md\:bui-pt-4{padding-top:var(--bui-space-4)}.md\:bui-pt-5{padding-top:var(--bui-space-5)}.md\:bui-pt-6{padding-top:var(--bui-space-6)}.md\:bui-pt-7{padding-top:var(--bui-space-7)}.md\:bui-pt-8{padding-top:var(--bui-space-8)}.md\:bui-pt-9{padding-top:var(--bui-space-9)}.md\:bui-pt-10{padding-top:var(--bui-space-10)}.md\:bui-pt-11{padding-top:var(--bui-space-11)}.md\:bui-pt-12{padding-top:var(--bui-space-12)}.md\:bui-pt-13{padding-top:var(--bui-space-13)}.md\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pt{padding-top:var(--pt-lg)}.lg\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.lg\:bui-pt-1{padding-top:var(--bui-space-1)}.lg\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.lg\:bui-pt-2{padding-top:var(--bui-space-2)}.lg\:bui-pt-3{padding-top:var(--bui-space-3)}.lg\:bui-pt-4{padding-top:var(--bui-space-4)}.lg\:bui-pt-5{padding-top:var(--bui-space-5)}.lg\:bui-pt-6{padding-top:var(--bui-space-6)}.lg\:bui-pt-7{padding-top:var(--bui-space-7)}.lg\:bui-pt-8{padding-top:var(--bui-space-8)}.lg\:bui-pt-9{padding-top:var(--bui-space-9)}.lg\:bui-pt-10{padding-top:var(--bui-space-10)}.lg\:bui-pt-11{padding-top:var(--bui-space-11)}.lg\:bui-pt-12{padding-top:var(--bui-space-12)}.lg\:bui-pt-13{padding-top:var(--bui-space-13)}.lg\:bui-pt-14{padding-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pt{padding-top:var(--pt-xl)}.xl\:bui-pt-0\.5{padding-top:var(--bui-space-0_5)}.xl\:bui-pt-1{padding-top:var(--bui-space-1)}.xl\:bui-pt-1\.5{padding-top:var(--bui-space-1_5)}.xl\:bui-pt-2{padding-top:var(--bui-space-2)}.xl\:bui-pt-3{padding-top:var(--bui-space-3)}.xl\:bui-pt-4{padding-top:var(--bui-space-4)}.xl\:bui-pt-5{padding-top:var(--bui-space-5)}.xl\:bui-pt-6{padding-top:var(--bui-space-6)}.xl\:bui-pt-7{padding-top:var(--bui-space-7)}.xl\:bui-pt-8{padding-top:var(--bui-space-8)}.xl\:bui-pt-9{padding-top:var(--bui-space-9)}.xl\:bui-pt-10{padding-top:var(--bui-space-10)}.xl\:bui-pt-11{padding-top:var(--bui-space-11)}.xl\:bui-pt-12{padding-top:var(--bui-space-12)}.xl\:bui-pt-13{padding-top:var(--bui-space-13)}.xl\:bui-pt-14{padding-top:var(--bui-space-14)}}.bui-pb{padding-bottom:var(--pb)}.bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.bui-pb-1{padding-bottom:var(--bui-space-1)}.bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.bui-pb-2{padding-bottom:var(--bui-space-2)}.bui-pb-3{padding-bottom:var(--bui-space-3)}.bui-pb-4{padding-bottom:var(--bui-space-4)}.bui-pb-5{padding-bottom:var(--bui-space-5)}.bui-pb-6{padding-bottom:var(--bui-space-6)}.bui-pb-7{padding-bottom:var(--bui-space-7)}.bui-pb-8{padding-bottom:var(--bui-space-8)}.bui-pb-9{padding-bottom:var(--bui-space-9)}.bui-pb-10{padding-bottom:var(--bui-space-10)}.bui-pb-11{padding-bottom:var(--bui-space-11)}.bui-pb-12{padding-bottom:var(--bui-space-12)}.bui-pb-13{padding-bottom:var(--bui-space-13)}.bui-pb-14{padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-pb{padding-bottom:var(--pb-xs)}.xs\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xs\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xs\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xs\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xs\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xs\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xs\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xs\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xs\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xs\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xs\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xs\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xs\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xs\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xs\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xs\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-pb{padding-bottom:var(--pb-sm)}.sm\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.sm\:bui-pb-1{padding-bottom:var(--bui-space-1)}.sm\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.sm\:bui-pb-2{padding-bottom:var(--bui-space-2)}.sm\:bui-pb-3{padding-bottom:var(--bui-space-3)}.sm\:bui-pb-4{padding-bottom:var(--bui-space-4)}.sm\:bui-pb-5{padding-bottom:var(--bui-space-5)}.sm\:bui-pb-6{padding-bottom:var(--bui-space-6)}.sm\:bui-pb-7{padding-bottom:var(--bui-space-7)}.sm\:bui-pb-8{padding-bottom:var(--bui-space-8)}.sm\:bui-pb-9{padding-bottom:var(--bui-space-9)}.sm\:bui-pb-10{padding-bottom:var(--bui-space-10)}.sm\:bui-pb-11{padding-bottom:var(--bui-space-11)}.sm\:bui-pb-12{padding-bottom:var(--bui-space-12)}.sm\:bui-pb-13{padding-bottom:var(--bui-space-13)}.sm\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-pb{padding-bottom:var(--pb-md)}.md\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.md\:bui-pb-1{padding-bottom:var(--bui-space-1)}.md\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.md\:bui-pb-2{padding-bottom:var(--bui-space-2)}.md\:bui-pb-3{padding-bottom:var(--bui-space-3)}.md\:bui-pb-4{padding-bottom:var(--bui-space-4)}.md\:bui-pb-5{padding-bottom:var(--bui-space-5)}.md\:bui-pb-6{padding-bottom:var(--bui-space-6)}.md\:bui-pb-7{padding-bottom:var(--bui-space-7)}.md\:bui-pb-8{padding-bottom:var(--bui-space-8)}.md\:bui-pb-9{padding-bottom:var(--bui-space-9)}.md\:bui-pb-10{padding-bottom:var(--bui-space-10)}.md\:bui-pb-11{padding-bottom:var(--bui-space-11)}.md\:bui-pb-12{padding-bottom:var(--bui-space-12)}.md\:bui-pb-13{padding-bottom:var(--bui-space-13)}.md\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-pb{padding-bottom:var(--pb-lg)}.lg\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.lg\:bui-pb-1{padding-bottom:var(--bui-space-1)}.lg\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.lg\:bui-pb-2{padding-bottom:var(--bui-space-2)}.lg\:bui-pb-3{padding-bottom:var(--bui-space-3)}.lg\:bui-pb-4{padding-bottom:var(--bui-space-4)}.lg\:bui-pb-5{padding-bottom:var(--bui-space-5)}.lg\:bui-pb-6{padding-bottom:var(--bui-space-6)}.lg\:bui-pb-7{padding-bottom:var(--bui-space-7)}.lg\:bui-pb-8{padding-bottom:var(--bui-space-8)}.lg\:bui-pb-9{padding-bottom:var(--bui-space-9)}.lg\:bui-pb-10{padding-bottom:var(--bui-space-10)}.lg\:bui-pb-11{padding-bottom:var(--bui-space-11)}.lg\:bui-pb-12{padding-bottom:var(--bui-space-12)}.lg\:bui-pb-13{padding-bottom:var(--bui-space-13)}.lg\:bui-pb-14{padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-pb{padding-bottom:var(--pb-xl)}.xl\:bui-pb-0\.5{padding-bottom:var(--bui-space-0_5)}.xl\:bui-pb-1{padding-bottom:var(--bui-space-1)}.xl\:bui-pb-1\.5{padding-bottom:var(--bui-space-1_5)}.xl\:bui-pb-2{padding-bottom:var(--bui-space-2)}.xl\:bui-pb-3{padding-bottom:var(--bui-space-3)}.xl\:bui-pb-4{padding-bottom:var(--bui-space-4)}.xl\:bui-pb-5{padding-bottom:var(--bui-space-5)}.xl\:bui-pb-6{padding-bottom:var(--bui-space-6)}.xl\:bui-pb-7{padding-bottom:var(--bui-space-7)}.xl\:bui-pb-8{padding-bottom:var(--bui-space-8)}.xl\:bui-pb-9{padding-bottom:var(--bui-space-9)}.xl\:bui-pb-10{padding-bottom:var(--bui-space-10)}.xl\:bui-pb-11{padding-bottom:var(--bui-space-11)}.xl\:bui-pb-12{padding-bottom:var(--bui-space-12)}.xl\:bui-pb-13{padding-bottom:var(--bui-space-13)}.xl\:bui-pb-14{padding-bottom:var(--bui-space-14)}}.bui-py{padding-top:var(--py);padding-bottom:var(--py)}.bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-py{padding-top:var(--py-xs);padding-bottom:var(--py-xs)}.xs\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xs\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xs\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xs\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xs\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xs\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xs\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xs\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xs\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xs\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xs\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xs\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xs\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xs\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xs\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xs\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-py{padding-top:var(--py-sm);padding-bottom:var(--py-sm)}.sm\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.sm\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.sm\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.sm\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.sm\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.sm\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.sm\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.sm\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.sm\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.sm\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.sm\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.sm\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.sm\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.sm\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.sm\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.sm\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-py{padding-top:var(--py-md);padding-bottom:var(--py-md)}.md\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.md\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.md\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.md\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.md\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.md\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.md\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.md\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.md\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.md\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.md\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.md\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.md\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.md\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.md\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.md\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-py{padding-top:var(--py-lg);padding-bottom:var(--py-lg)}.lg\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.lg\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.lg\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.lg\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.lg\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.lg\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.lg\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.lg\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.lg\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.lg\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.lg\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.lg\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.lg\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.lg\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.lg\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.lg\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-py{padding-top:var(--py-xl);padding-bottom:var(--py-xl)}.xl\:bui-py-0\.5{padding-top:var(--bui-space-0_5);padding-bottom:var(--bui-space-0_5)}.xl\:bui-py-1{padding-top:var(--bui-space-1);padding-bottom:var(--bui-space-1)}.xl\:bui-py-1\.5{padding-top:var(--bui-space-1_5);padding-bottom:var(--bui-space-1_5)}.xl\:bui-py-2{padding-top:var(--bui-space-2);padding-bottom:var(--bui-space-2)}.xl\:bui-py-3{padding-top:var(--bui-space-3);padding-bottom:var(--bui-space-3)}.xl\:bui-py-4{padding-top:var(--bui-space-4);padding-bottom:var(--bui-space-4)}.xl\:bui-py-5{padding-top:var(--bui-space-5);padding-bottom:var(--bui-space-5)}.xl\:bui-py-6{padding-top:var(--bui-space-6);padding-bottom:var(--bui-space-6)}.xl\:bui-py-7{padding-top:var(--bui-space-7);padding-bottom:var(--bui-space-7)}.xl\:bui-py-8{padding-top:var(--bui-space-8);padding-bottom:var(--bui-space-8)}.xl\:bui-py-9{padding-top:var(--bui-space-9);padding-bottom:var(--bui-space-9)}.xl\:bui-py-10{padding-top:var(--bui-space-10);padding-bottom:var(--bui-space-10)}.xl\:bui-py-11{padding-top:var(--bui-space-11);padding-bottom:var(--bui-space-11)}.xl\:bui-py-12{padding-top:var(--bui-space-12);padding-bottom:var(--bui-space-12)}.xl\:bui-py-13{padding-top:var(--bui-space-13);padding-bottom:var(--bui-space-13)}.xl\:bui-py-14{padding-top:var(--bui-space-14);padding-bottom:var(--bui-space-14)}}.bui-px{padding-left:var(--px);padding-right:var(--px)}.bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-px{padding-left:var(--px-xs);padding-right:var(--px-xs)}.xs\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xs\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xs\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xs\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xs\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xs\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xs\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xs\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xs\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xs\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xs\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xs\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xs\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xs\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xs\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xs\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-px{padding-left:var(--px-sm);padding-right:var(--px-sm)}.sm\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.sm\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.sm\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.sm\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.sm\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.sm\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.sm\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.sm\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.sm\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.sm\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.sm\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.sm\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.sm\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.sm\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.sm\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.sm\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-px{padding-left:var(--px-md);padding-right:var(--px-md)}.md\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.md\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.md\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.md\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.md\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.md\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.md\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.md\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.md\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.md\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.md\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.md\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.md\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.md\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.md\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.md\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-px{padding-left:var(--px-lg);padding-right:var(--px-lg)}.lg\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.lg\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.lg\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.lg\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.lg\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.lg\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.lg\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.lg\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.lg\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.lg\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.lg\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.lg\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.lg\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.lg\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.lg\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.lg\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-px{padding-left:var(--px-xl);padding-right:var(--px-xl)}.xl\:bui-px-0\.5{padding-left:var(--bui-space-0_5);padding-right:var(--bui-space-0_5)}.xl\:bui-px-1{padding-left:var(--bui-space-1);padding-right:var(--bui-space-1)}.xl\:bui-px-1\.5{padding-left:var(--bui-space-1_5);padding-right:var(--bui-space-1_5)}.xl\:bui-px-2{padding-left:var(--bui-space-2);padding-right:var(--bui-space-2)}.xl\:bui-px-3{padding-left:var(--bui-space-3);padding-right:var(--bui-space-3)}.xl\:bui-px-4{padding-left:var(--bui-space-4);padding-right:var(--bui-space-4)}.xl\:bui-px-5{padding-left:var(--bui-space-5);padding-right:var(--bui-space-5)}.xl\:bui-px-6{padding-left:var(--bui-space-6);padding-right:var(--bui-space-6)}.xl\:bui-px-7{padding-left:var(--bui-space-7);padding-right:var(--bui-space-7)}.xl\:bui-px-8{padding-left:var(--bui-space-8);padding-right:var(--bui-space-8)}.xl\:bui-px-9{padding-left:var(--bui-space-9);padding-right:var(--bui-space-9)}.xl\:bui-px-10{padding-left:var(--bui-space-10);padding-right:var(--bui-space-10)}.xl\:bui-px-11{padding-left:var(--bui-space-11);padding-right:var(--bui-space-11)}.xl\:bui-px-12{padding-left:var(--bui-space-12);padding-right:var(--bui-space-12)}.xl\:bui-px-13{padding-left:var(--bui-space-13);padding-right:var(--bui-space-13)}.xl\:bui-px-14{padding-left:var(--bui-space-14);padding-right:var(--bui-space-14)}}.bui-m{margin:var(--m)}.bui-m-0\.5{margin:var(--bui-space-0_5)}.bui-m-1{margin:var(--bui-space-1)}.bui-m-1\.5{margin:var(--bui-space-1_5)}.bui-m-2{margin:var(--bui-space-2)}.bui-m-3{margin:var(--bui-space-3)}.bui-m-4{margin:var(--bui-space-4)}.bui-m-5{margin:var(--bui-space-5)}.bui-m-6{margin:var(--bui-space-6)}.bui-m-7{margin:var(--bui-space-7)}.bui-m-8{margin:var(--bui-space-8)}.bui-m-9{margin:var(--bui-space-9)}.bui-m-10{margin:var(--bui-space-10)}.bui-m-11{margin:var(--bui-space-11)}.bui-m-12{margin:var(--bui-space-12)}.bui-m-13{margin:var(--bui-space-13)}.bui-m-14{margin:var(--bui-space-14)}@media (width>=640px){.xs\:bui-m{margin:var(--p-xs)}.xs\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xs\:bui-m-1{margin:var(--bui-space-1)}.xs\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xs\:bui-m-2{margin:var(--bui-space-2)}.xs\:bui-m-3{margin:var(--bui-space-3)}.xs\:bui-m-4{margin:var(--bui-space-4)}.xs\:bui-m-5{margin:var(--bui-space-5)}.xs\:bui-m-6{margin:var(--bui-space-6)}.xs\:bui-m-7{margin:var(--bui-space-7)}.xs\:bui-m-8{margin:var(--bui-space-8)}.xs\:bui-m-9{margin:var(--bui-space-9)}.xs\:bui-m-10{margin:var(--bui-space-10)}.xs\:bui-m-11{margin:var(--bui-space-11)}.xs\:bui-m-12{margin:var(--bui-space-12)}.xs\:bui-m-13{margin:var(--bui-space-13)}.xs\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-m{margin:var(--p-sm)}.sm\:bui-m-0\.5{margin:var(--bui-space-0_5)}.sm\:bui-m-1{margin:var(--bui-space-1)}.sm\:bui-m-1\.5{margin:var(--bui-space-1_5)}.sm\:bui-m-2{margin:var(--bui-space-2)}.sm\:bui-m-3{margin:var(--bui-space-3)}.sm\:bui-m-4{margin:var(--bui-space-4)}.sm\:bui-m-5{margin:var(--bui-space-5)}.sm\:bui-m-6{margin:var(--bui-space-6)}.sm\:bui-m-7{margin:var(--bui-space-7)}.sm\:bui-m-8{margin:var(--bui-space-8)}.sm\:bui-m-9{margin:var(--bui-space-9)}.sm\:bui-m-10{margin:var(--bui-space-10)}.sm\:bui-m-11{margin:var(--bui-space-11)}.sm\:bui-m-12{margin:var(--bui-space-12)}.sm\:bui-m-13{margin:var(--bui-space-13)}.sm\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-m{margin:var(--p-md)}.md\:bui-m-0\.5{margin:var(--bui-space-0_5)}.md\:bui-m-1{margin:var(--bui-space-1)}.md\:bui-m-1\.5{margin:var(--bui-space-1_5)}.md\:bui-m-2{margin:var(--bui-space-2)}.md\:bui-m-3{margin:var(--bui-space-3)}.md\:bui-m-4{margin:var(--bui-space-4)}.md\:bui-m-5{margin:var(--bui-space-5)}.md\:bui-m-6{margin:var(--bui-space-6)}.md\:bui-m-7{margin:var(--bui-space-7)}.md\:bui-m-8{margin:var(--bui-space-8)}.md\:bui-m-9{margin:var(--bui-space-9)}.md\:bui-m-10{margin:var(--bui-space-10)}.md\:bui-m-11{margin:var(--bui-space-11)}.md\:bui-m-12{margin:var(--bui-space-12)}.md\:bui-m-13{margin:var(--bui-space-13)}.md\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-m{margin:var(--p-lg)}.lg\:bui-m-0\.5{margin:var(--bui-space-0_5)}.lg\:bui-m-1{margin:var(--bui-space-1)}.lg\:bui-m-1\.5{margin:var(--bui-space-1_5)}.lg\:bui-m-2{margin:var(--bui-space-2)}.lg\:bui-m-3{margin:var(--bui-space-3)}.lg\:bui-m-4{margin:var(--bui-space-4)}.lg\:bui-m-5{margin:var(--bui-space-5)}.lg\:bui-m-6{margin:var(--bui-space-6)}.lg\:bui-m-7{margin:var(--bui-space-7)}.lg\:bui-m-8{margin:var(--bui-space-8)}.lg\:bui-m-9{margin:var(--bui-space-9)}.lg\:bui-m-10{margin:var(--bui-space-10)}.lg\:bui-m-11{margin:var(--bui-space-11)}.lg\:bui-m-12{margin:var(--bui-space-12)}.lg\:bui-m-13{margin:var(--bui-space-13)}.lg\:bui-m-14{margin:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-m{margin:var(--p-xl)}.xl\:bui-m-0\.5{margin:var(--bui-space-0_5)}.xl\:bui-m-1{margin:var(--bui-space-1)}.xl\:bui-m-1\.5{margin:var(--bui-space-1_5)}.xl\:bui-m-2{margin:var(--bui-space-2)}.xl\:bui-m-3{margin:var(--bui-space-3)}.xl\:bui-m-4{margin:var(--bui-space-4)}.xl\:bui-m-5{margin:var(--bui-space-5)}.xl\:bui-m-6{margin:var(--bui-space-6)}.xl\:bui-m-7{margin:var(--bui-space-7)}.xl\:bui-m-8{margin:var(--bui-space-8)}.xl\:bui-m-9{margin:var(--bui-space-9)}.xl\:bui-m-10{margin:var(--bui-space-10)}.xl\:bui-m-11{margin:var(--bui-space-11)}.xl\:bui-m-12{margin:var(--bui-space-12)}.xl\:bui-m-13{margin:var(--bui-space-13)}.xl\:bui-m-14{margin:var(--bui-space-14)}}.bui-ml{margin-left:var(--ml)}.bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.bui-ml-1{margin-left:var(--bui-space-1)}.bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.bui-ml-2{margin-left:var(--bui-space-2)}.bui-ml-3{margin-left:var(--bui-space-3)}.bui-ml-4{margin-left:var(--bui-space-4)}.bui-ml-5{margin-left:var(--bui-space-5)}.bui-ml-6{margin-left:var(--bui-space-6)}.bui-ml-7{margin-left:var(--bui-space-7)}.bui-ml-8{margin-left:var(--bui-space-8)}.bui-ml-9{margin-left:var(--bui-space-9)}.bui-ml-10{margin-left:var(--bui-space-10)}.bui-ml-11{margin-left:var(--bui-space-11)}.bui-ml-12{margin-left:var(--bui-space-12)}.bui-ml-13{margin-left:var(--bui-space-13)}.bui-ml-14{margin-left:var(--bui-space-14)}@media (width>=640px){.xs\:bui-ml{margin-left:var(--pl-xs)}.xs\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xs\:bui-ml-1{margin-left:var(--bui-space-1)}.xs\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xs\:bui-ml-2{margin-left:var(--bui-space-2)}.xs\:bui-ml-3{margin-left:var(--bui-space-3)}.xs\:bui-ml-4{margin-left:var(--bui-space-4)}.xs\:bui-ml-5{margin-left:var(--bui-space-5)}.xs\:bui-ml-6{margin-left:var(--bui-space-6)}.xs\:bui-ml-7{margin-left:var(--bui-space-7)}.xs\:bui-ml-8{margin-left:var(--bui-space-8)}.xs\:bui-ml-9{margin-left:var(--bui-space-9)}.xs\:bui-ml-10{margin-left:var(--bui-space-10)}.xs\:bui-ml-11{margin-left:var(--bui-space-11)}.xs\:bui-ml-12{margin-left:var(--bui-space-12)}.xs\:bui-ml-13{margin-left:var(--bui-space-13)}.xs\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-ml{margin-left:var(--pl-sm)}.sm\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.sm\:bui-ml-1{margin-left:var(--bui-space-1)}.sm\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.sm\:bui-ml-2{margin-left:var(--bui-space-2)}.sm\:bui-ml-3{margin-left:var(--bui-space-3)}.sm\:bui-ml-4{margin-left:var(--bui-space-4)}.sm\:bui-ml-5{margin-left:var(--bui-space-5)}.sm\:bui-ml-6{margin-left:var(--bui-space-6)}.sm\:bui-ml-7{margin-left:var(--bui-space-7)}.sm\:bui-ml-8{margin-left:var(--bui-space-8)}.sm\:bui-ml-9{margin-left:var(--bui-space-9)}.sm\:bui-ml-10{margin-left:var(--bui-space-10)}.sm\:bui-ml-11{margin-left:var(--bui-space-11)}.sm\:bui-ml-12{margin-left:var(--bui-space-12)}.sm\:bui-ml-13{margin-left:var(--bui-space-13)}.sm\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-ml{margin-left:var(--pl-md)}.md\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.md\:bui-ml-1{margin-left:var(--bui-space-1)}.md\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.md\:bui-ml-2{margin-left:var(--bui-space-2)}.md\:bui-ml-3{margin-left:var(--bui-space-3)}.md\:bui-ml-4{margin-left:var(--bui-space-4)}.md\:bui-ml-5{margin-left:var(--bui-space-5)}.md\:bui-ml-6{margin-left:var(--bui-space-6)}.md\:bui-ml-7{margin-left:var(--bui-space-7)}.md\:bui-ml-8{margin-left:var(--bui-space-8)}.md\:bui-ml-9{margin-left:var(--bui-space-9)}.md\:bui-ml-10{margin-left:var(--bui-space-10)}.md\:bui-ml-11{margin-left:var(--bui-space-11)}.md\:bui-ml-12{margin-left:var(--bui-space-12)}.md\:bui-ml-13{margin-left:var(--bui-space-13)}.md\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-ml{margin-left:var(--pl-lg)}.lg\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.lg\:bui-ml-1{margin-left:var(--bui-space-1)}.lg\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.lg\:bui-ml-2{margin-left:var(--bui-space-2)}.lg\:bui-ml-3{margin-left:var(--bui-space-3)}.lg\:bui-ml-4{margin-left:var(--bui-space-4)}.lg\:bui-ml-5{margin-left:var(--bui-space-5)}.lg\:bui-ml-6{margin-left:var(--bui-space-6)}.lg\:bui-ml-7{margin-left:var(--bui-space-7)}.lg\:bui-ml-8{margin-left:var(--bui-space-8)}.lg\:bui-ml-9{margin-left:var(--bui-space-9)}.lg\:bui-ml-10{margin-left:var(--bui-space-10)}.lg\:bui-ml-11{margin-left:var(--bui-space-11)}.lg\:bui-ml-12{margin-left:var(--bui-space-12)}.lg\:bui-ml-13{margin-left:var(--bui-space-13)}.lg\:bui-ml-14{margin-left:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-ml{margin-left:var(--pl-xl)}.xl\:bui-ml-0\.5{margin-left:var(--bui-space-0_5)}.xl\:bui-ml-1{margin-left:var(--bui-space-1)}.xl\:bui-ml-1\.5{margin-left:var(--bui-space-1_5)}.xl\:bui-ml-2{margin-left:var(--bui-space-2)}.xl\:bui-ml-3{margin-left:var(--bui-space-3)}.xl\:bui-ml-4{margin-left:var(--bui-space-4)}.xl\:bui-ml-5{margin-left:var(--bui-space-5)}.xl\:bui-ml-6{margin-left:var(--bui-space-6)}.xl\:bui-ml-7{margin-left:var(--bui-space-7)}.xl\:bui-ml-8{margin-left:var(--bui-space-8)}.xl\:bui-ml-9{margin-left:var(--bui-space-9)}.xl\:bui-ml-10{margin-left:var(--bui-space-10)}.xl\:bui-ml-11{margin-left:var(--bui-space-11)}.xl\:bui-ml-12{margin-left:var(--bui-space-12)}.xl\:bui-ml-13{margin-left:var(--bui-space-13)}.xl\:bui-ml-14{margin-left:var(--bui-space-14)}}.bui-mr{margin-right:var(--mr)}.bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.bui-mr-1{margin-right:var(--bui-space-1)}.bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.bui-mr-2{margin-right:var(--bui-space-2)}.bui-mr-3{margin-right:var(--bui-space-3)}.bui-mr-4{margin-right:var(--bui-space-4)}.bui-mr-5{margin-right:var(--bui-space-5)}.bui-mr-6{margin-right:var(--bui-space-6)}.bui-mr-7{margin-right:var(--bui-space-7)}.bui-mr-8{margin-right:var(--bui-space-8)}.bui-mr-9{margin-right:var(--bui-space-9)}.bui-mr-10{margin-right:var(--bui-space-10)}.bui-mr-11{margin-right:var(--bui-space-11)}.bui-mr-12{margin-right:var(--bui-space-12)}.bui-mr-13{margin-right:var(--bui-space-13)}.bui-mr-14{margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mr{margin-right:var(--pr-xs)}.xs\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xs\:bui-mr-1{margin-right:var(--bui-space-1)}.xs\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xs\:bui-mr-2{margin-right:var(--bui-space-2)}.xs\:bui-mr-3{margin-right:var(--bui-space-3)}.xs\:bui-mr-4{margin-right:var(--bui-space-4)}.xs\:bui-mr-5{margin-right:var(--bui-space-5)}.xs\:bui-mr-6{margin-right:var(--bui-space-6)}.xs\:bui-mr-7{margin-right:var(--bui-space-7)}.xs\:bui-mr-8{margin-right:var(--bui-space-8)}.xs\:bui-mr-9{margin-right:var(--bui-space-9)}.xs\:bui-mr-10{margin-right:var(--bui-space-10)}.xs\:bui-mr-11{margin-right:var(--bui-space-11)}.xs\:bui-mr-12{margin-right:var(--bui-space-12)}.xs\:bui-mr-13{margin-right:var(--bui-space-13)}.xs\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mr{margin-right:var(--pr-sm)}.sm\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.sm\:bui-mr-1{margin-right:var(--bui-space-1)}.sm\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.sm\:bui-mr-2{margin-right:var(--bui-space-2)}.sm\:bui-mr-3{margin-right:var(--bui-space-3)}.sm\:bui-mr-4{margin-right:var(--bui-space-4)}.sm\:bui-mr-5{margin-right:var(--bui-space-5)}.sm\:bui-mr-6{margin-right:var(--bui-space-6)}.sm\:bui-mr-7{margin-right:var(--bui-space-7)}.sm\:bui-mr-8{margin-right:var(--bui-space-8)}.sm\:bui-mr-9{margin-right:var(--bui-space-9)}.sm\:bui-mr-10{margin-right:var(--bui-space-10)}.sm\:bui-mr-11{margin-right:var(--bui-space-11)}.sm\:bui-mr-12{margin-right:var(--bui-space-12)}.sm\:bui-mr-13{margin-right:var(--bui-space-13)}.sm\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mr{margin-right:var(--pr-md)}.md\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.md\:bui-mr-1{margin-right:var(--bui-space-1)}.md\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.md\:bui-mr-2{margin-right:var(--bui-space-2)}.md\:bui-mr-3{margin-right:var(--bui-space-3)}.md\:bui-mr-4{margin-right:var(--bui-space-4)}.md\:bui-mr-5{margin-right:var(--bui-space-5)}.md\:bui-mr-6{margin-right:var(--bui-space-6)}.md\:bui-mr-7{margin-right:var(--bui-space-7)}.md\:bui-mr-8{margin-right:var(--bui-space-8)}.md\:bui-mr-9{margin-right:var(--bui-space-9)}.md\:bui-mr-10{margin-right:var(--bui-space-10)}.md\:bui-mr-11{margin-right:var(--bui-space-11)}.md\:bui-mr-12{margin-right:var(--bui-space-12)}.md\:bui-mr-13{margin-right:var(--bui-space-13)}.md\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mr{margin-right:var(--pr-lg)}.lg\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.lg\:bui-mr-1{margin-right:var(--bui-space-1)}.lg\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.lg\:bui-mr-2{margin-right:var(--bui-space-2)}.lg\:bui-mr-3{margin-right:var(--bui-space-3)}.lg\:bui-mr-4{margin-right:var(--bui-space-4)}.lg\:bui-mr-5{margin-right:var(--bui-space-5)}.lg\:bui-mr-6{margin-right:var(--bui-space-6)}.lg\:bui-mr-7{margin-right:var(--bui-space-7)}.lg\:bui-mr-8{margin-right:var(--bui-space-8)}.lg\:bui-mr-9{margin-right:var(--bui-space-9)}.lg\:bui-mr-10{margin-right:var(--bui-space-10)}.lg\:bui-mr-11{margin-right:var(--bui-space-11)}.lg\:bui-mr-12{margin-right:var(--bui-space-12)}.lg\:bui-mr-13{margin-right:var(--bui-space-13)}.lg\:bui-mr-14{margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mr{margin-right:var(--pr-xl)}.xl\:bui-mr-0\.5{margin-right:var(--bui-space-0_5)}.xl\:bui-mr-1{margin-right:var(--bui-space-1)}.xl\:bui-mr-1\.5{margin-right:var(--bui-space-1_5)}.xl\:bui-mr-2{margin-right:var(--bui-space-2)}.xl\:bui-mr-3{margin-right:var(--bui-space-3)}.xl\:bui-mr-4{margin-right:var(--bui-space-4)}.xl\:bui-mr-5{margin-right:var(--bui-space-5)}.xl\:bui-mr-6{margin-right:var(--bui-space-6)}.xl\:bui-mr-7{margin-right:var(--bui-space-7)}.xl\:bui-mr-8{margin-right:var(--bui-space-8)}.xl\:bui-mr-9{margin-right:var(--bui-space-9)}.xl\:bui-mr-10{margin-right:var(--bui-space-10)}.xl\:bui-mr-11{margin-right:var(--bui-space-11)}.xl\:bui-mr-12{margin-right:var(--bui-space-12)}.xl\:bui-mr-13{margin-right:var(--bui-space-13)}.xl\:bui-mr-14{margin-right:var(--bui-space-14)}}.bui-mt{margin-top:var(--mt)}.bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.bui-mt-1{margin-top:var(--bui-space-1)}.bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.bui-mt-2{margin-top:var(--bui-space-2)}.bui-mt-3{margin-top:var(--bui-space-3)}.bui-mt-4{margin-top:var(--bui-space-4)}.bui-mt-5{margin-top:var(--bui-space-5)}.bui-mt-6{margin-top:var(--bui-space-6)}.bui-mt-7{margin-top:var(--bui-space-7)}.bui-mt-8{margin-top:var(--bui-space-8)}.bui-mt-9{margin-top:var(--bui-space-9)}.bui-mt-10{margin-top:var(--bui-space-10)}.bui-mt-11{margin-top:var(--bui-space-11)}.bui-mt-12{margin-top:var(--bui-space-12)}.bui-mt-13{margin-top:var(--bui-space-13)}.bui-mt-14{margin-top:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mt{margin-top:var(--pt-xs)}.xs\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xs\:bui-mt-1{margin-top:var(--bui-space-1)}.xs\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xs\:bui-mt-2{margin-top:var(--bui-space-2)}.xs\:bui-mt-3{margin-top:var(--bui-space-3)}.xs\:bui-mt-4{margin-top:var(--bui-space-4)}.xs\:bui-mt-5{margin-top:var(--bui-space-5)}.xs\:bui-mt-6{margin-top:var(--bui-space-6)}.xs\:bui-mt-7{margin-top:var(--bui-space-7)}.xs\:bui-mt-8{margin-top:var(--bui-space-8)}.xs\:bui-mt-9{margin-top:var(--bui-space-9)}.xs\:bui-mt-10{margin-top:var(--bui-space-10)}.xs\:bui-mt-11{margin-top:var(--bui-space-11)}.xs\:bui-mt-12{margin-top:var(--bui-space-12)}.xs\:bui-mt-13{margin-top:var(--bui-space-13)}.xs\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mt{margin-top:var(--pt-sm)}.sm\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.sm\:bui-mt-1{margin-top:var(--bui-space-1)}.sm\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.sm\:bui-mt-2{margin-top:var(--bui-space-2)}.sm\:bui-mt-3{margin-top:var(--bui-space-3)}.sm\:bui-mt-4{margin-top:var(--bui-space-4)}.sm\:bui-mt-5{margin-top:var(--bui-space-5)}.sm\:bui-mt-6{margin-top:var(--bui-space-6)}.sm\:bui-mt-7{margin-top:var(--bui-space-7)}.sm\:bui-mt-8{margin-top:var(--bui-space-8)}.sm\:bui-mt-9{margin-top:var(--bui-space-9)}.sm\:bui-mt-10{margin-top:var(--bui-space-10)}.sm\:bui-mt-11{margin-top:var(--bui-space-11)}.sm\:bui-mt-12{margin-top:var(--bui-space-12)}.sm\:bui-mt-13{margin-top:var(--bui-space-13)}.sm\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mt{margin-top:var(--pt-md)}.md\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.md\:bui-mt-1{margin-top:var(--bui-space-1)}.md\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.md\:bui-mt-2{margin-top:var(--bui-space-2)}.md\:bui-mt-3{margin-top:var(--bui-space-3)}.md\:bui-mt-4{margin-top:var(--bui-space-4)}.md\:bui-mt-5{margin-top:var(--bui-space-5)}.md\:bui-mt-6{margin-top:var(--bui-space-6)}.md\:bui-mt-7{margin-top:var(--bui-space-7)}.md\:bui-mt-8{margin-top:var(--bui-space-8)}.md\:bui-mt-9{margin-top:var(--bui-space-9)}.md\:bui-mt-10{margin-top:var(--bui-space-10)}.md\:bui-mt-11{margin-top:var(--bui-space-11)}.md\:bui-mt-12{margin-top:var(--bui-space-12)}.md\:bui-mt-13{margin-top:var(--bui-space-13)}.md\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mt{margin-top:var(--pt-lg)}.lg\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.lg\:bui-mt-1{margin-top:var(--bui-space-1)}.lg\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.lg\:bui-mt-2{margin-top:var(--bui-space-2)}.lg\:bui-mt-3{margin-top:var(--bui-space-3)}.lg\:bui-mt-4{margin-top:var(--bui-space-4)}.lg\:bui-mt-5{margin-top:var(--bui-space-5)}.lg\:bui-mt-6{margin-top:var(--bui-space-6)}.lg\:bui-mt-7{margin-top:var(--bui-space-7)}.lg\:bui-mt-8{margin-top:var(--bui-space-8)}.lg\:bui-mt-9{margin-top:var(--bui-space-9)}.lg\:bui-mt-10{margin-top:var(--bui-space-10)}.lg\:bui-mt-11{margin-top:var(--bui-space-11)}.lg\:bui-mt-12{margin-top:var(--bui-space-12)}.lg\:bui-mt-13{margin-top:var(--bui-space-13)}.lg\:bui-mt-14{margin-top:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mt{margin-top:var(--pt-xl)}.xl\:bui-mt-0\.5{margin-top:var(--bui-space-0_5)}.xl\:bui-mt-1{margin-top:var(--bui-space-1)}.xl\:bui-mt-1\.5{margin-top:var(--bui-space-1_5)}.xl\:bui-mt-2{margin-top:var(--bui-space-2)}.xl\:bui-mt-3{margin-top:var(--bui-space-3)}.xl\:bui-mt-4{margin-top:var(--bui-space-4)}.xl\:bui-mt-5{margin-top:var(--bui-space-5)}.xl\:bui-mt-6{margin-top:var(--bui-space-6)}.xl\:bui-mt-7{margin-top:var(--bui-space-7)}.xl\:bui-mt-8{margin-top:var(--bui-space-8)}.xl\:bui-mt-9{margin-top:var(--bui-space-9)}.xl\:bui-mt-10{margin-top:var(--bui-space-10)}.xl\:bui-mt-11{margin-top:var(--bui-space-11)}.xl\:bui-mt-12{margin-top:var(--bui-space-12)}.xl\:bui-mt-13{margin-top:var(--bui-space-13)}.xl\:bui-mt-14{margin-top:var(--bui-space-14)}}.bui-mb{margin-bottom:var(--mb)}.bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.bui-mb-1{margin-bottom:var(--bui-space-1)}.bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.bui-mb-2{margin-bottom:var(--bui-space-2)}.bui-mb-3{margin-bottom:var(--bui-space-3)}.bui-mb-4{margin-bottom:var(--bui-space-4)}.bui-mb-5{margin-bottom:var(--bui-space-5)}.bui-mb-6{margin-bottom:var(--bui-space-6)}.bui-mb-7{margin-bottom:var(--bui-space-7)}.bui-mb-8{margin-bottom:var(--bui-space-8)}.bui-mb-9{margin-bottom:var(--bui-space-9)}.bui-mb-10{margin-bottom:var(--bui-space-10)}.bui-mb-11{margin-bottom:var(--bui-space-11)}.bui-mb-12{margin-bottom:var(--bui-space-12)}.bui-mb-13{margin-bottom:var(--bui-space-13)}.bui-mb-14{margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mb{margin-bottom:var(--pb-xs)}.xs\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xs\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xs\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xs\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xs\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xs\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xs\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xs\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xs\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xs\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xs\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xs\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xs\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xs\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xs\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xs\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mb{margin-bottom:var(--pb-sm)}.sm\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.sm\:bui-mb-1{margin-bottom:var(--bui-space-1)}.sm\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.sm\:bui-mb-2{margin-bottom:var(--bui-space-2)}.sm\:bui-mb-3{margin-bottom:var(--bui-space-3)}.sm\:bui-mb-4{margin-bottom:var(--bui-space-4)}.sm\:bui-mb-5{margin-bottom:var(--bui-space-5)}.sm\:bui-mb-6{margin-bottom:var(--bui-space-6)}.sm\:bui-mb-7{margin-bottom:var(--bui-space-7)}.sm\:bui-mb-8{margin-bottom:var(--bui-space-8)}.sm\:bui-mb-9{margin-bottom:var(--bui-space-9)}.sm\:bui-mb-10{margin-bottom:var(--bui-space-10)}.sm\:bui-mb-11{margin-bottom:var(--bui-space-11)}.sm\:bui-mb-12{margin-bottom:var(--bui-space-12)}.sm\:bui-mb-13{margin-bottom:var(--bui-space-13)}.sm\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mb{margin-bottom:var(--pb-md)}.md\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.md\:bui-mb-1{margin-bottom:var(--bui-space-1)}.md\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.md\:bui-mb-2{margin-bottom:var(--bui-space-2)}.md\:bui-mb-3{margin-bottom:var(--bui-space-3)}.md\:bui-mb-4{margin-bottom:var(--bui-space-4)}.md\:bui-mb-5{margin-bottom:var(--bui-space-5)}.md\:bui-mb-6{margin-bottom:var(--bui-space-6)}.md\:bui-mb-7{margin-bottom:var(--bui-space-7)}.md\:bui-mb-8{margin-bottom:var(--bui-space-8)}.md\:bui-mb-9{margin-bottom:var(--bui-space-9)}.md\:bui-mb-10{margin-bottom:var(--bui-space-10)}.md\:bui-mb-11{margin-bottom:var(--bui-space-11)}.md\:bui-mb-12{margin-bottom:var(--bui-space-12)}.md\:bui-mb-13{margin-bottom:var(--bui-space-13)}.md\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mb{margin-bottom:var(--pb-lg)}.lg\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.lg\:bui-mb-1{margin-bottom:var(--bui-space-1)}.lg\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.lg\:bui-mb-2{margin-bottom:var(--bui-space-2)}.lg\:bui-mb-3{margin-bottom:var(--bui-space-3)}.lg\:bui-mb-4{margin-bottom:var(--bui-space-4)}.lg\:bui-mb-5{margin-bottom:var(--bui-space-5)}.lg\:bui-mb-6{margin-bottom:var(--bui-space-6)}.lg\:bui-mb-7{margin-bottom:var(--bui-space-7)}.lg\:bui-mb-8{margin-bottom:var(--bui-space-8)}.lg\:bui-mb-9{margin-bottom:var(--bui-space-9)}.lg\:bui-mb-10{margin-bottom:var(--bui-space-10)}.lg\:bui-mb-11{margin-bottom:var(--bui-space-11)}.lg\:bui-mb-12{margin-bottom:var(--bui-space-12)}.lg\:bui-mb-13{margin-bottom:var(--bui-space-13)}.lg\:bui-mb-14{margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mb{margin-bottom:var(--pb-xl)}.xl\:bui-mb-0\.5{margin-bottom:var(--bui-space-0_5)}.xl\:bui-mb-1{margin-bottom:var(--bui-space-1)}.xl\:bui-mb-1\.5{margin-bottom:var(--bui-space-1_5)}.xl\:bui-mb-2{margin-bottom:var(--bui-space-2)}.xl\:bui-mb-3{margin-bottom:var(--bui-space-3)}.xl\:bui-mb-4{margin-bottom:var(--bui-space-4)}.xl\:bui-mb-5{margin-bottom:var(--bui-space-5)}.xl\:bui-mb-6{margin-bottom:var(--bui-space-6)}.xl\:bui-mb-7{margin-bottom:var(--bui-space-7)}.xl\:bui-mb-8{margin-bottom:var(--bui-space-8)}.xl\:bui-mb-9{margin-bottom:var(--bui-space-9)}.xl\:bui-mb-10{margin-bottom:var(--bui-space-10)}.xl\:bui-mb-11{margin-bottom:var(--bui-space-11)}.xl\:bui-mb-12{margin-bottom:var(--bui-space-12)}.xl\:bui-mb-13{margin-bottom:var(--bui-space-13)}.xl\:bui-mb-14{margin-bottom:var(--bui-space-14)}}.bui-my{margin-top:var(--my);margin-bottom:var(--my)}.bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}@media (width>=640px){.xs\:bui-my{margin-top:var(--py-xs);margin-bottom:var(--py-xs)}.xs\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xs\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xs\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xs\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xs\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xs\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xs\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xs\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xs\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xs\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xs\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xs\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xs\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xs\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xs\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xs\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-my{margin-top:var(--py-sm);margin-bottom:var(--py-sm)}.sm\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.sm\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.sm\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.sm\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.sm\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.sm\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.sm\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.sm\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.sm\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.sm\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.sm\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.sm\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.sm\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.sm\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.sm\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.sm\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-my{margin-top:var(--py-md);margin-bottom:var(--py-md)}.md\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.md\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.md\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.md\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.md\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.md\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.md\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.md\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.md\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.md\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.md\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.md\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.md\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.md\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.md\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.md\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-my{margin-top:var(--py-lg);margin-bottom:var(--py-lg)}.lg\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.lg\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.lg\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.lg\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.lg\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.lg\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.lg\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.lg\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.lg\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.lg\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.lg\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.lg\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.lg\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.lg\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.lg\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.lg\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-my{margin-top:var(--py-xl);margin-bottom:var(--py-xl)}.xl\:bui-my-0\.5{margin-top:var(--bui-space-0_5);margin-bottom:var(--bui-space-0_5)}.xl\:bui-my-1{margin-top:var(--bui-space-1);margin-bottom:var(--bui-space-1)}.xl\:bui-my-1\.5{margin-top:var(--bui-space-1_5);margin-bottom:var(--bui-space-1_5)}.xl\:bui-my-2{margin-top:var(--bui-space-2);margin-bottom:var(--bui-space-2)}.xl\:bui-my-3{margin-top:var(--bui-space-3);margin-bottom:var(--bui-space-3)}.xl\:bui-my-4{margin-top:var(--bui-space-4);margin-bottom:var(--bui-space-4)}.xl\:bui-my-5{margin-top:var(--bui-space-5);margin-bottom:var(--bui-space-5)}.xl\:bui-my-6{margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6)}.xl\:bui-my-7{margin-top:var(--bui-space-7);margin-bottom:var(--bui-space-7)}.xl\:bui-my-8{margin-top:var(--bui-space-8);margin-bottom:var(--bui-space-8)}.xl\:bui-my-9{margin-top:var(--bui-space-9);margin-bottom:var(--bui-space-9)}.xl\:bui-my-10{margin-top:var(--bui-space-10);margin-bottom:var(--bui-space-10)}.xl\:bui-my-11{margin-top:var(--bui-space-11);margin-bottom:var(--bui-space-11)}.xl\:bui-my-12{margin-top:var(--bui-space-12);margin-bottom:var(--bui-space-12)}.xl\:bui-my-13{margin-top:var(--bui-space-13);margin-bottom:var(--bui-space-13)}.xl\:bui-my-14{margin-top:var(--bui-space-14);margin-bottom:var(--bui-space-14)}}.bui-mx{margin-left:var(--mx);margin-right:var(--mx)}.bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}@media (width>=640px){.xs\:bui-mx{margin-left:var(--px-xs);margin-right:var(--px-xs)}.xs\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xs\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xs\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xs\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xs\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xs\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xs\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xs\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xs\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xs\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xs\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xs\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xs\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xs\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xs\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xs\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-mx{margin-left:var(--px-sm);margin-right:var(--px-sm)}.sm\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.sm\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.sm\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.sm\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.sm\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.sm\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.sm\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.sm\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.sm\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.sm\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.sm\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.sm\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.sm\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.sm\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.sm\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.sm\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-mx{margin-left:var(--px-md);margin-right:var(--px-md)}.md\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.md\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.md\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.md\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.md\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.md\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.md\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.md\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.md\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.md\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.md\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.md\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.md\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.md\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.md\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.md\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-mx{margin-left:var(--px-lg);margin-right:var(--px-lg)}.lg\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.lg\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.lg\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.lg\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.lg\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.lg\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.lg\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.lg\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.lg\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.lg\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.lg\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.lg\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.lg\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.lg\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.lg\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.lg\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-mx{margin-left:var(--px-xl);margin-right:var(--px-xl)}.xl\:bui-mx-0\.5{margin-left:var(--bui-space-0_5);margin-right:var(--bui-space-0_5)}.xl\:bui-mx-1{margin-left:var(--bui-space-1);margin-right:var(--bui-space-1)}.xl\:bui-mx-1\.5{margin-left:var(--bui-space-1_5);margin-right:var(--bui-space-1_5)}.xl\:bui-mx-2{margin-left:var(--bui-space-2);margin-right:var(--bui-space-2)}.xl\:bui-mx-3{margin-left:var(--bui-space-3);margin-right:var(--bui-space-3)}.xl\:bui-mx-4{margin-left:var(--bui-space-4);margin-right:var(--bui-space-4)}.xl\:bui-mx-5{margin-left:var(--bui-space-5);margin-right:var(--bui-space-5)}.xl\:bui-mx-6{margin-left:var(--bui-space-6);margin-right:var(--bui-space-6)}.xl\:bui-mx-7{margin-left:var(--bui-space-7);margin-right:var(--bui-space-7)}.xl\:bui-mx-8{margin-left:var(--bui-space-8);margin-right:var(--bui-space-8)}.xl\:bui-mx-9{margin-left:var(--bui-space-9);margin-right:var(--bui-space-9)}.xl\:bui-mx-10{margin-left:var(--bui-space-10);margin-right:var(--bui-space-10)}.xl\:bui-mx-11{margin-left:var(--bui-space-11);margin-right:var(--bui-space-11)}.xl\:bui-mx-12{margin-left:var(--bui-space-12);margin-right:var(--bui-space-12)}.xl\:bui-mx-13{margin-left:var(--bui-space-13);margin-right:var(--bui-space-13)}.xl\:bui-mx-14{margin-left:var(--bui-space-14);margin-right:var(--bui-space-14)}}.bui-display-none{display:none}.bui-display-inline{display:inline}.bui-display-inline-block{display:inline-block}.bui-display-block{display:block}@media (width>=640px){.xs\:bui-display-none{display:none}.xs\:bui-display-inline{display:inline}.xs\:bui-display-inline-block{display:inline-block}.xs\:bui-display-block{display:block}}@media (width>=768px){.sm\:bui-display-none{display:none}.sm\:bui-display-inline{display:inline}.sm\:bui-display-inline-block{display:inline-block}.sm\:bui-display-block{display:block}}@media (width>=1024px){.md\:bui-display-none{display:none}.md\:bui-display-inline{display:inline}.md\:bui-display-inline-block{display:inline-block}.md\:bui-display-block{display:block}}@media (width>=1280px){.lg\:bui-display-none{display:none}.lg\:bui-display-inline{display:inline}.lg\:bui-display-inline-block{display:inline-block}.lg\:bui-display-block{display:block}}@media (width>=1536px){.xl\:bui-display-none{display:none}.xl\:bui-display-inline{display:inline}.xl\:bui-display-inline-block{display:inline-block}.xl\:bui-display-block{display:block}}.bui-w{width:var(--width)}.bui-min-w{min-width:var(--min-width)}.bui-max-w{max-width:var(--max-width)}@media (width>=640px){.xs\:bui-w{width:var(--width)}.xs\:bui-min-w{min-width:var(--min-width)}.xs\:bui-max-w{max-width:var(--max-width)}}@media (width>=768px){.sm\:bui-w{width:var(--width)}.sm\:bui-min-w{min-width:var(--min-width)}.sm\:bui-max-w{max-width:var(--max-width)}}@media (width>=1024px){.md\:bui-w{width:var(--width)}.md\:bui-min-w{min-width:var(--min-width)}.md\:bui-max-w{max-width:var(--max-width)}}@media (width>=1280px){.lg\:bui-w{width:var(--width)}.lg\:bui-min-w{min-width:var(--min-width)}.lg\:bui-max-w{max-width:var(--max-width)}}@media (width>=1536px){.xl\:bui-w{width:var(--width)}.xl\:bui-min-w{min-width:var(--min-width)}.xl\:bui-max-w{max-width:var(--max-width)}}.bui-h{height:var(--height)}.bui-min-h{min-height:var(--min-height)}.bui-max-h{max-height:var(--max-height)}@media (width>=640px){.xs\:bui-h{height:var(--height)}.xs\:bui-min-h{min-height:var(--min-height)}.xs\:bui-max-h{max-height:var(--max-height)}}@media (width>=768px){.sm\:bui-h{height:var(--height)}.sm\:bui-min-h{min-height:var(--min-height)}.sm\:bui-max-h{max-height:var(--max-height)}}@media (width>=1024px){.md\:bui-h{height:var(--height)}.md\:bui-min-h{min-height:var(--min-height)}.md\:bui-max-h{max-height:var(--max-height)}}@media (width>=1280px){.lg\:bui-h{height:var(--height)}.lg\:bui-min-h{min-height:var(--min-height)}.lg\:bui-max-h{max-height:var(--max-height)}}@media (width>=1536px){.xl\:bui-h{height:var(--height)}.xl\:bui-min-h{min-height:var(--min-height)}.xl\:bui-max-h{max-height:var(--max-height)}}.bui-position-absolute{position:absolute}.bui-position-fixed{position:fixed}.bui-position-sticky{position:sticky}.bui-position-relative{position:relative}.bui-position-static{position:static}@media (width>=640px){.xs\:bui-position-absolute{position:absolute}.xs\:bui-position-fixed{position:fixed}.xs\:bui-position-sticky{position:sticky}.xs\:bui-position-relative{position:relative}.xs\:bui-position-static{position:static}}@media (width>=768px){.sm\:bui-position-absolute{position:absolute}.sm\:bui-position-fixed{position:fixed}.sm\:bui-position-sticky{position:sticky}.sm\:bui-position-relative{position:relative}.sm\:bui-position-static{position:static}}@media (width>=1024px){.md\:bui-position-absolute{position:absolute}.md\:bui-position-fixed{position:fixed}.md\:bui-position-sticky{position:sticky}.md\:bui-position-relative{position:relative}.md\:bui-position-static{position:static}}@media (width>=1280px){.lg\:bui-position-absolute{position:absolute}.lg\:bui-position-fixed{position:fixed}.lg\:bui-position-sticky{position:sticky}.lg\:bui-position-relative{position:relative}.lg\:bui-position-static{position:static}}@media (width>=1536px){.xl\:bui-position-absolute{position:absolute}.xl\:bui-position-fixed{position:fixed}.xl\:bui-position-sticky{position:sticky}.xl\:bui-position-relative{position:relative}.xl\:bui-position-static{position:static}}.bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.bui-col-span-1{grid-column:span 1/span 1}.bui-col-span-2{grid-column:span 2/span 2}.bui-col-span-3{grid-column:span 3/span 3}.bui-col-span-4{grid-column:span 4/span 4}.bui-col-span-5{grid-column:span 5/span 5}.bui-col-span-6{grid-column:span 6/span 6}.bui-col-span-7{grid-column:span 7/span 7}.bui-col-span-8{grid-column:span 8/span 8}.bui-col-span-9{grid-column:span 9/span 9}.bui-col-span-10{grid-column:span 10/span 10}.bui-col-span-11{grid-column:span 11/span 11}.bui-col-span-12{grid-column:span 12/span 12}.bui-col-span-auto{grid-column:span auto/span auto}.bui-col-start-1{grid-column-start:1}.bui-col-start-2{grid-column-start:2}.bui-col-start-3{grid-column-start:3}.bui-col-start-4{grid-column-start:4}.bui-col-start-5{grid-column-start:5}.bui-col-start-6{grid-column-start:6}.bui-col-start-7{grid-column-start:7}.bui-col-start-8{grid-column-start:8}.bui-col-start-9{grid-column-start:9}.bui-col-start-10{grid-column-start:10}.bui-col-start-11{grid-column-start:11}.bui-col-start-12{grid-column-start:12}.bui-col-start-13{grid-column-start:13}.bui-col-start-auto{grid-column-start:auto}.bui-col-end-1{grid-column-end:1}.bui-col-end-2{grid-column-end:2}.bui-col-end-3{grid-column-end:3}.bui-col-end-4{grid-column-end:4}.bui-col-end-5{grid-column-end:5}.bui-col-end-6{grid-column-end:6}.bui-col-end-7{grid-column-end:7}.bui-col-end-8{grid-column-end:8}.bui-col-end-9{grid-column-end:9}.bui-col-end-10{grid-column-end:10}.bui-col-end-11{grid-column-end:11}.bui-col-end-12{grid-column-end:12}.bui-col-end-13{grid-column-end:13}.bui-col-end-auto{grid-column-end:auto}.bui-row-span-1{grid-row:span 1/span 1}.bui-row-span-2{grid-row:span 2/span 2}.bui-row-span-3{grid-row:span 3/span 3}.bui-row-span-4{grid-row:span 4/span 4}.bui-row-span-5{grid-row:span 5/span 5}.bui-row-span-6{grid-row:span 6/span 6}.bui-row-span-7{grid-row:span 7/span 7}.bui-row-span-8{grid-row:span 8/span 8}.bui-row-span-9{grid-row:span 9/span 9}.bui-row-span-10{grid-row:span 10/span 10}.bui-row-span-11{grid-row:span 11/span 11}.bui-row-span-12{grid-row:span 12/span 12}.bui-row-span-auto{grid-row:span auto/span auto}@media (width>=640px){.xs\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xs\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xs\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xs\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xs\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xs\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xs\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xs\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xs\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xs\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xs\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xs\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xs\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xs\:bui-col-span-1{grid-column:span 1/span 1}.xs\:bui-col-span-2{grid-column:span 2/span 2}.xs\:bui-col-span-3{grid-column:span 3/span 3}.xs\:bui-col-span-4{grid-column:span 4/span 4}.xs\:bui-col-span-5{grid-column:span 5/span 5}.xs\:bui-col-span-6{grid-column:span 6/span 6}.xs\:bui-col-span-7{grid-column:span 7/span 7}.xs\:bui-col-span-8{grid-column:span 8/span 8}.xs\:bui-col-span-9{grid-column:span 9/span 9}.xs\:bui-col-span-10{grid-column:span 10/span 10}.xs\:bui-col-span-11{grid-column:span 11/span 11}.xs\:bui-col-span-12{grid-column:span 12/span 12}.xs\:bui-col-span-auto{grid-column:span auto/span auto}.xs\:bui-col-start-1{grid-column-start:1}.xs\:bui-col-start-2{grid-column-start:2}.xs\:bui-col-start-3{grid-column-start:3}.xs\:bui-col-start-4{grid-column-start:4}.xs\:bui-col-start-5{grid-column-start:5}.xs\:bui-col-start-6{grid-column-start:6}.xs\:bui-col-start-7{grid-column-start:7}.xs\:bui-col-start-8{grid-column-start:8}.xs\:bui-col-start-9{grid-column-start:9}.xs\:bui-col-start-10{grid-column-start:10}.xs\:bui-col-start-11{grid-column-start:11}.xs\:bui-col-start-12{grid-column-start:12}.xs\:bui-col-start-13{grid-column-start:13}.xs\:bui-col-start-auto{grid-column-start:auto}.xs\:bui-col-end-1{grid-column-end:1}.xs\:bui-col-end-2{grid-column-end:2}.xs\:bui-col-end-3{grid-column-end:3}.xs\:bui-col-end-4{grid-column-end:4}.xs\:bui-col-end-5{grid-column-end:5}.xs\:bui-col-end-6{grid-column-end:6}.xs\:bui-col-end-7{grid-column-end:7}.xs\:bui-col-end-8{grid-column-end:8}.xs\:bui-col-end-9{grid-column-end:9}.xs\:bui-col-end-10{grid-column-end:10}.xs\:bui-col-end-11{grid-column-end:11}.xs\:bui-col-end-12{grid-column-end:12}.xs\:bui-col-end-13{grid-column-end:13}.xs\:bui-col-end-auto{grid-column-end:auto}.xs\:bui-row-span-1{grid-row:span 1/span 1}.xs\:bui-row-span-2{grid-row:span 2/span 2}.xs\:bui-row-span-3{grid-row:span 3/span 3}.xs\:bui-row-span-4{grid-row:span 4/span 4}.xs\:bui-row-span-5{grid-row:span 5/span 5}.xs\:bui-row-span-6{grid-row:span 6/span 6}.xs\:bui-row-span-7{grid-row:span 7/span 7}.xs\:bui-row-span-8{grid-row:span 8/span 8}.xs\:bui-row-span-9{grid-row:span 9/span 9}.xs\:bui-row-span-10{grid-row:span 10/span 10}.xs\:bui-row-span-11{grid-row:span 11/span 11}.xs\:bui-row-span-12{grid-row:span 12/span 12}.xs\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=768px){.sm\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.sm\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.sm\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.sm\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.sm\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.sm\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.sm\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.sm\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.sm\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.sm\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.sm\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.sm\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.sm\:bui-col-span-1{grid-column:span 1/span 1}.sm\:bui-col-span-2{grid-column:span 2/span 2}.sm\:bui-col-span-3{grid-column:span 3/span 3}.sm\:bui-col-span-4{grid-column:span 4/span 4}.sm\:bui-col-span-5{grid-column:span 5/span 5}.sm\:bui-col-span-6{grid-column:span 6/span 6}.sm\:bui-col-span-7{grid-column:span 7/span 7}.sm\:bui-col-span-8{grid-column:span 8/span 8}.sm\:bui-col-span-9{grid-column:span 9/span 9}.sm\:bui-col-span-10{grid-column:span 10/span 10}.sm\:bui-col-span-11{grid-column:span 11/span 11}.sm\:bui-col-span-12{grid-column:span 12/span 12}.sm\:bui-col-span-auto{grid-column:span auto/span auto}.sm\:bui-col-start-1{grid-column-start:1}.sm\:bui-col-start-2{grid-column-start:2}.sm\:bui-col-start-3{grid-column-start:3}.sm\:bui-col-start-4{grid-column-start:4}.sm\:bui-col-start-5{grid-column-start:5}.sm\:bui-col-start-6{grid-column-start:6}.sm\:bui-col-start-7{grid-column-start:7}.sm\:bui-col-start-8{grid-column-start:8}.sm\:bui-col-start-9{grid-column-start:9}.sm\:bui-col-start-10{grid-column-start:10}.sm\:bui-col-start-11{grid-column-start:11}.sm\:bui-col-start-12{grid-column-start:12}.sm\:bui-col-start-13{grid-column-start:13}.sm\:bui-col-start-auto{grid-column-start:auto}.sm\:bui-col-end-1{grid-column-end:1}.sm\:bui-col-end-2{grid-column-end:2}.sm\:bui-col-end-3{grid-column-end:3}.sm\:bui-col-end-4{grid-column-end:4}.sm\:bui-col-end-5{grid-column-end:5}.sm\:bui-col-end-6{grid-column-end:6}.sm\:bui-col-end-7{grid-column-end:7}.sm\:bui-col-end-8{grid-column-end:8}.sm\:bui-col-end-9{grid-column-end:9}.sm\:bui-col-end-10{grid-column-end:10}.sm\:bui-col-end-11{grid-column-end:11}.sm\:bui-col-end-12{grid-column-end:12}.sm\:bui-col-end-13{grid-column-end:13}.sm\:bui-col-end-auto{grid-column-end:auto}.sm\:bui-row-span-1{grid-row:span 1/span 1}.sm\:bui-row-span-2{grid-row:span 2/span 2}.sm\:bui-row-span-3{grid-row:span 3/span 3}.sm\:bui-row-span-4{grid-row:span 4/span 4}.sm\:bui-row-span-5{grid-row:span 5/span 5}.sm\:bui-row-span-6{grid-row:span 6/span 6}.sm\:bui-row-span-7{grid-row:span 7/span 7}.sm\:bui-row-span-8{grid-row:span 8/span 8}.sm\:bui-row-span-9{grid-row:span 9/span 9}.sm\:bui-row-span-10{grid-row:span 10/span 10}.sm\:bui-row-span-11{grid-row:span 11/span 11}.sm\:bui-row-span-12{grid-row:span 12/span 12}.sm\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1024px){.md\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.md\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.md\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.md\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.md\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.md\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.md\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.md\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.md\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.md\:bui-col-span-1{grid-column:span 1/span 1}.md\:bui-col-span-2{grid-column:span 2/span 2}.md\:bui-col-span-3{grid-column:span 3/span 3}.md\:bui-col-span-4{grid-column:span 4/span 4}.md\:bui-col-span-5{grid-column:span 5/span 5}.md\:bui-col-span-6{grid-column:span 6/span 6}.md\:bui-col-span-7{grid-column:span 7/span 7}.md\:bui-col-span-8{grid-column:span 8/span 8}.md\:bui-col-span-9{grid-column:span 9/span 9}.md\:bui-col-span-10{grid-column:span 10/span 10}.md\:bui-col-span-11{grid-column:span 11/span 11}.md\:bui-col-span-12{grid-column:span 12/span 12}.md\:bui-col-span-auto{grid-column:span auto/span auto}.md\:bui-col-start-1{grid-column-start:1}.md\:bui-col-start-2{grid-column-start:2}.md\:bui-col-start-3{grid-column-start:3}.md\:bui-col-start-4{grid-column-start:4}.md\:bui-col-start-5{grid-column-start:5}.md\:bui-col-start-6{grid-column-start:6}.md\:bui-col-start-7{grid-column-start:7}.md\:bui-col-start-8{grid-column-start:8}.md\:bui-col-start-9{grid-column-start:9}.md\:bui-col-start-10{grid-column-start:10}.md\:bui-col-start-11{grid-column-start:11}.md\:bui-col-start-12{grid-column-start:12}.md\:bui-col-start-13{grid-column-start:13}.md\:bui-col-start-auto{grid-column-start:auto}.md\:bui-col-end-1{grid-column-end:1}.md\:bui-col-end-2{grid-column-end:2}.md\:bui-col-end-3{grid-column-end:3}.md\:bui-col-end-4{grid-column-end:4}.md\:bui-col-end-5{grid-column-end:5}.md\:bui-col-end-6{grid-column-end:6}.md\:bui-col-end-7{grid-column-end:7}.md\:bui-col-end-8{grid-column-end:8}.md\:bui-col-end-9{grid-column-end:9}.md\:bui-col-end-10{grid-column-end:10}.md\:bui-col-end-11{grid-column-end:11}.md\:bui-col-end-12{grid-column-end:12}.md\:bui-col-end-13{grid-column-end:13}.md\:bui-col-end-auto{grid-column-end:auto}.md\:bui-row-span-1{grid-row:span 1/span 1}.md\:bui-row-span-2{grid-row:span 2/span 2}.md\:bui-row-span-3{grid-row:span 3/span 3}.md\:bui-row-span-4{grid-row:span 4/span 4}.md\:bui-row-span-5{grid-row:span 5/span 5}.md\:bui-row-span-6{grid-row:span 6/span 6}.md\:bui-row-span-7{grid-row:span 7/span 7}.md\:bui-row-span-8{grid-row:span 8/span 8}.md\:bui-row-span-9{grid-row:span 9/span 9}.md\:bui-row-span-10{grid-row:span 10/span 10}.md\:bui-row-span-11{grid-row:span 11/span 11}.md\:bui-row-span-12{grid-row:span 12/span 12}.md\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1280px){.lg\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.lg\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.lg\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.lg\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.lg\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.lg\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.lg\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.lg\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.lg\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.lg\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.lg\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.lg\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.lg\:bui-col-span-1{grid-column:span 1/span 1}.lg\:bui-col-span-2{grid-column:span 2/span 2}.lg\:bui-col-span-3{grid-column:span 3/span 3}.lg\:bui-col-span-4{grid-column:span 4/span 4}.lg\:bui-col-span-5{grid-column:span 5/span 5}.lg\:bui-col-span-6{grid-column:span 6/span 6}.lg\:bui-col-span-7{grid-column:span 7/span 7}.lg\:bui-col-span-8{grid-column:span 8/span 8}.lg\:bui-col-span-9{grid-column:span 9/span 9}.lg\:bui-col-span-10{grid-column:span 10/span 10}.lg\:bui-col-span-11{grid-column:span 11/span 11}.lg\:bui-col-span-12{grid-column:span 12/span 12}.lg\:bui-col-span-auto{grid-column:span auto/span auto}.lg\:bui-col-start-1{grid-column-start:1}.lg\:bui-col-start-2{grid-column-start:2}.lg\:bui-col-start-3{grid-column-start:3}.lg\:bui-col-start-4{grid-column-start:4}.lg\:bui-col-start-5{grid-column-start:5}.lg\:bui-col-start-6{grid-column-start:6}.lg\:bui-col-start-7{grid-column-start:7}.lg\:bui-col-start-8{grid-column-start:8}.lg\:bui-col-start-9{grid-column-start:9}.lg\:bui-col-start-10{grid-column-start:10}.lg\:bui-col-start-11{grid-column-start:11}.lg\:bui-col-start-12{grid-column-start:12}.lg\:bui-col-start-13{grid-column-start:13}.lg\:bui-col-start-auto{grid-column-start:auto}.lg\:bui-col-end-1{grid-column-end:1}.lg\:bui-col-end-2{grid-column-end:2}.lg\:bui-col-end-3{grid-column-end:3}.lg\:bui-col-end-4{grid-column-end:4}.lg\:bui-col-end-5{grid-column-end:5}.lg\:bui-col-end-6{grid-column-end:6}.lg\:bui-col-end-7{grid-column-end:7}.lg\:bui-col-end-8{grid-column-end:8}.lg\:bui-col-end-9{grid-column-end:9}.lg\:bui-col-end-10{grid-column-end:10}.lg\:bui-col-end-11{grid-column-end:11}.lg\:bui-col-end-12{grid-column-end:12}.lg\:bui-col-end-13{grid-column-end:13}.lg\:bui-col-end-auto{grid-column-end:auto}.lg\:bui-row-span-1{grid-row:span 1/span 1}.lg\:bui-row-span-2{grid-row:span 2/span 2}.lg\:bui-row-span-3{grid-row:span 3/span 3}.lg\:bui-row-span-4{grid-row:span 4/span 4}.lg\:bui-row-span-5{grid-row:span 5/span 5}.lg\:bui-row-span-6{grid-row:span 6/span 6}.lg\:bui-row-span-7{grid-row:span 7/span 7}.lg\:bui-row-span-8{grid-row:span 8/span 8}.lg\:bui-row-span-9{grid-row:span 9/span 9}.lg\:bui-row-span-10{grid-row:span 10/span 10}.lg\:bui-row-span-11{grid-row:span 11/span 11}.lg\:bui-row-span-12{grid-row:span 12/span 12}.lg\:bui-row-span-auto{grid-row:span auto/span auto}}@media (width>=1536px){.xl\:bui-columns-1{grid-template-columns:repeat(1,minmax(0,1fr))}.xl\:bui-columns-2{grid-template-columns:repeat(2,minmax(0,1fr))}.xl\:bui-columns-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:bui-columns-4{grid-template-columns:repeat(4,minmax(0,1fr))}.xl\:bui-columns-5{grid-template-columns:repeat(5,minmax(0,1fr))}.xl\:bui-columns-6{grid-template-columns:repeat(6,minmax(0,1fr))}.xl\:bui-columns-7{grid-template-columns:repeat(7,minmax(0,1fr))}.xl\:bui-columns-8{grid-template-columns:repeat(8,minmax(0,1fr))}.xl\:bui-columns-9{grid-template-columns:repeat(9,minmax(0,1fr))}.xl\:bui-columns-10{grid-template-columns:repeat(10,minmax(0,1fr))}.xl\:bui-columns-11{grid-template-columns:repeat(11,minmax(0,1fr))}.xl\:bui-columns-12{grid-template-columns:repeat(12,minmax(0,1fr))}.xl\:bui-columns-auto{grid-template-columns:repeat(auto-fit,minmax(0,1fr))}.xl\:bui-col-span-1{grid-column:span 1/span 1}.xl\:bui-col-span-2{grid-column:span 2/span 2}.xl\:bui-col-span-3{grid-column:span 3/span 3}.xl\:bui-col-span-4{grid-column:span 4/span 4}.xl\:bui-col-span-5{grid-column:span 5/span 5}.xl\:bui-col-span-6{grid-column:span 6/span 6}.xl\:bui-col-span-7{grid-column:span 7/span 7}.xl\:bui-col-span-8{grid-column:span 8/span 8}.xl\:bui-col-span-9{grid-column:span 9/span 9}.xl\:bui-col-span-10{grid-column:span 10/span 10}.xl\:bui-col-span-11{grid-column:span 11/span 11}.xl\:bui-col-span-12{grid-column:span 12/span 12}.xl\:bui-col-span-auto{grid-column:span auto/span auto}.xl\:bui-col-start-1{grid-column-start:1}.xl\:bui-col-start-2{grid-column-start:2}.xl\:bui-col-start-3{grid-column-start:3}.xl\:bui-col-start-4{grid-column-start:4}.xl\:bui-col-start-5{grid-column-start:5}.xl\:bui-col-start-6{grid-column-start:6}.xl\:bui-col-start-7{grid-column-start:7}.xl\:bui-col-start-8{grid-column-start:8}.xl\:bui-col-start-9{grid-column-start:9}.xl\:bui-col-start-10{grid-column-start:10}.xl\:bui-col-start-11{grid-column-start:11}.xl\:bui-col-start-12{grid-column-start:12}.xl\:bui-col-start-13{grid-column-start:13}.xl\:bui-col-start-auto{grid-column-start:auto}.xl\:bui-col-end-1{grid-column-end:1}.xl\:bui-col-end-2{grid-column-end:2}.xl\:bui-col-end-3{grid-column-end:3}.xl\:bui-col-end-4{grid-column-end:4}.xl\:bui-col-end-5{grid-column-end:5}.xl\:bui-col-end-6{grid-column-end:6}.xl\:bui-col-end-7{grid-column-end:7}.xl\:bui-col-end-8{grid-column-end:8}.xl\:bui-col-end-9{grid-column-end:9}.xl\:bui-col-end-10{grid-column-end:10}.xl\:bui-col-end-11{grid-column-end:11}.xl\:bui-col-end-12{grid-column-end:12}.xl\:bui-col-end-13{grid-column-end:13}.xl\:bui-col-end-auto{grid-column-end:auto}.xl\:bui-row-span-1{grid-row:span 1/span 1}.xl\:bui-row-span-2{grid-row:span 2/span 2}.xl\:bui-row-span-3{grid-row:span 3/span 3}.xl\:bui-row-span-4{grid-row:span 4/span 4}.xl\:bui-row-span-5{grid-row:span 5/span 5}.xl\:bui-row-span-6{grid-row:span 6/span 6}.xl\:bui-row-span-7{grid-row:span 7/span 7}.xl\:bui-row-span-8{grid-row:span 8/span 8}.xl\:bui-row-span-9{grid-row:span 9/span 9}.xl\:bui-row-span-10{grid-row:span 10/span 10}.xl\:bui-row-span-11{grid-row:span 11/span 11}.xl\:bui-row-span-12{grid-row:span 12/span 12}.xl\:bui-row-span-auto{grid-row:span auto/span auto}}.bui-gap{gap:var(--gap)}.bui-gap-0\.5{gap:var(--bui-space-0_5)}.bui-gap-1{gap:var(--bui-space-1)}.bui-gap-1\.5{gap:var(--bui-space-1_5)}.bui-gap-2{gap:var(--bui-space-2)}.bui-gap-3{gap:var(--bui-space-3)}.bui-gap-4{gap:var(--bui-space-4)}.bui-gap-5{gap:var(--bui-space-5)}.bui-gap-6{gap:var(--bui-space-6)}.bui-gap-7{gap:var(--bui-space-7)}.bui-gap-8{gap:var(--bui-space-8)}.bui-gap-9{gap:var(--bui-space-9)}.bui-gap-10{gap:var(--bui-space-10)}.bui-gap-11{gap:var(--bui-space-11)}.bui-gap-12{gap:var(--bui-space-12)}.bui-gap-13{gap:var(--bui-space-13)}.bui-gap-14{gap:var(--bui-space-14)}@media (width>=640px){.xs\:bui-gap{gap:var(--gap-xs)}.xs\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xs\:bui-gap-1{gap:var(--bui-space-1)}.xs\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xs\:bui-gap-2{gap:var(--bui-space-2)}.xs\:bui-gap-3{gap:var(--bui-space-3)}.xs\:bui-gap-4{gap:var(--bui-space-4)}.xs\:bui-gap-5{gap:var(--bui-space-5)}.xs\:bui-gap-6{gap:var(--bui-space-6)}.xs\:bui-gap-7{gap:var(--bui-space-7)}.xs\:bui-gap-8{gap:var(--bui-space-8)}.xs\:bui-gap-9{gap:var(--bui-space-9)}.xs\:bui-gap-10{gap:var(--bui-space-10)}.xs\:bui-gap-11{gap:var(--bui-space-11)}.xs\:bui-gap-12{gap:var(--bui-space-12)}.xs\:bui-gap-13{gap:var(--bui-space-13)}.xs\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=768px){.sm\:bui-gap{gap:var(--gap-sm)}.sm\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.sm\:bui-gap-1{gap:var(--bui-space-1)}.sm\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.sm\:bui-gap-2{gap:var(--bui-space-2)}.sm\:bui-gap-3{gap:var(--bui-space-3)}.sm\:bui-gap-4{gap:var(--bui-space-4)}.sm\:bui-gap-5{gap:var(--bui-space-5)}.sm\:bui-gap-6{gap:var(--bui-space-6)}.sm\:bui-gap-7{gap:var(--bui-space-7)}.sm\:bui-gap-8{gap:var(--bui-space-8)}.sm\:bui-gap-9{gap:var(--bui-space-9)}.sm\:bui-gap-10{gap:var(--bui-space-10)}.sm\:bui-gap-11{gap:var(--bui-space-11)}.sm\:bui-gap-12{gap:var(--bui-space-12)}.sm\:bui-gap-13{gap:var(--bui-space-13)}.sm\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1024px){.md\:bui-gap{gap:var(--gap-md)}.md\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.md\:bui-gap-1{gap:var(--bui-space-1)}.md\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.md\:bui-gap-2{gap:var(--bui-space-2)}.md\:bui-gap-3{gap:var(--bui-space-3)}.md\:bui-gap-4{gap:var(--bui-space-4)}.md\:bui-gap-5{gap:var(--bui-space-5)}.md\:bui-gap-6{gap:var(--bui-space-6)}.md\:bui-gap-7{gap:var(--bui-space-7)}.md\:bui-gap-8{gap:var(--bui-space-8)}.md\:bui-gap-9{gap:var(--bui-space-9)}.md\:bui-gap-10{gap:var(--bui-space-10)}.md\:bui-gap-11{gap:var(--bui-space-11)}.md\:bui-gap-12{gap:var(--bui-space-12)}.md\:bui-gap-13{gap:var(--bui-space-13)}.md\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1280px){.lg\:bui-gap{gap:var(--gap-lg)}.lg\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.lg\:bui-gap-1{gap:var(--bui-space-1)}.lg\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.lg\:bui-gap-2{gap:var(--bui-space-2)}.lg\:bui-gap-3{gap:var(--bui-space-3)}.lg\:bui-gap-4{gap:var(--bui-space-4)}.lg\:bui-gap-5{gap:var(--bui-space-5)}.lg\:bui-gap-6{gap:var(--bui-space-6)}.lg\:bui-gap-7{gap:var(--bui-space-7)}.lg\:bui-gap-8{gap:var(--bui-space-8)}.lg\:bui-gap-9{gap:var(--bui-space-9)}.lg\:bui-gap-10{gap:var(--bui-space-10)}.lg\:bui-gap-11{gap:var(--bui-space-11)}.lg\:bui-gap-12{gap:var(--bui-space-12)}.lg\:bui-gap-13{gap:var(--bui-space-13)}.lg\:bui-gap-14{gap:var(--bui-space-14)}}@media (width>=1536px){.xl\:bui-gap{gap:var(--gap-xl)}.xl\:bui-gap-0\.5{gap:var(--bui-space-0_5)}.xl\:bui-gap-1{gap:var(--bui-space-1)}.xl\:bui-gap-1\.5{gap:var(--bui-space-1_5)}.xl\:bui-gap-2{gap:var(--bui-space-2)}.xl\:bui-gap-3{gap:var(--bui-space-3)}.xl\:bui-gap-4{gap:var(--bui-space-4)}.xl\:bui-gap-5{gap:var(--bui-space-5)}.xl\:bui-gap-6{gap:var(--bui-space-6)}.xl\:bui-gap-7{gap:var(--bui-space-7)}.xl\:bui-gap-8{gap:var(--bui-space-8)}.xl\:bui-gap-9{gap:var(--bui-space-9)}.xl\:bui-gap-10{gap:var(--bui-space-10)}.xl\:bui-gap-11{gap:var(--bui-space-11)}.xl\:bui-gap-12{gap:var(--bui-space-12)}.xl\:bui-gap-13{gap:var(--bui-space-13)}.xl\:bui-gap-14{gap:var(--bui-space-14)}}.bui-align-start{align-items:start}.bui-align-center{align-items:center}.bui-align-end{align-items:end}.bui-align-baseline{align-items:baseline}.bui-align-stretch{align-items:stretch}.bui-jc-start{justify-content:start}.bui-jc-center{justify-content:center}.bui-jc-end{justify-content:end}.bui-jc-between{justify-content:space-between}.bui-fd-row{flex-direction:row}.bui-fd-column{flex-direction:column}.bui-fd-row-reverse{flex-direction:row-reverse}.bui-fd-column-reverse{flex-direction:column-reverse}@media (width>=640px){.xs\:bui-align-start{align-items:start}.xs\:bui-align-center{align-items:center}.xs\:bui-align-end{align-items:end}.xs\:bui-align-stretch{align-items:stretch}.xs\:bui-jc-start{justify-content:start}.xs\:bui-jc-center{justify-content:center}.xs\:bui-jc-end{justify-content:end}.xs\:bui-jc-between{justify-content:space-between}.xs\:bui-fd-row{flex-direction:row}.xs\:bui-fd-column{flex-direction:column}.xs\:bui-fd-row-reverse{flex-direction:row-reverse}.xs\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=768px){.sm\:bui-align-start{align-items:start}.sm\:bui-align-center{align-items:center}.sm\:bui-align-end{align-items:end}.sm\:bui-align-stretch{align-items:stretch}.sm\:bui-jc-start{justify-content:start}.sm\:bui-jc-center{justify-content:center}.sm\:bui-jc-end{justify-content:end}.sm\:bui-jc-between{justify-content:space-between}.sm\:bui-fd-row{flex-direction:row}.sm\:bui-fd-column{flex-direction:column}.sm\:bui-fd-row-reverse{flex-direction:row-reverse}.sm\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1024px){.md\:bui-align-start{align-items:start}.md\:bui-align-center{align-items:center}.md\:bui-align-end{align-items:end}.md\:bui-align-stretch{align-items:stretch}.md\:bui-jc-start{justify-content:start}.md\:bui-jc-center{justify-content:center}.md\:bui-jc-end{justify-content:end}.md\:bui-jc-between{justify-content:space-between}.md\:bui-fd-row{flex-direction:row}.md\:bui-fd-column{flex-direction:column}.md\:bui-fd-row-reverse{flex-direction:row-reverse}.md\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1280px){.lg\:bui-align-start{align-items:start}.lg\:bui-align-center{align-items:center}.lg\:bui-align-end{align-items:end}.lg\:bui-align-stretch{align-items:stretch}.lg\:bui-jc-start{justify-content:start}.lg\:bui-jc-center{justify-content:center}.lg\:bui-jc-end{justify-content:end}.lg\:bui-jc-between{justify-content:space-between}.lg\:bui-fd-row{flex-direction:row}.lg\:bui-fd-column{flex-direction:column}.lg\:bui-fd-row-reverse{flex-direction:row-reverse}.lg\:bui-fd-column-reverse{flex-direction:column-reverse}}@media (width>=1536px){.xl\:bui-align-start{align-items:start}.xl\:bui-align-center{align-items:center}.xl\:bui-align-end{align-items:end}.xl\:bui-align-stretch{align-items:stretch}.xl\:bui-jc-start{justify-content:start}.xl\:bui-jc-center{justify-content:center}.xl\:bui-jc-end{justify-content:end}.xl\:bui-jc-between{justify-content:space-between}.xl\:bui-fd-row{flex-direction:row}.xl\:bui-fd-column{flex-direction:column}.xl\:bui-fd-row-reverse{flex-direction:row-reverse}.xl\:bui-fd-column-reverse{flex-direction:column-reverse}}:where(a){color:inherit;text-decoration:none}@keyframes pulse{50%{opacity:.5}}:root{--bui-font-regular:system-ui;--bui-font-monospace:ui-monospace,"Menlo","Monaco","Consolas","Liberation Mono","Courier New",monospace;--bui-font-weight-regular:400;--bui-font-weight-bold:600;--bui-font-size-1:.625rem;--bui-font-size-2:.75rem;--bui-font-size-3:.875rem;--bui-font-size-4:1rem;--bui-font-size-5:1.25rem;--bui-font-size-6:1.5rem;--bui-font-size-7:2rem;--bui-font-size-8:3rem;--bui-font-size-9:4rem;--bui-font-size-10:5.75rem;--bui-space:.25rem;--bui-space-0_5:calc(var(--bui-space)*.5);--bui-space-1:var(--bui-space);--bui-space-1_5:calc(var(--bui-space)*1.5);--bui-space-2:calc(var(--bui-space)*2);--bui-space-3:calc(var(--bui-space)*3);--bui-space-4:calc(var(--bui-space)*4);--bui-space-5:calc(var(--bui-space)*5);--bui-space-6:calc(var(--bui-space)*6);--bui-space-7:calc(var(--bui-space)*7);--bui-space-8:calc(var(--bui-space)*8);--bui-space-9:calc(var(--bui-space)*9);--bui-space-10:calc(var(--bui-space)*10);--bui-space-11:calc(var(--bui-space)*11);--bui-space-12:calc(var(--bui-space)*12);--bui-space-13:calc(var(--bui-space)*13);--bui-space-14:calc(var(--bui-space)*14);--bui-radius-1:calc(.125rem);--bui-radius-2:calc(.25rem);--bui-radius-3:calc(.5rem);--bui-radius-4:calc(.75rem);--bui-radius-5:calc(1rem);--bui-radius-6:calc(1.25rem);--bui-radius-full:9999px;--bui-black:#000;--bui-white:#fff;--bui-gray-1:#f8f8f8;--bui-gray-2:#ececec;--bui-gray-3:#d9d9d9;--bui-gray-4:#c1c1c1;--bui-gray-5:#9e9e9e;--bui-gray-6:#8c8c8c;--bui-gray-7:#757575;--bui-gray-8:#595959;--bui-bg:var(--bui-gray-1);--bui-bg-surface-1:var(--bui-white);--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#1f5493;--bui-bg-solid-hover:#163a66;--bui-bg-solid-pressed:#0f2b4e;--bui-bg-solid-disabled:#ebebeb;--bui-bg-tint:transparent;--bui-bg-tint-hover:#1f549366;--bui-bg-tint-pressed:#1f549399;--bui-bg-tint-disabled:#ebebeb;--bui-bg-danger:#feebe7;--bui-bg-warning:#fff2b2;--bui-bg-success:#e6f6eb;--bui-fg-primary:var(--bui-black);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#1f5493;--bui-fg-link-hover:#1f2d5c;--bui-fg-disabled:#9e9e9e;--bui-fg-solid:var(--bui-white);--bui-fg-solid-disabled:#9c9c9c;--bui-fg-tint:#1f5493;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#0000001a;--bui-border-hover:#0003;--bui-border-pressed:#0006;--bui-border-disabled:#0000001a;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#a0a0a03b;--bui-scrollbar-thumb:#a0a0a0;--bui-animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite}[data-theme-mode=dark]{--bui-gray-1:#191919;--bui-gray-2:#242424;--bui-gray-3:#373737;--bui-gray-4:#464646;--bui-gray-5:#575757;--bui-gray-6:#7b7b7b;--bui-gray-7:#9e9e9e;--bui-gray-8:#b4b4b4;--bui-bg:#333;--bui-bg-surface-1:#424242;--bui-bg-surface-2:var(--bui-gray-2);--bui-bg-solid:#9cc9ff;--bui-bg-solid-hover:#83b9fd;--bui-bg-solid-pressed:#83b9fd;--bui-bg-solid-disabled:#222;--bui-bg-tint:transparent;--bui-bg-tint-hover:#9cc9ff1f;--bui-bg-tint-pressed:#9cc9ff29;--bui-bg-tint-disabled:transparent;--bui-bg-danger:#3b1219;--bui-bg-warning:#302008;--bui-bg-success:#132d21;--bui-fg-primary:var(--bui-white);--bui-fg-secondary:var(--bui-gray-7);--bui-fg-link:#9cc9ff;--bui-fg-link-hover:#7eb5f7;--bui-fg-disabled:var(--bui-gray-7);--bui-fg-solid:#101821;--bui-fg-solid-disabled:var(--bui-gray-5);--bui-fg-tint:#9cc9ff;--bui-fg-tint-disabled:var(--bui-gray-5);--bui-fg-danger:#e22b2b;--bui-fg-warning:#e36d05;--bui-fg-success:#1db954;--bui-border:#ffffff1f;--bui-border-hover:#fff6;--bui-border-pressed:#ffffff80;--bui-border-disabled:#fff3;--bui-border-danger:#f87a7a;--bui-border-warning:#e36d05;--bui-border-success:#53db83;--bui-ring:#1f5493;--bui-scrollbar:#3636363a;--bui-scrollbar-thumb:#575757}.bui-AvatarRoot{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-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}.bui-AvatarRoot[data-size=small]{width:1.5rem;height:1.5rem}.bui-AvatarRoot[data-size=medium]{width:2rem;height:2rem}.bui-AvatarRoot[data-size=large]{width:3rem;height:3rem}.bui-AvatarImage{object-fit:cover;width:100%;height:100%}.bui-AvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-Box{font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary)}.bui-Button{user-select:none;font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-bold);cursor:pointer;border-radius:var(--bui-radius-2);justify-content:center;align-items:center;gap:var(--bui-space-1_5);border:none;flex-shrink:0;padding:0;display:inline-flex;&[data-disabled=true]{cursor:not-allowed}}.bui-Button[data-variant=primary]{background-color:var(--bui-bg-solid);color:var(--bui-fg-solid);&:hover{background-color:var(--bui-bg-solid-hover);transition:background-color .15s}&:active{background-color:var(--bui-bg-solid-pressed)}&:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled=true]{background-color:var(--bui-bg-solid-disabled);color:var(--bui-fg-solid-disabled)}}.bui-Button[data-variant=secondary]{background-color:var(--bui-bg-surface-1);box-shadow:inset 0 0 0 1px var(--bui-border);color:var(--bui-fg-primary);&:hover{box-shadow:inset 0 0 0 1px var(--bui-border-hover);transition:box-shadow .15s}&:active{box-shadow:inset 0 0 0 1px var(--bui-border-pressed)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{box-shadow:inset 0 0 0 1px var(--bui-border-disabled);color:var(--bui-fg-disabled)}}.bui-Button[data-variant=tertiary]{color:var(--bui-fg-primary);background-color:#0000;&:hover{background-color:var(--bui-bg-surface-1);transition:background-color .2s}&:active{background-color:var(--bui-bg-surface-2)}&:focus-visible{box-shadow:inset 0 0 0 2px var(--bui-ring);outline:none;transition:none}&[data-disabled=true]{color:var(--bui-fg-disabled);background-color:#0000}}.bui-Button[data-size=medium]{font-size:var(--bui-font-size-4);padding:0 var(--bui-space-3);height:2.5rem}.bui-Button[data-size=small]{font-size:var(--bui-font-size-3);padding:0 var(--bui-space-2);height:2rem}.bui-Button[data-size=small] svg{width:1rem;height:1rem}.bui-Button[data-size=medium] svg{width:1.25rem;height:1.25rem}.bui-ButtonIcon{justify-content:center;align-items:center}.bui-ButtonIcon[data-size=small]{width:2rem;padding:0}.bui-ButtonIcon[data-size=medium]{width:2.5rem;padding:0}.bui-Card{gap:var(--bui-space-3);background-color:var(--bui-bg-surface-1);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-3);color:var(--bui-fg-primary);border:1px solid var(--bui-border);flex-direction:column;width:100%;min-height:0;display:flex;overflow:hidden}.bui-CardBody{flex:1;min-height:0;overflow:auto}.bui-CardHeader,.bui-CardFooter{padding-inline:var(--bui-space-3)}.bui-CheckboxRoot{width:1rem;height:1rem;box-shadow:inset 0 0 0 1px var(--bui-border);cursor:pointer;background-color:var(--bui-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}.bui-CheckboxRoot:focus-visible{outline:2px solid var(--bui-ring);outline-offset:2px;transition:none}.bui-CheckboxRoot[data-checked]{background-color:var(--bui-bg-solid);box-shadow:none;color:var(--bui-fg-solid)}.bui-CheckboxLabel{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);user-select:none;flex-direction:row;display:flex;&:hover{& .bui-CheckboxRoot:not([data-checked]){box-shadow:inset 0 0 0 1px var(--bui-border-hover)}}}.bui-CheckboxIndicator{color:var(--bui-fg-solid);justify-content:center;align-items:center;display:flex}.bui-CollapsiblePanel{height:var(--collapsible-panel-height);transition:all .15s ease-out;display:flex;overflow:hidden;&[data-starting-style],&[data-ending-style]{height:0}}.bui-Container{max-width:120rem;padding-inline:var(--bui-space-4);margin-inline:auto;transition:padding .2s ease-in-out}@media (width>=640px){.bui-Container{padding-inline:var(--bui-space-5)}}.bui-FieldError{color:var(--bui-fg-danger);font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);margin-top:var(--bui-space-2);display:inline-block}.bui-FieldLabelWrapper{margin-bottom:var(--bui-space-3);gap:var(--bui-space-1);flex-direction:column;display:flex}.bui-FieldLabel{color:var(--bui-fg-primary);cursor:pointer;font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);margin-right:auto}.bui-FieldSecondaryLabel{color:var(--bui-fg-secondary);font-weight:var(--bui-font-weight-regular);margin-left:var(--bui-space-1)}.bui-FieldDescription{font-weight:var(--bui-font-weight-regular);font-size:var(--bui-font-size-2);color:var(--bui-fg-secondary);margin:0}.bui-Flex{min-width:0;display:flex}.bui-Grid{display:grid}.bui-HeaderToolbar{margin-bottom:var(--bui-space-6);&:before{content:"";background-color:var(--bui-bg);z-index:0;height:16px;position:absolute;top:0;left:0;right:0}&[data-has-tabs=true]{margin-bottom:0}}.bui-HeaderToolbarWrapper{z-index:1;background-color:var(--bui-bg-surface-1);padding-inline:var(--bui-space-5);border-bottom:1px solid var(--bui-border);color:var(--bui-fg-primary);flex-direction:row;justify-content:space-between;align-items:center;height:52px;display:flex;position:relative}.bui-HeaderToolbarContent{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-HeaderToolbarName{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-3);font-weight:var(--bui-font-weight-regular);flex-direction:row;flex-shrink:0;display:flex}.bui-HeaderToolbarIcon{width:16px;height:16px;color:var(--bui-fg-primary);& svg{width:100%;height:100%}}.bui-HeaderToolbarControls{right:var(--bui-space-5);align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex;position:absolute;top:50%;transform:translateY(-50%)}.bui-HeaderTabsWrapper{margin-bottom:var(--bui-space-4);padding-inline:var(--bui-space-3);border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1)}.bui-HeaderPage{gap:var(--bui-space-1);margin-top:var(--bui-space-6);margin-bottom:var(--bui-space-6);flex-direction:column;display:flex}.bui-HeaderPageContent{flex-direction:row;justify-content:space-between;display:flex}.bui-HeaderPageTabsWrapper{margin-left:-8px}.bui-HeaderPageControls,.bui-HeaderPageBreadcrumbs{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:flex}.bui-Icon{width:1rem;height:1rem}.bui-Link{font-family:var(--bui-font-regular);cursor:pointer;margin:0;padding:0;text-decoration-line:none;display:inline-block;&: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,currentColor 30%,transparent)}}.bui-MenuPopover{border:1px solid var(--bui-border);border-radius:var(--bui-radius-2);background:var(--bui-bg-surface-1);color:var(--bui-fg-primary);outline:none;flex-direction:column;min-height:0;transition:transform .2s,opacity .2s;display:flex;overflow:hidden;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}&[data-placement=top]{--origin:translateY(8px)}&[data-placement=bottom]{--origin:translateY(-8px)}&[data-placement=right]{--origin:translateX(-8px)}&[data-placement=left]{--origin:translateX(8px)}}.bui-MenuContent{max-height:inherit;box-sizing:border-box;padding:var(--bui-space-1);outline:none;min-width:150px;overflow:auto}.bui-MenuPopover .bui-ScrollAreaRoot{flex-direction:column;flex:1;height:100%;min-height:0;display:flex}.bui-MenuPopover .bui-ScrollAreaScrollbar{margin-inline:var(--bui-space-1_5)}.bui-MenuItem{height:2rem;padding-inline:var(--bui-space-2);border-radius:var(--bui-radius-2);cursor:default;color:var(--bui-fg-primary);font-size:var(--bui-font-size-3);justify-content:space-between;align-items:center;gap:var(--bui-space-6);outline:none;display:flex;&[data-focused],&[data-open]{background:var(--bui-bg-surface-2);color:var(--bui-fg-primary)}&[data-color=danger]{color:var(--bui-fg-danger)}&[data-color=danger][data-focused]{background:var(--bui-bg-danger);color:var(--bui-fg-danger)}&[data-has-submenu]{&>.bui-MenuItemArrow{display:block}}}.bui-MenuItemListBox{height:2rem;padding-inline:var(--bui-space-2);border-radius:var(--bui-radius-2);cursor:default;color:var(--bui-fg-primary);font-size:var(--bui-font-size-3);justify-content:space-between;align-items:center;gap:var(--bui-space-6);outline:none;display:flex;&:hover{background:var(--bui-bg-surface-2);color:var(--bui-fg-primary)}&[data-selected] .bui-MenuItemListBoxCheck{&>svg{opacity:1;color:var(--bui-fg-primary)}}}.bui-MenuItemListBoxCheck{justify-content:center;align-items:center;width:1rem;height:1rem;display:flex;&>svg{opacity:0;width:1rem;height:1rem}}.bui-MenuItemContent{align-items:center;gap:var(--bui-space-2);display:flex;&>svg{width:1rem;height:1rem}}.bui-MenuItemArrow{width:1rem;height:1rem;display:none;&>svg{width:1rem;height:1rem}}.bui-MenuSection{&:first-child .bui-MenuSectionHeader{padding-top:0}}.bui-MenuSectionHeader{height:2rem;padding-top:var(--bui-space-3);padding-left:var(--bui-space-2);color:var(--bui-fg-primary);font-size:var(--bui-font-size-1);letter-spacing:.05rem;text-transform:uppercase;align-items:center;font-weight:700;display:flex}.bui-MenuSeparator{background:var(--bui-border);height:1px;margin-inline:var(--bui-space-1_5);margin-block:var(--bui-space-1)}.bui-MenuSearchField{font-family:var(--bui-font-regular);flex-shrink:0;width:100%;position:relative;&[data-empty]{& .bui-MenuSearchFieldClear{display:none}}}.bui-MenuSearchFieldInput{padding:0 var(--bui-space-3);border:none;border-bottom:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);width:100%;height:2rem;cursor:inherit;outline:none;align-items:center;display:flex;&::-webkit-search-cancel-button,&::-webkit-search-decoration{-webkit-appearance:none}}.bui-MenuSearchFieldClear{right:var(--bui-space-2);cursor:pointer;color:var(--bui-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;&>svg{width:1rem;height:1rem}}.bui-MenuEmptyState{padding:var(--bui-space-1);color:var(--bui-fg-secondary);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular)}.bui-Popover{background-color:var(--bui-bg-surface-1);border:1px solid var(--bui-border);border-radius:var(--bui-radius-3);padding-block:var(--bui-space-1);margin-right:12px;overflow:scroll;box-shadow:0 4px 12px #0000001a}.bui-RadioGroup{color:var(--bui-fg-primary);flex-direction:column;display:flex}.bui-RadioGroup[data-orientation=horizontal] .bui-RadioGroupContent{gap:var(--bui-space-4);flex-direction:row}.bui-RadioGroupContent{gap:var(--bui-space-2);flex-direction:column;display:flex}.bui-Radio{align-items:center;gap:var(--bui-space-2);font-size:var(--bui-font-size-2);color:var(--bui-fg-primary);forced-color-adjust:none;display:flex;position:relative;&:before{content:"";box-sizing:border-box;border:.125rem solid var(--bui-border);background:var(--bui-gray-1);border-radius:var(--bui-radius-full);width:1rem;height:1rem;transition:all .2s;display:block}&[data-pressed]:before{border-color:var(--bui-border)}&[data-selected]{&:before{border-color:var(--bui-bg-solid);border-width:.25rem}&[data-pressed]:before{border-color:var(--bui-bg-solid)}}&[data-focus-visible]:before{outline:2px solid var(--bui-ring);outline-offset:2px}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}&[data-invalid]:before,&[data-invalid][data-selected]:before{border-color:var(--bui-border-danger)}&[data-disabled][data-invalid]{color:var(--bui-fg-disabled);&:before{border-color:var(--bui-border-disabled);background:var(--bui-bg-disabled)}&[data-selected]:before{border-color:var(--bui-border-disabled)}}}.bui-Table{caption-side:bottom;border-collapse:collapse;width:100%}.bui-TableHeader{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out}.bui-TableHead{text-align:left;padding:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary)}.bui-TableHeadSortButton{cursor:pointer;user-select:none;align-items:center;gap:var(--bui-space-1);display:inline-flex;&:hover svg{opacity:.5}& svg{opacity:0;transition:opacity .1s ease-in-out,transform .1s ease-in-out}&[data-sort-order=asc] svg{opacity:1;transform:rotate(0)}&[data-sort-order=desc] svg{opacity:1;transform:rotate(180deg)}}.bui-TableBody{color:var(--bui-fg-primary)}.bui-TableRow{border-bottom:1px solid var(--bui-border);transition:color .2s ease-in-out;&[data-react-aria-pressable=true]{cursor:pointer}}.bui-TableBody .bui-TableRow:hover{background-color:var(--bui-gray-2)}.bui-TableCell{padding:var(--bui-space-3);font-size:var(--bui-font-size-3);padding:var(--bui-space-3);font-size:var(--bui-font-size-3)}.bui-TableCellContentWrapper{align-items:center;gap:var(--bui-space-2);flex-direction:row;display:inline-flex}.bui-TableCellIcon,.bui-TableCellIcon svg{color:var(--bui-fg-primary);align-items:center;display:inline-flex}.bui-TableCellContent{gap:var(--bui-space-0_5);flex-direction:column;display:flex}.bui-TableCellProfile{gap:var(--bui-space-2);flex-direction:row;align-items:center;display:flex}.bui-TableCellProfileAvatar{vertical-align:middle;user-select:none;color:var(--bui-fg-primary);background-color:var(--bui-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}.bui-TableCellProfileAvatarImage{object-fit:cover;width:100%;height:100%}.bui-TableCellProfileAvatarFallback{width:100%;height:100%;font-size:var(--bui-font-size-2);font-weight:var(--bui-font-weight-regular);box-shadow:inset 0 0 0 1px var(--bui-border);border-radius:var(--bui-radius-full);justify-content:center;align-items:center;display:flex}.bui-DataTablePagination{padding-top:var(--bui-space-5);justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--left{justify-content:space-between;align-items:center;display:flex}.bui-DataTablePagination--right{justify-content:space-between;align-items:center;gap:var(--bui-space-2);display:flex}.bui-DataTablePagination--select{min-width:10.5rem}.bui-Tabs{--active-tab-left:0px;--active-tab-right:0px;--active-tab-top:0px;--active-tab-bottom:0px;--active-tab-width:0px;--active-tab-height:0px;--active-transition-duration:0s;--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}.bui-TabList{flex-direction:row;display:flex}.bui-TabListWrapper{position:relative}.bui-Tab{font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-secondary);cursor:pointer;z-index:2;height:36px;padding-inline:var(--bui-space-2);justify-content:center;align-items:center;display:flex;position:relative;&[data-selected=true]{color:var(--bui-fg-primary)}}.bui-TabActive{content:"";left:calc(var(--active-tab-left) + var(--bui-space-2));width:calc(var(--active-tab-width) - var(--bui-space-4));background-color:var(--bui-fg-primary);height:1px;transition:left var(--active-transition-duration)ease-out,opacity .15s ease-out,width var(--active-transition-duration)ease-out;opacity:1;border-radius:4px;position:absolute;bottom:-1px}.bui-TabHovered{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(--bui-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}.bui-TabPanel{padding-inline:var(--bui-space-2);padding-top:var(--bui-space-4)}.bui-TagList{gap:var(--bui-space-2);flex-wrap:wrap;display:flex}.bui-Tag{color:var(--bui-fg-primary);background-color:var(--bui-gray-2);border-radius:var(--bui-radius-2);font-weight:var(--bui-font-weight-regular);justify-content:center;align-items:center;gap:var(--bui-space-1);box-sizing:border-box;transition-property:background-color,box-shadow,color;transition-duration:.2s;transition-timing-function:ease-in-out;display:flex}.bui-Tag[data-size=small]{height:26px;padding:0 var(--bui-space-2);font-size:var(--bui-font-size-1)}.bui-Tag[data-size=medium]{height:32px;padding:0 var(--bui-space-2);font-size:var(--bui-font-size-2)}.bui-Tag[data-hovered]{background-color:var(--bui-gray-3);cursor:pointer}.bui-Tag[data-focus-visible]{outline:2px solid var(--bui-ring);outline-offset:1px}.bui-Tag[data-selected]{box-shadow:inset 0 0 0 1px var(--bui-gray-8)}.bui-Tag[data-disabled]{color:var(--bui-fg-disabled);cursor:not-allowed}.bui-TagRemoveButton{cursor:pointer;color:var(--bui-fg-primary);background-color:#0000;border:none;width:1rem;height:1rem;margin:0;padding:0}.bui-TagIcon{justify-content:center;align-items:center;transition:color .2s ease-in-out;display:flex;& svg{width:1rem;height:1rem}}.bui-Text{font-family:var(--bui-font-regular);margin:0;padding:0}.bui-Text[data-variant=title-large]{font-size:var(--bui-font-size-8);line-height:140%}.bui-Text[data-variant=title-medium]{font-size:var(--bui-font-size-7);line-height:140%}.bui-Text[data-variant=title-small]{font-size:var(--bui-font-size-6);line-height:140%}.bui-Text[data-variant=title-x-small]{font-size:var(--bui-font-size-5);line-height:140%}.bui-Text[data-variant=body-large]{font-size:var(--bui-font-size-4);line-height:140%}.bui-Text[data-variant=body-medium]{font-size:var(--bui-font-size-3);line-height:140%}.bui-Text[data-variant=body-small]{font-size:var(--bui-font-size-2);line-height:140%}.bui-Text[data-variant=body-x-small]{font-size:var(--bui-font-size-1);line-height:140%}.bui-Text[data-weight=regular]{font-weight:var(--bui-font-weight-regular)}.bui-Text[data-weight=bold]{font-weight:var(--bui-font-weight-bold)}.bui-Text[data-color=primary]{color:var(--bui-fg-primary)}.bui-Text[data-color=secondary]{color:var(--bui-fg-secondary)}.bui-Text[data-color=danger]{color:var(--bui-fg-danger)}.bui-Text[data-color=warning]{color:var(--bui-fg-warning)}.bui-Text[data-color=success]{color:var(--bui-fg-success)}.bui-Text[data-truncate]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bui-Text[data-as=span],.bui-Text[data-as=label],.bui-Text[data-as=strong],.bui-Text[data-as=em],.bui-Text[data-as=small]{display:inline-block}.bui-TextField{font-family:var(--bui-font-regular);flex-direction:column;flex-shrink:0;width:100%;display:flex}.bui-InputWrapper{position:relative;&[data-size=small] .bui-Input{height:2rem}&[data-size=medium] .bui-Input{height:2.5rem}&[data-size=small] .bui-Input[data-icon]{padding-left:var(--bui-space-8)}&[data-size=medium] .bui-Input[data-icon]{padding-left:var(--bui-space-9)}}.bui-InputIcon{left:var(--bui-space-3);margin-right:var(--bui-space-1);color:var(--bui-fg-primary);pointer-events:none;flex-shrink:0;transition:left .2s ease-in-out;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}}.bui-Input{padding:0 var(--bui-space-3);border-radius:var(--bui-radius-2);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-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(--bui-fg-secondary)}&[data-focused]{outline-color:var(--bui-border-pressed);outline-width:0}&[data-hovered]{border-color:var(--bui-border-hover)}&[data-focused]{border-color:var(--bui-border-pressed);outline-width:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-disabled]{opacity:.5;cursor:not-allowed;border:1px solid var(--bui-border-disabled)}}.bui-PasswordField{font-family:var(--bui-font-regular);--bui-passwordmanager-icon-width:var(--bui-space-1);flex-direction:column;flex-shrink:0;width:100%;display:flex}.bui-InputVisibility{right:var(--bui-passwordmanager-icon-width);cursor:pointer;color:var(--bui-fg-primary);background-color:#0000;border:none;justify-content:center;align-items:center;margin:0;padding:0;display:flex;position:absolute;top:0;bottom:0;&[data-size=small]{width:2rem;height:2rem}&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium]{width:2.5rem;height:2.5rem}&[data-size=medium] svg{width:1.25rem;height:1.25rem}}.bui-PasswordField .bui-InputWrapper[data-size=small] .bui-Input{padding-right:calc(2rem + var(--bui-passwordmanager-icon-width))}.bui-PasswordField .bui-InputWrapper[data-size=medium] .bui-Input{padding-right:calc(2.5rem + var(--bui-passwordmanager-icon-width))}.bui-SearchField{flex:1 0;&[data-empty]{& .bui-InputClear{display:none}}&[data-start-collapsed=true]{flex:0 auto;padding:0;transition:flex-basis .3s ease-in-out;&[data-collapsed=true]{flex-basis:200px}&[data-collapsed=false]{cursor:pointer;&[data-size=medium]{flex-basis:2.5rem;height:2.5rem}&[data-size=small]{flex-basis:2rem;height:2rem}&[data-size=medium] .bui-Input{&::placeholder{opacity:0}}&[data-size=small] .bui-Input{&::placeholder{opacity:0}}& .bui-InputWrapper{& .bui-Input[data-icon]{padding-right:0}}}}}.bui-SearchField .bui-Input{transition:padding .3s ease-in-out,border-color .2s ease-in-out,outline-color .2s ease-in-out;&[data-hovered]{border-color:var(--bui-border-hover)}&[data-focused]{border-color:var(--bui-border-pressed);outline-width:0}}.bui-SearchField .bui-InputWrapper{& .bui-Input[data-icon]{padding-right:var(--bui-space-6)}}.bui-SearchField .bui-InputIcon{justify-content:center;display:flex;left:0;&[data-size=small]{width:var(--bui-space-8)}&[data-size=medium]{width:var(--bui-space-10)}}.bui-InputClear{cursor:pointer;color:var(--bui-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}.bui-InputClear:hover{color:var(--bui-fg-primary)}.bui-InputClear[data-size=small]{width:2rem;height:2rem}.bui-InputClear[data-size=medium]{width:2.5rem;height:2.5rem}.bui-InputClear svg{width:1rem;height:1rem}.bui-Skeleton{animation:var(--bui-animate-pulse);background-color:var(--bui-bg-surface-2);border-radius:var(--bui-radius-2)}.bui-Skeleton[data-rounded=true]{border-radius:var(--bui-radius-full)}.bui-Tooltip{background:var(--bui-bg-surface-1);border:1px solid var(--bui-gray-3);forced-color-adjust:none;padding:var(--bui-space-2)var(--bui-space-3);max-width:240px;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);color:var(--bui-fg-primary);border-radius:4px;outline:none;transition:transform .2s,opacity .2s;transform:translate(0,0);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -4px #0000001a;&[data-entering],&[data-exiting]{transform:var(--origin);opacity:0}--tooltip-offset:var(--bui-space-3)&[data-placement=top]{margin-bottom:var(--tooltip-offset);--origin:translateY(4px)}&[data-placement=right]{margin-left:var(--tooltip-offset);--origin:translateX(-4px)}&[data-placement=bottom]{margin-top:var(--tooltip-offset);--origin:translateY(-4px)}&[data-placement=left]{margin-right:var(--tooltip-offset);--origin:translateX(4px)}}.bui-TooltipArrow{& svg{display:block;& path:first-child{fill:var(--bui-bg-surface-1)}& path:nth-child(2){fill:var(--bui-gray-3)}--tooltip-arrow-overlap:-2px}&[data-placement=top] svg{margin-top:var(--tooltip-arrow-overlap)}&[data-placement=bottom] svg{margin-bottom:var(--tooltip-arrow-overlap);transform:rotate(180deg)}&[data-placement=right] svg{margin-right:var(--tooltip-arrow-overlap);transform:rotate(90deg)}&[data-placement=left] svg{margin-left:var(--tooltip-arrow-overlap);transform:rotate(-90deg)}}[data-theme=dark]{& .bui-Tooltip{background:var(--bui-bg-surface-2);box-shadow:none;border:1px solid var(--bui-gray-4)}& .bui-TooltipArrow{& svg path:first-child{fill:var(--bui-bg-surface-2)}& svg path:nth-child(2){fill:var(--bui-gray-4)}}}.bui-ScrollAreaRoot{box-sizing:border-box;width:100%}.bui-ScrollAreaViewport{overscroll-behavior:contain;height:100%}.bui-ScrollAreaContent{padding-block:.75rem;flex-direction:column;gap:1rem;padding-left:1rem;padding-right:1.5rem;display:flex}.bui-ScrollAreaScrollbar{background-color:var(--bui-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}}.bui-ScrollAreaThumb{border-radius:inherit;background-color:var(--bui-scrollbar-thumb);width:100%}.bui-Select[data-invalid]{& .bui-SelectTrigger{border-color:var(--bui-fg-danger)}}.bui-SelectTrigger{box-sizing:border-box;border-radius:var(--bui-radius-3);border:1px solid var(--bui-border);background-color:var(--bui-bg-surface-1);cursor:pointer;justify-content:space-between;align-items:center;gap:var(--bui-space-2);width:100%;display:flex;& svg{color:var(--bui-fg-secondary);flex-shrink:0}&[data-size=small]{height:2rem;padding-inline:var(--bui-space-3)}&[data-size=medium]{height:3rem;padding-inline:var(--bui-space-4)}&[data-size=small] svg{width:1rem;height:1rem}&[data-size=medium] svg{width:1.25rem;height:1.25rem}&::placeholder{color:var(--bui-fg-secondary)}&:hover{border-color:var(--bui-border-hover);transition:border-color .2s ease-in-out,outline-color .2s ease-in-out}&:focus-visible{border-color:var(--bui-border-pressed);outline:0}&[data-invalid]{border-color:var(--bui-fg-danger)}&[data-invalid]:hover,&[data-invalid]:focus-visible{border-width:2px}&[disabled]{cursor:not-allowed;border-color:var(--bui-border-disabled);color:var(--bui-fg-disabled)}&[disabled] .bui-SelectValue{color:var(--bui-fg-disabled)}&[data-popup-open] .bui-SelectIcon{transform:rotate(180deg)}}.bui-SelectValue{text-overflow:ellipsis;white-space:nowrap;width:100%;font-size:var(--bui-font-size-3);font-family:var(--bui-font-regular);font-weight:var(--bui-font-weight-regular);color:var(--bui-fg-primary);text-align:left;overflow:hidden;& .bui-SelectItemIndicator{display:none}&[disabled]{color:var(--bui-fg-disabled)}}.bui-SelectItem{width:var(--anchor-width);padding-block:var(--bui-space-2);padding-left:var(--bui-space-3);padding-right:var(--bui-space-4);color:var(--bui-fg-primary);border-radius:var(--bui-radius-3);cursor:pointer;user-select:none;font-size:var(--bui-font-size-3);align-items:center;gap:var(--bui-space-1);outline:none;grid-template-columns:1rem 1fr;grid-template-areas:"icon text";display:grid;position:relative;&[data-focused]{z-index:0;color:var(--bui-fg-primary);position:relative}&[data-focused]:before{content:"";z-index:-1;background-color:var(--bui-bg-tint-hover);border-radius:.25rem;position:absolute;inset-block:0;inset-inline:.25rem}&[data-disabled]{cursor:not-allowed;color:var(--bui-fg-disabled)}&[data-selected] .bui-SelectItemIndicator{opacity:1}}.bui-SelectItemIndicator{opacity:0;grid-area:icon;justify-content:center;align-items:center;transition:opacity .2s ease-in-out;display:flex}.bui-SelectItemLabel{flex:1;grid-area:text}.bui-Switch{align-items:center;gap:var(--bui-space-3);font-size:var(--bui-font-size-3);color:var(--bui-fg-primary);cursor:pointer;display:flex;position:relative;&[data-pressed] .bui-SwitchIndicator{&:before{background:var(--bui-fg-solid)}}&[data-selected]{& .bui-SwitchIndicator{background:var(--bui-bg-solid);&:before{background:var(--bui-fg-solid);transform:translate(100%)}}&[data-pressed]{& .indicator{background:var(--bui-gray-3)}}}&[data-focus-visible] .bui-SwitchIndicator{outline-offset:2px;outline:2px solid}}.bui-SwitchIndicator{background:var(--bui-gray-3);border:2px;border-radius:1.143rem;width:2rem;height:1.143rem;transition:all .2s;&:before{content:"";background:var(--bui-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/packages/ui/css/styles.css b/packages/ui/css/styles.css index 0554276dc2..d93ba87829 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -10431,16 +10431,6 @@ display: flex; } -.bui-PasswordField { - font-family: var(--bui-font-regular); - flex-direction: column; - flex-shrink: 0; - width: 100%; - display: flex; - /* Reserve space for browser/password manager icon (e.g. 1Password) */ - --bui-passwordmanager-icon-width: var(--bui-space-1); -} - .bui-InputWrapper { position: relative; @@ -10461,60 +10451,6 @@ } } -.bui-InputAction { - position: absolute; - display: flex; - flex-direction: row; - right: var(--bui-space-1); - top: 50%; - transform: translateY(-50%); - color: var(--bui-fg-primary); - flex-shrink: 0; - /* To animate the icon when the input is collapsed */ - transition: right 0.2s ease-in-out; - - &[data-size='small'], - &[data-size='small'] svg { - width: 1rem; - height: 1rem; - } - - &[data-size='medium'], - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; - } -} - -.bui-InputVisibility { - background-color: transparent; - cursor: pointer; - border: none; - padding: 0; - margin: 0; - display: flex; - align-items: center; - justify-content: center; - color: var(--bui-fg-primary); - - /* Size: small */ - &[data-size="small"] { width: 2rem; height: 2rem; } - &[data-size="small"] svg { width: 1rem; height: 1rem; } - - /* Size: medium */ - &[data-size="medium"] { width: 2.5rem; height: 2.5rem; } - &[data-size="medium"] svg { width: 1.25rem; height: 1.25rem; } -} - -/* Ensure input has enough right padding for our toggle + PM icon */ -.bui-PasswordField .bui-InputWrapper[data-size='small'] .bui-Input { - padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); -} - -.bui-PasswordField .bui-InputWrapper[data-size='medium'] .bui-Input { - padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); -} - .bui-InputIcon { left: var(--bui-space-3); margin-right: var(--bui-space-1); @@ -10586,6 +10522,59 @@ } } +.bui-PasswordField { + font-family: var(--bui-font-regular); + --bui-passwordmanager-icon-width: var(--bui-space-1); + flex-direction: column; + flex-shrink: 0; + width: 100%; + display: flex; +} + +.bui-InputVisibility { + right: var(--bui-passwordmanager-icon-width); + cursor: pointer; + color: var(--bui-fg-primary); + background-color: #0000; + border: none; + justify-content: center; + align-items: center; + margin: 0; + padding: 0; + display: flex; + position: absolute; + top: 0; + bottom: 0; + + &[data-size="small"] { + width: 2rem; + height: 2rem; + } + + &[data-size="small"] svg { + width: 1rem; + height: 1rem; + } + + &[data-size="medium"] { + width: 2.5rem; + height: 2.5rem; + } + + &[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; + } +} + +.bui-PasswordField .bui-InputWrapper[data-size="small"] .bui-Input { + padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); +} + +.bui-PasswordField .bui-InputWrapper[data-size="medium"] .bui-Input { + padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); +} + .bui-SearchField { flex: 1 0; From 82540078e800ebeb26d6d0f751b67019ee682b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Mon, 29 Sep 2025 10:00:18 +0200 Subject: [PATCH 053/244] chore: update package.json MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b510a5a864..babce203dd 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,7 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@yarnpkg/plugin-npm@npm:^3.1.0": "patch:@yarnpkg/plugin-npm@npm%3A3.1.0#~/.yarn/patches/@yarnpkg-plugin-npm-npm-3.1.0-6533d0f5a1.patch", + "GendocuPublicApis": "npm:gendocu-public-apis@^1.0.0", "ast-types@0.14.2": "patch:ast-types@npm%3A0.14.2#./.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch", "ast-types@^0.14.1": "patch:ast-types@npm%3A0.14.2#./.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch", "ast-types@npm:0.14.2": "patch:ast-types@npm%3A0.16.1#./.yarn/patches/ast-types-npm-0.16.1-43c4ac4b0d.patch", From f2cf56451897fd398a47c11a9c303c41e5a55ef3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 29 Sep 2025 13:53:28 +0200 Subject: [PATCH 054/244] cli: remove jest script module cache Signed-off-by: Patrik Oldsberg --- .changeset/full-chefs-roll.md | 5 +++++ packages/cli/config/jestCachingModuleLoader.js | 17 ----------------- 2 files changed, 5 insertions(+), 17 deletions(-) create mode 100644 .changeset/full-chefs-roll.md diff --git a/.changeset/full-chefs-roll.md b/.changeset/full-chefs-roll.md new file mode 100644 index 0000000000..2eaa8b8026 --- /dev/null +++ b/.changeset/full-chefs-roll.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Removed the script transform cache from the default Jest configuration. The script cache provided a moderate performance boost, but it is incomatible with Jest 30. diff --git a/packages/cli/config/jestCachingModuleLoader.js b/packages/cli/config/jestCachingModuleLoader.js index b2b6a4f8ae..a3fdf106e9 100644 --- a/packages/cli/config/jestCachingModuleLoader.js +++ b/packages/cli/config/jestCachingModuleLoader.js @@ -16,29 +16,12 @@ const { default: JestRuntime } = require('jest-runtime'); -const scriptTransformCache = new Map(); - module.exports = class CachingJestRuntime extends JestRuntime { constructor(config, ...restArgs) { super(config, ...restArgs); this.allowLoadAsEsm = config.extensionsToTreatAsEsm.includes('.mts'); } - // This may or may not be a good idea. Theoretically I don't know why this would impact - // test correctness and flakiness, but it seems like it may introduce flakiness and strange failures. - // It does seem to speed up test execution by a fair amount though. - createScriptFromCode(scriptSource, filename) { - let script = scriptTransformCache.get(scriptSource); - if (!script) { - script = super.createScriptFromCode(scriptSource, filename); - // Tried to store the script object in a WeakRef here. It starts out at - // about 90% hit rate, but eventually drops all the way to 20%, and overall - // it seemed to increase memory usage by 20% or so. - scriptTransformCache.set(scriptSource, script); - } - return script; - } - // Unfortunately we need to use this unstable API to make sure that .js files // are only loaded as modules where ESM is supported, i.e. Node.js packages. unstable_shouldLoadAsEsm(path, ...restArgs) { From 032a19f3fbe1405e0e4c46f8a824d99a0917b826 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 30 Sep 2025 09:34:03 +0200 Subject: [PATCH 055/244] Fix typo in changeset for coreExtensionData.title Signed-off-by: Patrik Oldsberg --- .changeset/nasty-moose-rescue.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/nasty-moose-rescue.md b/.changeset/nasty-moose-rescue.md index ff8cf1b02c..875c19e9a4 100644 --- a/.changeset/nasty-moose-rescue.md +++ b/.changeset/nasty-moose-rescue.md @@ -2,4 +2,4 @@ '@backstage/frontend-plugin-api': patch --- -Added `coreExtensionData.title`, especially useful for creating extensible layout with tabbed pages, but availble for use for other cases too. +Added `coreExtensionData.title`, especially useful for creating extensible layout with tabbed pages, but available for use for other cases too. From 90496fe4727593f070384fb2741ac26a0f0422f2 Mon Sep 17 00:00:00 2001 From: Tommy Le Date: Tue, 30 Sep 2025 17:10:30 +0200 Subject: [PATCH 056/244] fix: forward disabled prop Signed-off-by: Tommy Le --- .../components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx index 0651066cfb..2e93c8b71d 100644 --- a/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx +++ b/plugins/scaffolder/src/components/fields/OwnedEntityPicker/OwnedEntityPicker.tsx @@ -115,6 +115,7 @@ function buildEntityPickerUISchema( ...extraOptions, catalogFilter, }, + 'ui:disabled': uiSchema['ui:disabled'], }; } From d9aed7400c5ac6f383b1384ea8a43cc80341e7dd Mon Sep 17 00:00:00 2001 From: Tommy Le Date: Tue, 30 Sep 2025 17:11:22 +0200 Subject: [PATCH 057/244] chore: add changeset Signed-off-by: Tommy Le --- .changeset/tidy-coats-know.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tidy-coats-know.md diff --git a/.changeset/tidy-coats-know.md b/.changeset/tidy-coats-know.md new file mode 100644 index 0000000000..e641c12784 --- /dev/null +++ b/.changeset/tidy-coats-know.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Forward `ui:disabled` in `OwnedEntityPicker` to allow disabling it From ace202e4d1fec11032895d8373a1d0dc0392bd2b Mon Sep 17 00:00:00 2001 From: punkle Date: Fri, 3 Oct 2025 11:56:15 +0100 Subject: [PATCH 058/244] chore: update material-ui-popup-state Signed-off-by: punkle --- .changeset/solid-pianos-cry.md | 5 ++++ plugins/catalog-react/package.json | 2 +- yarn.lock | 42 ++++++++++++------------------ 3 files changed, 23 insertions(+), 26 deletions(-) create mode 100644 .changeset/solid-pianos-cry.md diff --git a/.changeset/solid-pianos-cry.md b/.changeset/solid-pianos-cry.md new file mode 100644 index 0000000000..8e7db678fb --- /dev/null +++ b/.changeset/solid-pianos-cry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Update `material-ui-popup-state` to latest available version. diff --git a/plugins/catalog-react/package.json b/plugins/catalog-react/package.json index cb55343b0a..cb85e3d9fa 100644 --- a/plugins/catalog-react/package.json +++ b/plugins/catalog-react/package.json @@ -81,7 +81,7 @@ "@react-hookz/web": "^24.0.0", "classnames": "^2.2.6", "lodash": "^4.17.21", - "material-ui-popup-state": "^1.9.3", + "material-ui-popup-state": "^5.3.6", "qs": "^6.9.4", "react-use": "^17.2.4", "yaml": "^2.0.0", diff --git a/yarn.lock b/yarn.lock index c1a352407c..cc38fd4415 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2428,10 +2428,10 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.26.10, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": - version: 7.28.2 - resolution: "@babel/runtime@npm:7.28.2" - checksum: 10/a0965fbdd6aaa40709290923bbe05e1c4314021f0cef608eb1d69f04f717c41829e50a53d79c4a0f461512b4be9b3c0190dc19387b219bcdaacdd793b2fe1b8a +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.20.6, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.26.10, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.4.4, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.0, @babel/runtime@npm:^7.7.6, @babel/runtime@npm:^7.8.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2": + version: 7.28.4 + resolution: "@babel/runtime@npm:7.28.4" + checksum: 10/6c9a70452322ea80b3c9b2a412bcf60771819213a67576c8cec41e88a95bb7bf01fc983754cda35dc19603eef52df22203ccbf7777b9d6316932f9fb77c25163 languageName: node linkType: hard @@ -4943,7 +4943,7 @@ __metadata: "@types/zen-observable": "npm:^0.8.0" classnames: "npm:^2.2.6" lodash: "npm:^4.17.21" - material-ui-popup-state: "npm:^1.9.3" + material-ui-popup-state: "npm:^5.3.6" qs: "npm:^6.9.4" react: "npm:^18.0.2" react-dom: "npm:^18.0.2" @@ -10626,18 +10626,6 @@ __metadata: languageName: node linkType: hard -"@material-ui/types@npm:^6.0.1": - version: 6.0.2 - resolution: "@material-ui/types@npm:6.0.2" - peerDependencies: - "@types/react": "*" - peerDependenciesMeta: - "@types/react": - optional: true - checksum: 10/cfdc412efcf471924a058e76601a2dcbf20924db3df34093b9329983172653f22d46fbaf9ae767a26eb9ed060f8e19571829329019019441f6801e1aae4cfdb4 - languageName: node - linkType: hard - "@material-ui/utils@npm:^4.11.3": version: 4.11.3 resolution: "@material-ui/utils@npm:4.11.3" @@ -36905,18 +36893,22 @@ __metadata: languageName: node linkType: hard -"material-ui-popup-state@npm:^1.9.3": - version: 1.9.3 - resolution: "material-ui-popup-state@npm:1.9.3" +"material-ui-popup-state@npm:^5.3.6": + version: 5.3.6 + resolution: "material-ui-popup-state@npm:5.3.6" dependencies: - "@babel/runtime": "npm:^7.12.5" - "@material-ui/types": "npm:^6.0.1" + "@babel/runtime": "npm:^7.26.0" + "@types/prop-types": "npm:^15.7.3" classnames: "npm:^2.2.6" prop-types: "npm:^15.7.2" peerDependencies: - "@material-ui/core": ^4.0.0 || ^5.0.0-beta - react: ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 10/9b0bb7bdcf257e1bf868cb2e74e2d80208fb870ab8e29229c49a0b64f1c1cb5c8b7ba78e89fb81019c2109729d25473188d79bf99f889c8ee698020f2013d578 + "@mui/material": ^5.0.0 || ^6.0.0 || ^7.0.0 + "@types/react": ^16.8.0 || ^17 || ^18 || ^19 + react: ^16.8.0 || ^17 || ^18 || ^19 + peerDependenciesMeta: + "@types/react": + optional: true + checksum: 10/0edb01e329b694517656833a4d923bdb25ab3454c3027dbbb2a32d3f264aa5ae9b174756a83d08dcc981a77775426004b5b3766bbf330fd4df2075c810d7aa9e languageName: node linkType: hard From c017220e7780f1a373d5da811a1941aaaf9b8d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Fri, 3 Oct 2025 13:25:53 +0200 Subject: [PATCH 059/244] Update .changeset/fuzzy-trams-kick.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/fuzzy-trams-kick.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/fuzzy-trams-kick.md b/.changeset/fuzzy-trams-kick.md index 71c06891d0..b433eac803 100644 --- a/.changeset/fuzzy-trams-kick.md +++ b/.changeset/fuzzy-trams-kick.md @@ -2,4 +2,4 @@ '@backstage/plugin-home': patch --- -fix(home): correct clearAll logic to properly handle deletable flag +fix(home): correct `clearAll` logic to properly handle `deletable` flag From d95d88cd23118f414017e4fb971b5d4e021bcdb8 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Fri, 3 Oct 2025 15:36:57 +0200 Subject: [PATCH 060/244] app: fix routing when PageExtensions are mounted on / Signed-off-by: Vincenzo Scamporlino --- plugins/app/src/extensions/AppRoutes.tsx | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/plugins/app/src/extensions/AppRoutes.tsx b/plugins/app/src/extensions/AppRoutes.tsx index 5cc3c3f4b8..ddd7962004 100644 --- a/plugins/app/src/extensions/AppRoutes.tsx +++ b/plugins/app/src/extensions/AppRoutes.tsx @@ -36,12 +36,18 @@ export const AppRoutes = createExtension({ factory({ inputs }) { const Routes = () => { const element = useRoutes([ - ...inputs.routes.map(route => ({ - path: `${route - .get(coreExtensionData.routePath) - .replace(/\/$/, '')}/*`, - element: route.get(coreExtensionData.reactElement), - })), + ...inputs.routes.map(route => { + const routePath = route.get(coreExtensionData.routePath); + + return { + path: + routePath === '/' + ? routePath + : `${routePath.replace(/\/$/, '')}/*`, + + element: route.get(coreExtensionData.reactElement), + }; + }), { path: '*', element: , From 5c21e451a733de3ff06a050622eefb385efdb47c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Fri, 3 Oct 2025 15:52:46 +0200 Subject: [PATCH 061/244] add changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .changeset/sad-women-rule.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/sad-women-rule.md diff --git a/.changeset/sad-women-rule.md b/.changeset/sad-women-rule.md new file mode 100644 index 0000000000..caed5bea87 --- /dev/null +++ b/.changeset/sad-women-rule.md @@ -0,0 +1,6 @@ +--- +'example-app': patch +'@backstage/ui': patch +--- + +Add react router for internal routing for ButtonLinks From 5f75636f858c9a4e122a00f3fb639c4914d92baa Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 3 Oct 2025 15:59:21 +0200 Subject: [PATCH 062/244] Update verify_chromatic.yml Signed-off-by: Charles de Dreuille --- .github/workflows/verify_chromatic.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/verify_chromatic.yml b/.github/workflows/verify_chromatic.yml index 0c9f110b4c..18511b936d 100644 --- a/.github/workflows/verify_chromatic.yml +++ b/.github/workflows/verify_chromatic.yml @@ -5,7 +5,7 @@ on: push: branches: - master - pull_request: + pull_request_target: paths: - '.github/workflows/verify_chromatic.yml' - '.storybook/**' @@ -31,6 +31,8 @@ jobs: - name: Checkout code uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: + # For pull_request_target, we need to check out the PR branch + ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }} fetch-depth: 10000 # Required to retrieve git history - name: Use node.js ${{ matrix.node-version }} @@ -63,7 +65,7 @@ jobs: packages/ui/src/**/*.css - name: Prepare Chromatic Message - if: github.event_name == 'pull_request' && steps.chromatic.outputs.url + if: github.event_name == 'pull_request_target' && steps.chromatic.outputs.url id: prepare-message run: | if [ "${{ steps.chromatic.outputs.changeCount }}" = "0" ] || [ -z "${{ steps.chromatic.outputs.changeCount }}" ]; then @@ -73,7 +75,7 @@ jobs: fi - name: Post Chromatic Link in PR Comment - if: github.event_name == 'pull_request' && steps.chromatic.outputs.url + if: github.event_name == 'pull_request_target' && steps.chromatic.outputs.url uses: mshick/add-pr-comment@v2 with: message: | From 722182fa90fb84834cedd298a80a41edb32e0dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Fri, 3 Oct 2025 16:28:19 +0200 Subject: [PATCH 063/244] fix changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .changeset/sad-women-rule.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/sad-women-rule.md b/.changeset/sad-women-rule.md index caed5bea87..04bbbe1eed 100644 --- a/.changeset/sad-women-rule.md +++ b/.changeset/sad-women-rule.md @@ -1,5 +1,4 @@ --- -'example-app': patch '@backstage/ui': patch --- From 97818157bba7038533d9805f16ad38ab47a1887b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Fri, 3 Oct 2025 16:39:03 +0200 Subject: [PATCH 064/244] add changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .changeset/thin-hoops-bathe.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/thin-hoops-bathe.md diff --git a/.changeset/thin-hoops-bathe.md b/.changeset/thin-hoops-bathe.md new file mode 100644 index 0000000000..508d548431 --- /dev/null +++ b/.changeset/thin-hoops-bathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Remove auto selection of tabs for tabs that all have href defined From edc15d8cd738bf9479dd382f9325ea1fe4b654b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Fri, 3 Oct 2025 16:50:39 +0200 Subject: [PATCH 065/244] Revert "chore: update package.json" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 82540078e800ebeb26d6d0f751b67019ee682b07. Signed-off-by: Sofia Sjöblad --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index babce203dd..b510a5a864 100644 --- a/package.json +++ b/package.json @@ -105,7 +105,6 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@yarnpkg/plugin-npm@npm:^3.1.0": "patch:@yarnpkg/plugin-npm@npm%3A3.1.0#~/.yarn/patches/@yarnpkg-plugin-npm-npm-3.1.0-6533d0f5a1.patch", - "GendocuPublicApis": "npm:gendocu-public-apis@^1.0.0", "ast-types@0.14.2": "patch:ast-types@npm%3A0.14.2#./.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch", "ast-types@^0.14.1": "patch:ast-types@npm%3A0.14.2#./.yarn/patches/ast-types-npm-0.14.2-43c4ac4b0d.patch", "ast-types@npm:0.14.2": "patch:ast-types@npm%3A0.16.1#./.yarn/patches/ast-types-npm-0.16.1-43c4ac4b0d.patch", From 28ee81c7178f0b62c132ce8034001e81f51edd0e Mon Sep 17 00:00:00 2001 From: Gabriel Dugny Date: Sat, 4 Oct 2025 12:24:38 +0200 Subject: [PATCH 066/244] fix: Invalid MUI to BUI conversion for --bui-bg Signed-off-by: Gabriel Dugny --- .changeset/legal-hounds-think.md | 5 +++++ .../components/BuiThemerPage/convertMuiToBuiTheme.test.ts | 2 ++ .../src/components/BuiThemerPage/convertMuiToBuiTheme.ts | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .changeset/legal-hounds-think.md diff --git a/.changeset/legal-hounds-think.md b/.changeset/legal-hounds-think.md new file mode 100644 index 0000000000..c7c9e87948 --- /dev/null +++ b/.changeset/legal-hounds-think.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-mui-to-bui': patch +--- + +Fix invalid conversion for `--bui-bg` variable diff --git a/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.test.ts b/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.test.ts index 74f4bfa777..6ba3f7d2d9 100644 --- a/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.test.ts +++ b/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.test.ts @@ -59,6 +59,7 @@ describe('convertMuiToBuiTheme', () => { // Border radius tokens are only generated when radius is 0 expect(result.css).not.toContain('--bui-radius-3:'); // Background default maps to surface-2 + expect(result.css).toContain('--bui-bg: #f5f5f5;'); expect(result.css).toContain('--bui-bg-surface-2: #f5f5f5;'); expect(result.css).toContain('--bui-bg-surface-1: #ffffff;'); expect(result.css).toContain('--bui-fg-primary: #000000;'); @@ -97,6 +98,7 @@ describe('convertMuiToBuiTheme', () => { expect(result.css).toContain("[data-theme-mode='dark'] {"); // Background default maps to surface-2 in dark mode as well + expect(result.css).toContain('--bui-bg: #121212;'); expect(result.css).toContain('--bui-bg-surface-2: #121212;'); expect(result.css).toContain('--bui-bg-surface-1: #1e1e1e;'); expect(result.css).toContain('--bui-fg-primary: #ffffff;'); diff --git a/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.ts b/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.ts index 11877bb564..1b8528922b 100644 --- a/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.ts +++ b/plugins/mui-to-bui/src/components/BuiThemerPage/convertMuiToBuiTheme.ts @@ -125,7 +125,7 @@ function generateBuiVariables(theme: Mui5Theme): Record { warning: palette.warning.light, success: palette.success.light, }).forEach(([key, value]) => { - styleObject[`--bui-bg-${key}`] = value; + styleObject[`--bui-bg${key ? `-${key}` : ''}`] = value; }); // Border colors @@ -134,7 +134,7 @@ function generateBuiVariables(theme: Mui5Theme): Record { warning: palette.warning.main, success: palette.success.main, }).forEach(([key, value]) => { - styleObject[`--bui-border${key ? `-${key}` : ''}`] = value; + styleObject[`--bui-border-${key}`] = value; }); // Base border color if available From 67cf9829946b301952ec74a467578b71364e285b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Mon, 6 Oct 2025 10:54:20 +0200 Subject: [PATCH 067/244] fix: update stories to comply with react-aria MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../HeaderPage/HeaderPage.stories.tsx | 32 +++++++++++++---- .../ui/src/components/Tabs/Tabs.stories.tsx | 36 ++++++++++++++++--- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx index c4849ddc20..c3c2b59ae1 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx @@ -44,22 +44,27 @@ const tabs: HeaderTab[] = [ { id: 'overview', label: 'Overview', + href: '/overview', }, { id: 'checks', label: 'Checks', + href: '/checks', }, { id: 'tracks', label: 'Tracks', + href: '/tracks', }, { id: 'campaigns', label: 'Campaigns', + href: '/campaigns', }, { id: 'integrations', label: 'Integrations', + href: '/integrations', }, ]; @@ -89,10 +94,19 @@ const withRouter = (Story: StoryFn) => ( ); +// White background decorator for stories +const withWhiteBackground = (Story: StoryFn) => ( +
+ +
+); + // Extract layout decorator as a reusable constant const layoutDecorator = [ (Story: StoryFn) => ( - <> +
- +
), ]; @@ -129,6 +143,7 @@ export const Default: Story = { args: { title: 'Page Title', }, + decorators: [withWhiteBackground], }; export const WithTabs: Story = { @@ -136,11 +151,11 @@ export const WithTabs: Story = { ...Default.args, tabs, }, - decorators: [withRouter], + decorators: [withRouter, withWhiteBackground], }; export const WithCustomActions: Story = { - decorators: [withRouter], + decorators: [withRouter, withWhiteBackground], render: () => ( ( ( ); +// White background decorator for stories +const withWhiteBackground = (Story: StoryFn) => ( +
+ +
+); + export const Default: Story = { args: { children: '', }, - decorators: [withRouter], + decorators: [withRouter, withWhiteBackground], render: () => ( - Tab 1 - Tab 2 - Tab 3 With long title + + Tab 1 + + + Tab 2 + + + Tab 3 With long title + ), @@ -54,7 +69,7 @@ export const WithTabPanels: Story = { args: { children: '', }, - decorators: [withRouter], + decorators: [withRouter, withWhiteBackground], render: () => ( @@ -79,6 +94,7 @@ export const WithMockedURLTab2: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -111,6 +127,7 @@ export const WithMockedURLTab3: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -143,6 +160,7 @@ export const WithMockedURLNoMatch: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -181,6 +199,7 @@ export const ExactMatchingDefault: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -217,6 +236,7 @@ export const PrefixMatchingForNestedRoutes: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -257,6 +277,7 @@ export const PrefixMatchingDeepNesting: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -292,6 +313,7 @@ export const MixedMatchingStrategies: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -343,6 +365,7 @@ export const PrefixMatchingEdgeCases: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -385,6 +408,7 @@ export const PrefixMatchingWithSlash: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -426,6 +450,7 @@ export const RootPathMatching: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => ( @@ -460,6 +485,7 @@ export const AutoSelectionOfTabs: Story = { args: { children: '', }, + decorators: [withWhiteBackground], render: () => (
From 23d8df0ce0534026e5e913576724faa68f74a4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Mon, 6 Oct 2025 11:31:35 +0200 Subject: [PATCH 068/244] fix: add react-aria label to button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../ui/src/components/HeaderPage/HeaderPage.stories.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx index c3c2b59ae1..bba6e8a857 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx @@ -163,7 +163,11 @@ export const WithCustomActions: Story = { <> - } /> + } + aria-label="More options" + /> {menuItems.map(option => ( Date: Mon, 6 Oct 2025 11:32:59 +0200 Subject: [PATCH 069/244] Get rid of visualizer "missing key" errors in browser console MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/two-emus-like.md | 5 +++++ .../src/components/AppVisualizerPage/TextVisualizer.tsx | 8 ++++---- 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/two-emus-like.md diff --git a/.changeset/two-emus-like.md b/.changeset/two-emus-like.md new file mode 100644 index 0000000000..e8af7a7fa0 --- /dev/null +++ b/.changeset/two-emus-like.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-app-visualizer': patch +--- + +Ensure that the text rendering has react keys for all elements diff --git a/plugins/app-visualizer/src/components/AppVisualizerPage/TextVisualizer.tsx b/plugins/app-visualizer/src/components/AppVisualizerPage/TextVisualizer.tsx index b388da80b4..4385ba0938 100644 --- a/plugins/app-visualizer/src/components/AppVisualizerPage/TextVisualizer.tsx +++ b/plugins/app-visualizer/src/components/AppVisualizerPage/TextVisualizer.tsx @@ -63,15 +63,15 @@ function nodeToText( .filter(e => options?.showDisabled || e.instance) .sort((a, b) => a.spec.id.localeCompare(b.spec.id)); if (children.length === 0) { - return mkDiv(`${key} []`, { indent: true }); + return mkDiv(`${key} []`, { key, indent: true }); } return mkDiv( [ - mkDiv(`${key} [`), + mkDiv(`${key} [`, { key: 'start' }), ...children.map(e => - mkDiv(nodeToText(e, options), { indent: true }), + mkDiv(nodeToText(e, options), { indent: true, key: e.spec.id }), ), - mkDiv(']'), + mkDiv(']', { key: 'end' }), ], { key, indent: true }, ); From 09a14e809f0fd1dce66842f2ce58239338d2dcc4 Mon Sep 17 00:00:00 2001 From: TA31OU Date: Thu, 18 Sep 2025 09:03:50 +0200 Subject: [PATCH 070/244] Clean up type Signed-off-by: TA31OU --- .../src/components/DependencyGraph/types.ts | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/packages/core-components/src/components/DependencyGraph/types.ts b/packages/core-components/src/components/DependencyGraph/types.ts index 2629d9fda1..d3e51db85b 100644 --- a/packages/core-components/src/components/DependencyGraph/types.ts +++ b/packages/core-components/src/components/DependencyGraph/types.ts @@ -99,17 +99,7 @@ export namespace DependencyGraphTypes { * * @public */ - export type RenderEdgeProps = { - edge: DependencyEdge; - id: dagre.Edge; - }; - - /** - * Custom React component for graph {@link DependencyGraphTypes.DependencyEdge} - * - * @public - */ - export type RenderEdgeFunction = (props: { + export type RenderEdgeProps = { edge: T & { points: { x: number; y: number }[]; label?: string; @@ -124,8 +114,17 @@ export namespace DependencyGraphTypes { to?: string; relations?: string[]; }; - id: { v: string; w: string }; - }) => ReactNode; + id: dagre.Edge; + }; + + /** + * Custom React component for graph {@link DependencyGraphTypes.DependencyEdge} + * + * @public + */ + export type RenderEdgeFunction = ( + props: RenderEdgeProps, + ) => ReactNode; /** * Graph direction From 1c25050ee974d15707f4ef55939eb2ed638455b4 Mon Sep 17 00:00:00 2001 From: TA31OU Date: Thu, 18 Sep 2025 09:42:42 +0200 Subject: [PATCH 071/244] undo package change Signed-off-by: TA31OU --- plugins/catalog-graph/package.json | 2 -- yarn.lock | 2 -- 2 files changed, 4 deletions(-) diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index 57d6f7544a..86bd930095 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -61,7 +61,6 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.61", "classnames": "^2.3.1", - "d3-shape": "^3.0.0", "lodash": "^4.17.15", "p-limit": "^3.1.0", "qs": "^6.9.4", @@ -77,7 +76,6 @@ "@testing-library/jest-dom": "^6.0.0", "@testing-library/react": "^16.0.0", "@testing-library/user-event": "^14.0.0", - "@types/d3-shape": "^3.0.1", "@types/react": "^18.0.0", "react": "^18.0.2", "react-dom": "^18.0.2", diff --git a/yarn.lock b/yarn.lock index 8c8cf7fe00..e606b8246d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4820,10 +4820,8 @@ __metadata: "@testing-library/jest-dom": "npm:^6.0.0" "@testing-library/react": "npm:^16.0.0" "@testing-library/user-event": "npm:^14.0.0" - "@types/d3-shape": "npm:^3.0.1" "@types/react": "npm:^18.0.0" classnames: "npm:^2.3.1" - d3-shape: "npm:^3.0.0" lodash: "npm:^4.17.15" p-limit: "npm:^3.1.0" qs: "npm:^6.9.4" From 3beb1dee934863a25ce90841526a4b9115a31e14 Mon Sep 17 00:00:00 2001 From: TA31OU Date: Thu, 18 Sep 2025 13:43:57 +0200 Subject: [PATCH 072/244] update api report Signed-off-by: TA31OU --- packages/core-components/report.api.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/core-components/report.api.md b/packages/core-components/report.api.md index c363ae9d56..97eb7d9761 100644 --- a/packages/core-components/report.api.md +++ b/packages/core-components/report.api.md @@ -318,7 +318,10 @@ export namespace DependencyGraphTypes { NETWORK_SIMPLEX = 'network-simplex', TIGHT_TREE = 'tight-tree', } - export type RenderEdgeFunction = (props: { + export type RenderEdgeFunction = ( + props: RenderEdgeProps, + ) => ReactNode; + export type RenderEdgeProps = { edge: T & { points: { x: number; @@ -336,13 +339,6 @@ export namespace DependencyGraphTypes { to?: string; relations?: string[]; }; - id: { - v: string; - w: string; - }; - }) => ReactNode; - export type RenderEdgeProps = { - edge: DependencyEdge; id: dagre.Edge; }; export type RenderLabelFunction = ( From 25aec46a8b0d63e9755170fa364a9cc144a8a07b Mon Sep 17 00:00:00 2001 From: TA31OU Date: Mon, 6 Oct 2025 11:26:23 +0200 Subject: [PATCH 073/244] Remove edge import Signed-off-by: TA31OU --- .../src/components/DependencyGraph/types.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/core-components/src/components/DependencyGraph/types.ts b/packages/core-components/src/components/DependencyGraph/types.ts index d3e51db85b..4436f8d1aa 100644 --- a/packages/core-components/src/components/DependencyGraph/types.ts +++ b/packages/core-components/src/components/DependencyGraph/types.ts @@ -21,7 +21,6 @@ */ import { ReactNode } from 'react'; -import dagre from '@dagrejs/dagre'; /** * Types for the {@link DependencyGraph} component. @@ -114,7 +113,11 @@ export namespace DependencyGraphTypes { to?: string; relations?: string[]; }; - id: dagre.Edge; + id: { + v: string; + w: string; + name?: string | undefined; + }; }; /** From 57e279d780ca06132994fdbc17dca74ac4b530f6 Mon Sep 17 00:00:00 2001 From: MrOpperman Date: Wed, 24 Sep 2025 09:32:39 +0200 Subject: [PATCH 074/244] Update .changeset/flat-peas-run.md Co-authored-by: Ben Lambert Signed-off-by: MrOpperman Signed-off-by: TA31OU --- .changeset/flat-peas-run.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.changeset/flat-peas-run.md b/.changeset/flat-peas-run.md index c09eadecf8..64d80107ba 100644 --- a/.changeset/flat-peas-run.md +++ b/.changeset/flat-peas-run.md @@ -1,6 +1,6 @@ --- -'@backstage/core-components': minor -'@backstage/plugin-catalog-graph': minor +'@backstage/core-components': patch +'@backstage/plugin-catalog-graph': patch --- Added `renderEdge` prop to component in @backstage/core-components to allow custom rendering of graph edges. From f9946a3edfdc1d23929be4888fb4473b66b93740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 6 Oct 2025 10:53:49 +0200 Subject: [PATCH 075/244] Update .changeset/flat-peas-run.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw Signed-off-by: TA31OU --- .changeset/flat-peas-run.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/flat-peas-run.md b/.changeset/flat-peas-run.md index 64d80107ba..bb075ce910 100644 --- a/.changeset/flat-peas-run.md +++ b/.changeset/flat-peas-run.md @@ -3,4 +3,4 @@ '@backstage/plugin-catalog-graph': patch --- -Added `renderEdge` prop to component in @backstage/core-components to allow custom rendering of graph edges. +Added `renderEdge` prop to `` component in `@backstage/core-components` to allow custom rendering of graph edges. From 81fc26c6a4eaab95ea77dc5b611dff7dd6f71758 Mon Sep 17 00:00:00 2001 From: TA31OU Date: Mon, 6 Oct 2025 11:48:32 +0200 Subject: [PATCH 076/244] Update api report Signed-off-by: TA31OU --- packages/core-components/report.api.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/core-components/report.api.md b/packages/core-components/report.api.md index 97eb7d9761..9c9992deff 100644 --- a/packages/core-components/report.api.md +++ b/packages/core-components/report.api.md @@ -18,7 +18,6 @@ import { ComponentType } from 'react'; import { Context } from 'react'; import { default as CSS_2 } from 'csstype'; import { CSSProperties } from 'react'; -import dagre from '@dagrejs/dagre'; import { ElementType } from 'react'; import { ErrorInfo } from 'react'; import IconButton from '@material-ui/core/IconButton'; @@ -339,7 +338,11 @@ export namespace DependencyGraphTypes { to?: string; relations?: string[]; }; - id: dagre.Edge; + id: { + v: string; + w: string; + name?: string | undefined; + }; }; export type RenderLabelFunction = ( props: RenderLabelProps, @@ -1575,8 +1578,8 @@ export type WarningPanelClassKey = // Warnings were encountered during analysis: // -// src/components/DependencyGraph/types.d.ts:23:9 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode" -// src/components/DependencyGraph/types.d.ts:27:9 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode" +// src/components/DependencyGraph/types.d.ts:22:9 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode" +// src/components/DependencyGraph/types.d.ts:26:9 - (ae-unresolved-link) The @link reference could not be resolved: The package "@backstage/core-components" does not have an export "DependencyNode" // src/components/TabbedLayout/RoutedTabs.d.ts:8:5 - (ae-forgotten-export) The symbol "SubRoute_2" needs to be exported by the entry point index.d.ts // src/components/Table/Table.d.ts:20:5 - (ae-forgotten-export) The symbol "SelectedFilters" needs to be exported by the entry point index.d.ts // src/layout/ErrorBoundary/ErrorBoundary.d.ts:8:5 - (ae-forgotten-export) The symbol "SlackChannel" needs to be exported by the entry point index.d.ts From dd69cf60c4b211b8df9cbec7cdd8f57d15d0aa16 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Mon, 6 Oct 2025 13:21:35 +0200 Subject: [PATCH 077/244] backend-app-api: earlier handling or unhandled errors Signed-off-by: Patrik Oldsberg --- .changeset/cuddly-mugs-act.md | 5 +++ .../src/wiring/BackendInitializer.ts | 43 +++++++++++-------- 2 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 .changeset/cuddly-mugs-act.md diff --git a/.changeset/cuddly-mugs-act.md b/.changeset/cuddly-mugs-act.md new file mode 100644 index 0000000000..1b939d8196 --- /dev/null +++ b/.changeset/cuddly-mugs-act.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Moved up registration of unhandled rejections and errors listeners to be done as early as possible, avoiding flakiness in backend startups and instead always logging these failures rather than sometimes crashing the process. diff --git a/packages/backend-app-api/src/wiring/BackendInitializer.ts b/packages/backend-app-api/src/wiring/BackendInitializer.ts index 9b925adb30..09b22e3a7a 100644 --- a/packages/backend-app-api/src/wiring/BackendInitializer.ts +++ b/packages/backend-app-api/src/wiring/BackendInitializer.ts @@ -258,6 +258,30 @@ export class BackendInitializer { createInstanceMetadataServiceFactory(this.#registrations), ); + // This makes sure that any uncaught errors or unhandled rejections are + // caught and logged, rather than terminating the process. We register these + // as early as possible while still using the root logger service, the + // tradeoff that if there are any unhandled errors as part of the that + // instationation, it will cause the process to crash. If there are multiple + // backend instances, each instance will log the error, because we can't + // determine which instance the error came from. + if (process.env.NODE_ENV !== 'test') { + const rootLogger = await this.#serviceRegistry.get( + coreServices.rootLogger, + 'root', + ); + process.on('unhandledRejection', (reason: Error) => { + rootLogger + ?.child({ type: 'unhandledRejection' }) + ?.error('Unhandled rejection', reason); + }); + process.on('uncaughtException', error => { + rootLogger + ?.child({ type: 'uncaughtException' }) + ?.error('Uncaught exception', error); + }); + } + // Initialize all root scoped services await this.#serviceRegistry.initializeEagerServicesWithScope('root'); @@ -449,25 +473,6 @@ export class BackendInitializer { await lifecycleService.startup(); initLogger.onAllStarted(); - - // Once the backend is started, any uncaught errors or unhandled rejections are caught - // and logged, in order to avoid crashing the entire backend on local failures. - if (process.env.NODE_ENV !== 'test') { - const rootLogger = await this.#serviceRegistry.get( - coreServices.rootLogger, - 'root', - ); - process.on('unhandledRejection', (reason: Error) => { - rootLogger - ?.child({ type: 'unhandledRejection' }) - ?.error('Unhandled rejection', reason); - }); - process.on('uncaughtException', error => { - rootLogger - ?.child({ type: 'uncaughtException' }) - ?.error('Uncaught exception', error); - }); - } } // It's fine to call .stop() multiple times, which for example can happen with manual stop + process exit From 04530de989224f2b6477a484888b068e03d92286 Mon Sep 17 00:00:00 2001 From: Marley Date: Fri, 26 Sep 2025 08:55:39 +0100 Subject: [PATCH 078/244] Change `target` to `targetRef` in catalog customization Signed-off-by: Marley Powell --- docs/features/software-catalog/catalog-customization.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/features/software-catalog/catalog-customization.md b/docs/features/software-catalog/catalog-customization.md index 2ed4b34822..a828e6591a 100644 --- a/docs/features/software-catalog/catalog-customization.md +++ b/docs/features/software-catalog/catalog-customization.md @@ -693,6 +693,6 @@ filter: relations: $contains: type: ownedBy - target: + targetRef: $in: [group:default/admins, group:default/viewers] ``` From fd23d3ed71cbcf57b93000fee12a7b9ed2e9fa0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Mon, 6 Oct 2025 16:25:39 +0200 Subject: [PATCH 079/244] use react router for internal routing in menus MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- packages/ui/src/components/Menu/Menu.tsx | 46 +++++++++++++++--------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/packages/ui/src/components/Menu/Menu.tsx b/packages/ui/src/components/Menu/Menu.tsx index a55d6fdafb..cea8aa2cb8 100644 --- a/packages/ui/src/components/Menu/Menu.tsx +++ b/packages/ui/src/components/Menu/Menu.tsx @@ -51,8 +51,8 @@ import { RiCheckLine, RiCloseCircleLine, } from '@remixicon/react'; -import { isExternalLink } from '../../utils/isExternalLink'; import { useNavigate, useHref } from 'react-router-dom'; +import { isExternalLink } from '../../utils/isExternalLink'; const MenuEmptyState = () => { const { classNames } = useStyles('Menu'); @@ -74,19 +74,22 @@ export const SubmenuTrigger = (props: SubmenuTriggerProps) => { export const Menu = (props: MenuProps) => { const { placement = 'bottom start', ...rest } = props; const { classNames } = useStyles('Menu'); + const navigate = useNavigate(); return ( - - - - {props.children} - - - - - - + + + + + {props.children} + + + + + + + ); }; @@ -201,7 +204,6 @@ export const MenuAutocompleteListbox = ( export const MenuItem = (props: MenuItemProps) => { const { iconStart, color = 'primary', children, href, ...rest } = props; const { classNames } = useStyles('Menu'); - const navigate = useNavigate(); const isLink = href !== undefined; const isExternal = isExternalLink(href); @@ -224,11 +226,23 @@ export const MenuItem = (props: MenuItemProps) => { ); - if (isLink && !isExternal) { + if (isLink && isExternal) { return ( - - {content} - + window.open(href, '_blank', 'noopener,noreferrer')} + {...rest} + > +
+ {iconStart} + {children} +
+
+ +
+
); } From f6dff5b4de96a6f600004f0741435cf8775a2fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Mon, 6 Oct 2025 16:27:15 +0200 Subject: [PATCH 080/244] add changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .changeset/tough-clocks-attack.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tough-clocks-attack.md diff --git a/.changeset/tough-clocks-attack.md b/.changeset/tough-clocks-attack.md new file mode 100644 index 0000000000..caf3b33fe4 --- /dev/null +++ b/.changeset/tough-clocks-attack.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Using react router for internal links in the Menu component From c49f392f9e1ee1194e91d75dbf6150ece81d8eb9 Mon Sep 17 00:00:00 2001 From: Christine Lee Date: Mon, 6 Oct 2025 10:34:52 -0400 Subject: [PATCH 081/244] add datadog-entity-sync.yaml Signed-off-by: Christine Lee --- microsite/data/plugins/datadog-entity-sync.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 microsite/data/plugins/datadog-entity-sync.yaml diff --git a/microsite/data/plugins/datadog-entity-sync.yaml b/microsite/data/plugins/datadog-entity-sync.yaml new file mode 100644 index 0000000000..2f0cd06cd5 --- /dev/null +++ b/microsite/data/plugins/datadog-entity-sync.yaml @@ -0,0 +1,10 @@ +--- +title: Datadog Entity Sync +author: datadog +authorUrl: https://www.datadoghq.com/ +category: Development +description: Sync entities from the Backstage catalog to the Datadog Software Catalog. +documentation: https://github.com/DataDog/datadog-backstage-plugins/tree/main/plugins/datadog-entity-sync-backend#installation +iconUrl: https://imgix.datadoghq.com/img/about/presskit/logo-v/dd_vertical_purple.png?auto=format&fit=max&w=847&dpr=2 +npmPackageName: '@datadog/backstage-plugin-datadog-entity-sync-backend' +addedDate: '2025-09-19' From f3c9a474004b78da6028517e707c00789f575bf7 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 7 Oct 2025 07:27:01 +0100 Subject: [PATCH 082/244] Small fixes Signed-off-by: Charles de Dreuille --- .github/vale/config/vocabularies/Backstage/accept.txt | 1 + docs-ui/src/app/theming/page.mdx | 2 +- docs/conf/user-interface/index.md | 2 +- docs/dls/component-design-guidelines.md | 4 ---- 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/vale/config/vocabularies/Backstage/accept.txt b/.github/vale/config/vocabularies/Backstage/accept.txt index b0225be547..1497386418 100644 --- a/.github/vale/config/vocabularies/Backstage/accept.txt +++ b/.github/vale/config/vocabularies/Backstage/accept.txt @@ -280,6 +280,7 @@ modularization monorepo Monorepo monorepos +monospace morgan msgraph msw diff --git a/docs-ui/src/app/theming/page.mdx b/docs-ui/src/app/theming/page.mdx index 73275020bc..92b5256791 100644 --- a/docs-ui/src/app/theming/page.mdx +++ b/docs-ui/src/app/theming/page.mdx @@ -226,7 +226,7 @@ color of your app. ### Foreground colors -Foreground colours are meant to work in pair with a background colours. Typeically this would work +Foreground colours are meant to work in pair with a background colours. Typically this would work for icons, texts, shapes, ... Use a matching name to know what foreground color to use. These colors are prefixed with `fg` to make it easier to identify. diff --git a/docs/conf/user-interface/index.md b/docs/conf/user-interface/index.md index aeae086b59..81acfdf720 100644 --- a/docs/conf/user-interface/index.md +++ b/docs/conf/user-interface/index.md @@ -178,7 +178,7 @@ These colors are used for the background of your application. We are mostly usin #### Foreground colors -Foreground colours are meant to work in pair with a background colours. Typeically this would work for icons, texts, shapes, ... Use a matching name to know what foreground color to use. These colors are prefixed with `fg` to make it easier to identify. +Foreground colours are meant to work in pair with a background colours. Typically this would work for icons, texts, shapes, ... Use a matching name to know what foreground color to use. These colors are prefixed with `fg` to make it easier to identify. | Token Name | Description | | ------------------------ | ----------------------------------------------------------------- | diff --git a/docs/dls/component-design-guidelines.md b/docs/dls/component-design-guidelines.md index 17e9d1f11a..fddffd9fd9 100644 --- a/docs/dls/component-design-guidelines.md +++ b/docs/dls/component-design-guidelines.md @@ -104,7 +104,3 @@ accessibility. [8]: https://v4.mui.com/customization/palette/#default-values [9]: https://v4.mui.com/customization/typography/ [10]: https://backstage.io/docs/conf/user-interface - - - -[12]: https://v4.mui.com/customization/default-theme/#explore From eb9b17d45ee642db519f55d3c68d0d3005d54859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Tue, 7 Oct 2025 09:48:51 +0200 Subject: [PATCH 083/244] Revert "fix: update stories to comply with react-aria" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 67cf9829946b301952ec74a467578b71364e285b. Signed-off-by: Sofia Sjöblad --- .../HeaderPage/HeaderPage.stories.tsx | 32 ++++------------- .../ui/src/components/Tabs/Tabs.stories.tsx | 36 +++---------------- 2 files changed, 12 insertions(+), 56 deletions(-) diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx index bba6e8a857..9e6e63ddf5 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx @@ -44,27 +44,22 @@ const tabs: HeaderTab[] = [ { id: 'overview', label: 'Overview', - href: '/overview', }, { id: 'checks', label: 'Checks', - href: '/checks', }, { id: 'tracks', label: 'Tracks', - href: '/tracks', }, { id: 'campaigns', label: 'Campaigns', - href: '/campaigns', }, { id: 'integrations', label: 'Integrations', - href: '/integrations', }, ]; @@ -94,19 +89,10 @@ const withRouter = (Story: StoryFn) => ( ); -// White background decorator for stories -const withWhiteBackground = (Story: StoryFn) => ( -
- -
-); - // Extract layout decorator as a reusable constant const layoutDecorator = [ (Story: StoryFn) => ( -
+ <>
-
+ ), ]; @@ -143,7 +129,6 @@ export const Default: Story = { args: { title: 'Page Title', }, - decorators: [withWhiteBackground], }; export const WithTabs: Story = { @@ -151,11 +136,11 @@ export const WithTabs: Story = { ...Default.args, tabs, }, - decorators: [withRouter, withWhiteBackground], + decorators: [withRouter], }; export const WithCustomActions: Story = { - decorators: [withRouter, withWhiteBackground], + decorators: [withRouter], render: () => ( ( ( ); -// White background decorator for stories -const withWhiteBackground = (Story: StoryFn) => ( -
- -
-); - export const Default: Story = { args: { children: '', }, - decorators: [withRouter, withWhiteBackground], + decorators: [withRouter], render: () => ( - - Tab 1 - - - Tab 2 - - - Tab 3 With long title - + Tab 1 + Tab 2 + Tab 3 With long title ), @@ -69,7 +54,7 @@ export const WithTabPanels: Story = { args: { children: '', }, - decorators: [withRouter, withWhiteBackground], + decorators: [withRouter], render: () => ( @@ -94,7 +79,6 @@ export const WithMockedURLTab2: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -127,7 +111,6 @@ export const WithMockedURLTab3: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -160,7 +143,6 @@ export const WithMockedURLNoMatch: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -199,7 +181,6 @@ export const ExactMatchingDefault: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -236,7 +217,6 @@ export const PrefixMatchingForNestedRoutes: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -277,7 +257,6 @@ export const PrefixMatchingDeepNesting: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -313,7 +292,6 @@ export const MixedMatchingStrategies: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -365,7 +343,6 @@ export const PrefixMatchingEdgeCases: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -408,7 +385,6 @@ export const PrefixMatchingWithSlash: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -450,7 +426,6 @@ export const RootPathMatching: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => ( @@ -485,7 +460,6 @@ export const AutoSelectionOfTabs: Story = { args: { children: '', }, - decorators: [withWhiteBackground], render: () => (
From ea3970a51d5a4e4c7c802baf8b1a22d41a8365b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Tue, 7 Oct 2025 10:35:01 +0200 Subject: [PATCH 084/244] add mandatory href for tabs in header component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- packages/ui/src/components/Header/types.ts | 2 +- packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/components/Header/types.ts b/packages/ui/src/components/Header/types.ts index 41bc437a18..c7c602abfc 100644 --- a/packages/ui/src/components/Header/types.ts +++ b/packages/ui/src/components/Header/types.ts @@ -39,7 +39,7 @@ export interface HeaderProps { export interface HeaderTab { id: string; label: string; - href?: string; + href: string; /** * Strategy for matching the current route to determine if this tab should be active. * - 'exact': Tab href must exactly match the current pathname (default) diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx index c4849ddc20..385ff0b10d 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx +++ b/packages/ui/src/components/HeaderPage/HeaderPage.stories.tsx @@ -44,22 +44,27 @@ const tabs: HeaderTab[] = [ { id: 'overview', label: 'Overview', + href: '/overview', }, { id: 'checks', label: 'Checks', + href: '/checks', }, { id: 'tracks', label: 'Tracks', + href: '/tracks', }, { id: 'campaigns', label: 'Campaigns', + href: '/campaigns', }, { id: 'integrations', label: 'Integrations', + href: '/integrations', }, ]; From 3c921c551810059dcea2809ae1dc78da72ccfc7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Tue, 7 Oct 2025 10:36:21 +0200 Subject: [PATCH 085/244] add changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .changeset/few-weeks-create.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/few-weeks-create.md diff --git a/.changeset/few-weeks-create.md b/.changeset/few-weeks-create.md new file mode 100644 index 0000000000..c9de7cb4be --- /dev/null +++ b/.changeset/few-weeks-create.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Making href mandatory in tabs that are part of a Header component From 12c929164ca0c9d6004454b56fdec9b58094a602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Tue, 7 Oct 2025 11:12:17 +0200 Subject: [PATCH 086/244] add api report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- packages/ui/report.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 5d04bf8626..f546761837 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -1038,7 +1038,7 @@ export interface HeaderProps { // @public export interface HeaderTab { // (undocumented) - href?: string; + href: string; // (undocumented) id: string; // (undocumented) From a26508eea4dd247df8d5bc3a536b41bc4e71d59c Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 11:43:03 +0200 Subject: [PATCH 087/244] fix renderInTestApp routing Signed-off-by: Vincenzo Scamporlino --- .../src/app/renderInTestApp.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index 80818509da..e1b35eba6c 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -107,6 +107,12 @@ const appPluginOverride = appPlugin.withOverrides({ appPlugin.getExtension('sign-in-page:app').override({ disabled: true, }), + appPlugin.getExtension('app/layout').override({ + disabled: true, + }), + appPlugin.getExtension('app/routes').override({ + disabled: true, + }), appPlugin.getExtension('app/nav').override({ output: [coreExtensionData.reactElement], factory(_originalFactory, { inputs }) { @@ -147,13 +153,10 @@ export function renderInTestApp( ): RenderResult { const extensions: Array = [ createExtension({ - attachTo: { id: 'app/routes', input: 'routes' }, - output: [coreExtensionData.reactElement, coreExtensionData.routePath], + attachTo: { id: 'app/root', input: 'children' }, + output: [coreExtensionData.reactElement], factory: () => { - return [ - coreExtensionData.reactElement(element), - coreExtensionData.routePath('/'), - ]; + return [coreExtensionData.reactElement(element)]; }, }), RouterBlueprint.make({ From 23c72e7e6537dfc972a5b16486cf8d517ddd32bb Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 12:40:12 +0200 Subject: [PATCH 088/244] frontend-test-utils: render the element as Page Signed-off-by: Vincenzo Scamporlino --- .../src/app/renderInTestApp.test.tsx | 35 +++++++++++-------- .../src/app/renderInTestApp.tsx | 21 +++++------ 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx index 8e1b1e1ea0..ae72e6a622 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx @@ -20,15 +20,18 @@ import { MockAnalyticsApi, TestApiProvider, } from '@backstage/frontend-test-utils'; -import { analyticsApiRef, useAnalytics } from '@backstage/frontend-plugin-api'; -import { Routes, Route } from 'react-router-dom'; +import { + analyticsApiRef, + PageBlueprint, + useAnalytics, +} from '@backstage/frontend-plugin-api'; import { renderInTestApp } from './renderInTestApp'; describe('renderInTestApp', () => { it('should render the given component in a page', async () => { const IndexPage = () =>
Index Page
; renderInTestApp(); - expect(screen.getByText('Index Page')).toBeInTheDocument(); + expect(await screen.findByText('Index Page')).toBeInTheDocument(); }); it('should works with apis provider', async () => { @@ -55,7 +58,7 @@ describe('renderInTestApp', () => { , ); - fireEvent.click(screen.getByRole('link', { name: 'See details' })); + fireEvent.click(await screen.findByRole('link', { name: 'See details' })); expect(analyticsApiMock.getEvents()).toEqual( expect.arrayContaining([ @@ -68,16 +71,20 @@ describe('renderInTestApp', () => { }); it('should support setting different locations in the history stack', async () => { - renderInTestApp( - - Index Page} /> - Second Page} /> - , - { - initialRouteEntries: ['/second-page'], - }, - ); + renderInTestApp(

Index page

, { + extensions: [ + PageBlueprint.make({ + name: 'second-page', + params: defineParams => + defineParams({ + path: '/second-page', + loader: async () =>

Second Page

, + }), + }), + ], + initialRouteEntries: ['/second-page'], + }); - expect(screen.getByText('Second Page')).toBeInTheDocument(); + expect(await screen.findByText('Second Page')).toBeInTheDocument(); }); }); diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index e1b35eba6c..8f52f349fe 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -31,6 +31,7 @@ import { NavItemBlueprint, createFrontendPlugin, FrontendFeature, + PageBlueprint, } from '@backstage/frontend-plugin-api'; import appPlugin from '@backstage/plugin-app'; @@ -107,12 +108,6 @@ const appPluginOverride = appPlugin.withOverrides({ appPlugin.getExtension('sign-in-page:app').override({ disabled: true, }), - appPlugin.getExtension('app/layout').override({ - disabled: true, - }), - appPlugin.getExtension('app/routes').override({ - disabled: true, - }), appPlugin.getExtension('app/nav').override({ output: [coreExtensionData.reactElement], factory(_originalFactory, { inputs }) { @@ -152,13 +147,6 @@ export function renderInTestApp( options?: TestAppOptions, ): RenderResult { const extensions: Array = [ - createExtension({ - attachTo: { id: 'app/root', input: 'children' }, - output: [coreExtensionData.reactElement], - factory: () => { - return [coreExtensionData.reactElement(element)]; - }, - }), RouterBlueprint.make({ params: { component: ({ children }) => ( @@ -197,6 +185,13 @@ export function renderInTestApp( extensions.push(...options.extensions); } + extensions.push( + PageBlueprint.make({ + name: 'mocked-root-page', + params: define => define({ path: '/', loader: async () => element }), + }), + ); + const features: FrontendFeature[] = [ createFrontendPlugin({ pluginId: 'test', From 34680e981c623fcd6db5bfcebc355efef547717b Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 14:09:16 +0200 Subject: [PATCH 089/244] frontend-test-utils: tweak test Signed-off-by: Vincenzo Scamporlino --- .../src/app/renderInTestApp.test.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx index ae72e6a622..4da1c4632c 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx @@ -26,6 +26,7 @@ import { useAnalytics, } from '@backstage/frontend-plugin-api'; import { renderInTestApp } from './renderInTestApp'; +import { Route, Routes } from 'react-router-dom'; describe('renderInTestApp', () => { it('should render the given component in a page', async () => { @@ -78,13 +79,18 @@ describe('renderInTestApp', () => { params: defineParams => defineParams({ path: '/second-page', - loader: async () =>

Second Page

, + loader: async () => ( + + Second page} /> + Subpage} /> + + ), }), }), ], - initialRouteEntries: ['/second-page'], + initialRouteEntries: ['/second-page/subpage'], }); - expect(await screen.findByText('Second Page')).toBeInTheDocument(); + expect(await screen.findByText('Subpage')).toBeInTheDocument(); }); }); From ae1dad0e734bb550803b42585409cb8164b68600 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 14:32:53 +0200 Subject: [PATCH 090/244] changeset notfound page Signed-off-by: Vincenzo Scamporlino --- .changeset/fluffy-cities-sip.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/fluffy-cities-sip.md diff --git a/.changeset/fluffy-cities-sip.md b/.changeset/fluffy-cities-sip.md new file mode 100644 index 0000000000..f6692d4e27 --- /dev/null +++ b/.changeset/fluffy-cities-sip.md @@ -0,0 +1,6 @@ +--- +'@backstage/frontend-test-utils': patch +'@backstage/plugin-app': patch +--- + +Fixed an issue that caused the `NotFound` page to not render correctly when a Page was mounted at `/`. From 7b41d9dd31e831c00f6c08f50090b9c1acdd94ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 7 Oct 2025 15:23:00 +0200 Subject: [PATCH 091/244] Remove app-root-element:signals/signals-display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/forty-crabs-travel.md | 5 +++++ plugins/signals/report-alpha.api.md | 12 ------------ plugins/signals/src/alpha.tsx | 12 +----------- 3 files changed, 6 insertions(+), 23 deletions(-) create mode 100644 .changeset/forty-crabs-travel.md diff --git a/.changeset/forty-crabs-travel.md b/.changeset/forty-crabs-travel.md new file mode 100644 index 0000000000..83e281aa51 --- /dev/null +++ b/.changeset/forty-crabs-travel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-signals': patch +--- + +Remove `app-root-element:signals/signals-display` which was not doing anything useful diff --git a/plugins/signals/report-alpha.api.md b/plugins/signals/report-alpha.api.md index cd2f384e10..91bd2b6726 100644 --- a/plugins/signals/report-alpha.api.md +++ b/plugins/signals/report-alpha.api.md @@ -8,7 +8,6 @@ import { ApiFactory } from '@backstage/frontend-plugin-api'; import { ExtensionBlueprintParams } from '@backstage/frontend-plugin-api'; import { ExtensionDataRef } from '@backstage/frontend-plugin-api'; import { ExtensionDefinition } from '@backstage/frontend-plugin-api'; -import { JSX as JSX_2 } from 'react'; import { OverridableFrontendPlugin } from '@backstage/frontend-plugin-api'; // @alpha (undocumented) @@ -31,17 +30,6 @@ const _default: OverridableFrontendPlugin< params: ApiFactory, ) => ExtensionBlueprintParams; }>; - 'app-root-element:signals/signals-display': ExtensionDefinition<{ - kind: 'app-root-element'; - name: 'signals-display'; - config: {}; - configInput: {}; - output: ExtensionDataRef; - inputs: {}; - params: { - element: JSX.Element; - }; - }>; } >; export default _default; diff --git a/plugins/signals/src/alpha.tsx b/plugins/signals/src/alpha.tsx index 5f9cd6f91b..c32bff140e 100644 --- a/plugins/signals/src/alpha.tsx +++ b/plugins/signals/src/alpha.tsx @@ -16,15 +16,12 @@ import { ApiBlueprint, - AppRootElementBlueprint, createFrontendPlugin, discoveryApiRef, identityApiRef, } from '@backstage/frontend-plugin-api'; import { signalApiRef } from '@backstage/plugin-signals-react'; import { SignalClient } from './api/SignalClient'; -import { SignalsDisplay } from './plugin'; -import { compatWrapper } from '@backstage/core-compat-api'; const api = ApiBlueprint.make({ params: defineParams => @@ -43,16 +40,9 @@ const api = ApiBlueprint.make({ }), }); -const signalsDisplayAppRootElement = AppRootElementBlueprint.make({ - name: 'signals-display', - params: { - element: compatWrapper(), - }, -}); - /** @alpha */ export default createFrontendPlugin({ pluginId: 'signals', info: { packageJson: () => import('../package.json') }, - extensions: [api, signalsDisplayAppRootElement], + extensions: [api], }); From b8cf31a93a21fba498a48e29ffcde17e1265b4f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 13:57:14 +0000 Subject: [PATCH 092/244] chore(deps): bump nodemailer from 6.9.16 to 7.0.7 Bumps [nodemailer](https://github.com/nodemailer/nodemailer) from 6.9.16 to 7.0.7. - [Release notes](https://github.com/nodemailer/nodemailer/releases) - [Changelog](https://github.com/nodemailer/nodemailer/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodemailer/nodemailer/compare/v6.9.16...v7.0.7) --- updated-dependencies: - dependency-name: nodemailer dependency-version: 7.0.7 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .changeset/dependabot-eaf5987.md | 5 +++++ .../notifications-backend-module-email/package.json | 2 +- yarn.lock | 10 +++++----- 3 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 .changeset/dependabot-eaf5987.md diff --git a/.changeset/dependabot-eaf5987.md b/.changeset/dependabot-eaf5987.md new file mode 100644 index 0000000000..bf1475613a --- /dev/null +++ b/.changeset/dependabot-eaf5987.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-notifications-backend-module-email': patch +--- + +chore(deps): bump `nodemailer` from 6.9.16 to 7.0.7 diff --git a/plugins/notifications-backend-module-email/package.json b/plugins/notifications-backend-module-email/package.json index 7c1e279c6c..9f16340057 100644 --- a/plugins/notifications-backend-module-email/package.json +++ b/plugins/notifications-backend-module-email/package.json @@ -48,7 +48,7 @@ "@backstage/plugin-notifications-node": "workspace:^", "@backstage/types": "workspace:^", "lodash": "^4.17.21", - "nodemailer": "^6.9.13", + "nodemailer": "^7.0.7", "p-throttle": "^4.1.1" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 8e09ebae47..73647d22b3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5723,7 +5723,7 @@ __metadata: "@backstage/types": "workspace:^" "@types/nodemailer": "npm:^6.4.14" lodash: "npm:^4.17.21" - nodemailer: "npm:^6.9.13" + nodemailer: "npm:^7.0.7" p-throttle: "npm:^4.1.1" languageName: unknown linkType: soft @@ -38906,10 +38906,10 @@ __metadata: languageName: node linkType: hard -"nodemailer@npm:^6.9.13": - version: 6.9.16 - resolution: "nodemailer@npm:6.9.16" - checksum: 10/f131888d3111238fde4ee03539e62f1764b99365ff31d556dde0367dfefcee1f2eb8948558f35ba84fe5cd805f2d01294eee63a5675d3aa501e7df548a2518ce +"nodemailer@npm:^7.0.7": + version: 7.0.9 + resolution: "nodemailer@npm:7.0.9" + checksum: 10/88883c58afe356d2b4c24b1e976c04857e8a7a7145e1752dab69072900b0cc2e3daa0964a08c653e692fb64382453e1cfcee3d863828844c8d6f6239727b9023 languageName: node linkType: hard From da97dad6253f6723fde6974799ef68ed8252f258 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Tue, 7 Oct 2025 16:20:49 +0200 Subject: [PATCH 093/244] Revert "Merge pull request #31230 from backstage/bui-fix-tooltip" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 60c5db13568fe1acbb2a7c64298d11e6a1d98647, reversing changes made to 47f5d67bea83b3179f2540ad18a06cb44fabc5b9. Signed-off-by: Sofia Sjöblad --- .changeset/moody-singers-deny.md | 5 ----- .../ui/src/components/Button/Button.stories.tsx | 10 ---------- packages/ui/src/components/Button/Button.tsx | 16 ++-------------- 3 files changed, 2 insertions(+), 29 deletions(-) delete mode 100644 .changeset/moody-singers-deny.md diff --git a/.changeset/moody-singers-deny.md b/.changeset/moody-singers-deny.md deleted file mode 100644 index 28072baf4b..0000000000 --- a/.changeset/moody-singers-deny.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@backstage/ui': patch ---- - -Enable tooltips on disabled buttons with automatic wrapper diff --git a/packages/ui/src/components/Button/Button.stories.tsx b/packages/ui/src/components/Button/Button.stories.tsx index 1604c04eb4..db8e999f98 100644 --- a/packages/ui/src/components/Button/Button.stories.tsx +++ b/packages/ui/src/components/Button/Button.stories.tsx @@ -19,7 +19,6 @@ import { Button } from './Button'; import { Flex } from '../Flex'; import { Text } from '../Text'; import { Icon } from '../Icon'; -import { Tooltip, TooltipTrigger } from '../Tooltip'; const meta = { title: 'Backstage UI/Button', @@ -217,12 +216,3 @@ export const Playground: Story = { ), }; - -export const DisabledWithTooltips: Story = { - render: () => ( - - - Why this is disabled - - ), -}; diff --git a/packages/ui/src/components/Button/Button.tsx b/packages/ui/src/components/Button/Button.tsx index 9f658fd00a..40879e51ed 100644 --- a/packages/ui/src/components/Button/Button.tsx +++ b/packages/ui/src/components/Button/Button.tsx @@ -16,7 +16,7 @@ import clsx from 'clsx'; import { forwardRef, Ref } from 'react'; -import { Button as RAButton, Focusable } from 'react-aria-components'; +import { Button as RAButton } from 'react-aria-components'; import type { ButtonProps } from './types'; import { useStyles } from '../../hooks/useStyles'; @@ -30,7 +30,6 @@ export const Button = forwardRef( iconEnd, children, className, - isDisabled, ...rest } = props; @@ -39,29 +38,18 @@ export const Button = forwardRef( variant, }); - const btn = ( + return ( {iconStart} {children} {iconEnd} ); - - return isDisabled ? ( - - - {btn} - - - ) : ( - btn - ); }, ); From 67fc6fe48ce0f692acb0cf5db808d6682846da9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 7 Oct 2025 16:40:11 +0200 Subject: [PATCH 094/244] Update .changeset/full-chefs-roll.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/full-chefs-roll.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/full-chefs-roll.md b/.changeset/full-chefs-roll.md index 2eaa8b8026..0a13f116ec 100644 --- a/.changeset/full-chefs-roll.md +++ b/.changeset/full-chefs-roll.md @@ -2,4 +2,4 @@ '@backstage/cli': patch --- -Removed the script transform cache from the default Jest configuration. The script cache provided a moderate performance boost, but it is incomatible with Jest 30. +Removed the script transform cache from the default Jest configuration. The script cache provided a moderate performance boost, but it is incompatible with Jest 30. From 316d0774b854d1a617937d9d03a938bd2a5c6ae6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 7 Oct 2025 15:00:59 +0000 Subject: [PATCH 095/244] Version Packages (next) --- .changeset/create-app-1759849206.md | 5 + .changeset/pre.json | 21 +- docs/releases/v1.44.0-next.3-changelog.md | 219 ++++++++++++++++++ package.json | 2 +- packages/backend-app-api/CHANGELOG.md | 6 + packages/backend-app-api/package.json | 2 +- packages/cli/CHANGELOG.md | 13 ++ packages/cli/package.json | 2 +- packages/core-components/CHANGELOG.md | 6 + packages/core-components/package.json | 2 +- packages/create-app/CHANGELOG.md | 6 + packages/create-app/package.json | 2 +- packages/frontend-plugin-api/CHANGELOG.md | 8 + packages/frontend-plugin-api/package.json | 2 +- packages/ui/CHANGELOG.md | 9 + packages/ui/package.json | 2 +- plugins/app-visualizer/CHANGELOG.md | 9 + plugins/app-visualizer/package.json | 2 +- .../catalog-backend-module-aws/CHANGELOG.md | 6 + .../catalog-backend-module-aws/package.json | 2 +- .../catalog-backend-module-azure/CHANGELOG.md | 6 + .../catalog-backend-module-azure/package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- .../CHANGELOG.md | 8 + .../package.json | 2 +- .../CHANGELOG.md | 7 + .../package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- plugins/catalog-graph/CHANGELOG.md | 9 + plugins/catalog-graph/package.json | 2 +- plugins/home/CHANGELOG.md | 9 + plugins/home/package.json | 2 +- plugins/kubernetes-cluster/CHANGELOG.md | 8 + plugins/kubernetes-cluster/package.json | 2 +- plugins/kubernetes/CHANGELOG.md | 9 + plugins/kubernetes/package.json | 2 +- .../CHANGELOG.md | 7 + .../package.json | 2 +- plugins/notifications-backend/CHANGELOG.md | 6 + plugins/notifications-backend/package.json | 2 +- plugins/notifications/CHANGELOG.md | 9 + plugins/notifications/package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- .../CHANGELOG.md | 6 + .../package.json | 2 +- plugins/scaffolder/CHANGELOG.md | 9 + plugins/scaffolder/package.json | 2 +- plugins/signals/CHANGELOG.md | 9 + plugins/signals/package.json | 2 +- 62 files changed, 489 insertions(+), 31 deletions(-) create mode 100644 .changeset/create-app-1759849206.md create mode 100644 docs/releases/v1.44.0-next.3-changelog.md diff --git a/.changeset/create-app-1759849206.md b/.changeset/create-app-1759849206.md new file mode 100644 index 0000000000..b50d431d4b --- /dev/null +++ b/.changeset/create-app-1759849206.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bumped create-app version. diff --git a/.changeset/pre.json b/.changeset/pre.json index 486fc27ac5..458c97896e 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -218,12 +218,20 @@ "create-app-1758639549", "create-app-1758718573", "create-app-1759243273", + "create-app-1759849206", + "cuddly-mugs-act", "curvy-bobcats-melt", + "dependabot-eaf5987", "eager-toes-start", "famous-loops-tickle", "fast-heads-brake", "fast-queens-guess", + "few-weeks-create", "five-olives-bet", + "flat-peas-run", + "forty-crabs-travel", + "full-chefs-roll", + "fuzzy-trams-kick", "giant-weeks-jump", "heavy-cooks-divide", "hungry-crews-fetch", @@ -232,6 +240,7 @@ "legal-eagles-jog", "modern-pugs-appear", "moody-singers-deny", + "nasty-moose-rescue", "nice-readers-judge", "public-sites-admire", "public-wombats-say", @@ -240,18 +249,28 @@ "ready-pots-arrive", "red-dodos-work", "red-times-bet", + "sad-women-rule", "salty-words-wash", + "shiny-candles-hide", "short-aliens-invite", + "silent-mice-play", "six-cooks-battle", "slimy-signs-agree", "solid-bikes-leave", "tame-hairs-smash", "tender-cups-tap", + "thin-hoops-bathe", "thirty-rules-press", + "tidy-coats-know", "tired-mice-cheer", + "tough-clocks-attack", "twelve-guests-sit", + "twelve-oranges-grin", + "two-emus-like", "unified-theme-attr-stack", + "warm-items-look", "wet-spiders-wait", - "wide-flies-jog" + "wide-flies-jog", + "yarn-plugin-integration" ] } diff --git a/docs/releases/v1.44.0-next.3-changelog.md b/docs/releases/v1.44.0-next.3-changelog.md new file mode 100644 index 0000000000..8a65d6d6a6 --- /dev/null +++ b/docs/releases/v1.44.0-next.3-changelog.md @@ -0,0 +1,219 @@ +# Release v1.44.0-next.3 + +Upgrade Helper: [https://backstage.github.io/upgrade-helper/?to=1.44.0-next.3](https://backstage.github.io/upgrade-helper/?to=1.44.0-next.3) + +## @backstage/backend-app-api@1.2.8-next.1 + +### Patch Changes + +- dd69cf6: Moved up registration of unhandled rejections and errors listeners to be done as early as possible, avoiding flakiness in backend startups and instead always logging these failures rather than sometimes crashing the process. + +## @backstage/cli@0.34.4-next.3 + +### Patch Changes + +- f2cf564: Removed the script transform cache from the default Jest configuration. The script cache provided a moderate performance boost, but it is incompatible with Jest 30. + +- 024645e: Remove unused @octokit modules from cli package + + - @octokit/graphql + - @octokit/graphql-schema + - @octokit/oauth-app + +- d14ef24: Added automatic detection and support for the Backstage Yarn plugin when generating new packages with `yarn new`. When the plugin is installed, new packages will automatically use `backstage:^` ranges for `@backstage/*` dependencies. + +## @backstage/core-components@0.18.2-next.3 + +### Patch Changes + +- 431130c: Added `renderEdge` prop to `` component in `@backstage/core-components` to allow custom rendering of graph edges. + +## @backstage/create-app@0.7.5-next.3 + +### Patch Changes + +- Bumped create-app version. + +## @backstage/frontend-plugin-api@0.12.1-next.2 + +### Patch Changes + +- 8ed53eb: Added `coreExtensionData.title`, especially useful for creating extensible layout with tabbed pages, but available for use for other cases too. +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + +## @backstage/ui@0.7.2-next.2 + +### Patch Changes + +- 3c921c5: Making href mandatory in tabs that are part of a Header component +- 5c21e45: Add react router for internal routing for ButtonLinks +- 9781815: Remove auto selection of tabs for tabs that all have href defined +- f6dff5b: Using react router for internal links in the Menu component + +## @backstage/plugin-app-visualizer@0.1.24-next.2 + +### Patch Changes + +- 4406144: Ensure that the text rendering has react keys for all elements +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + +## @backstage/plugin-catalog-backend-module-aws@0.4.16-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-backend-module-azure@0.3.10-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-backend-module-bitbucket-cloud@0.5.4-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-backend-module-bitbucket-server@0.5.4-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-backend-module-gerrit@0.3.7-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-backend-module-github@0.11.1-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-backend-module-github-org@0.3.15-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies +- Updated dependencies + - @backstage/plugin-catalog-backend-module-github@0.11.1-next.2 + +## @backstage/plugin-catalog-backend-module-gitlab@0.7.4-next.2 + +### Patch Changes + +- 0443119: Fixed an issue in `GitlabDiscoveryEntityProvider` where entity fetching could fail for projects with special characters or that had been renamed or moved. +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-backend-module-gitlab-org@0.2.14-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies +- Updated dependencies + - @backstage/plugin-catalog-backend-module-gitlab@0.7.4-next.2 + +## @backstage/plugin-catalog-backend-module-msgraph@0.8.1-next.1 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-backend-module-puppetdb@0.2.15-next.1 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + +## @backstage/plugin-catalog-graph@0.5.2-next.2 + +### Patch Changes + +- 431130c: Added `renderEdge` prop to `` component in `@backstage/core-components` to allow custom rendering of graph edges. +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + +## @backstage/plugin-home@0.8.13-next.3 + +### Patch Changes + +- e7d59d3: fix(home): correct `clearAll` logic to properly handle `deletable` flag +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + +## @backstage/plugin-kubernetes@0.12.12-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + +## @backstage/plugin-kubernetes-cluster@0.0.30-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + +## @backstage/plugin-notifications@0.5.10-next.3 + +### Patch Changes + +- f5e0963: Removed unused dependencies +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + +## @backstage/plugin-notifications-backend@0.5.11-next.2 + +### Patch Changes + +- f5e0963: Removed unused dependencies + +## @backstage/plugin-notifications-backend-module-email@0.3.14-next.1 + +### Patch Changes + +- b8cf31a: chore(deps): bump `nodemailer` from 6.9.16 to 7.0.7 +- f5e0963: Removed unused dependencies + +## @backstage/plugin-scaffolder@1.34.2-next.3 + +### Patch Changes + +- d9aed74: Forward `ui:disabled` in `OwnedEntityPicker` to allow disabling it +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + +## @backstage/plugin-scaffolder-backend-module-bitbucket-server@0.2.14-next.2 + +### Patch Changes + +- f5e0963: Removed unused dependencies + +## @backstage/plugin-scaffolder-backend-module-gitlab@0.9.6-next.2 + +### Patch Changes + +- f5e0963: Removed unused dependencies + +## @backstage/plugin-signals@0.0.24-next.3 + +### Patch Changes + +- 7b41d9d: Remove `app-root-element:signals/signals-display` which was not doing anything useful +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 diff --git a/package.json b/package.json index a22ab1666a..5ef45ce170 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "root", - "version": "1.44.0-next.2", + "version": "1.44.0-next.3", "backstage": { "cli": { "new": { diff --git a/packages/backend-app-api/CHANGELOG.md b/packages/backend-app-api/CHANGELOG.md index a0176a008f..e36a8a781b 100644 --- a/packages/backend-app-api/CHANGELOG.md +++ b/packages/backend-app-api/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/backend-app-api +## 1.2.8-next.1 + +### Patch Changes + +- dd69cf6: Moved up registration of unhandled rejections and errors listeners to be done as early as possible, avoiding flakiness in backend startups and instead always logging these failures rather than sometimes crashing the process. + ## 1.2.8-next.0 ### Patch Changes diff --git a/packages/backend-app-api/package.json b/packages/backend-app-api/package.json index b082de0cfa..1613e05cc0 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.8-next.0", + "version": "1.2.8-next.1", "description": "Core API used by Backstage backend apps", "backstage": { "role": "node-library" diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 7382ef147b..900401a8fa 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,18 @@ # @backstage/cli +## 0.34.4-next.3 + +### Patch Changes + +- f2cf564: Removed the script transform cache from the default Jest configuration. The script cache provided a moderate performance boost, but it is incompatible with Jest 30. +- 024645e: Remove unused @octokit modules from cli package + + - @octokit/graphql + - @octokit/graphql-schema + - @octokit/oauth-app + +- d14ef24: Added automatic detection and support for the Backstage Yarn plugin when generating new packages with `yarn new`. When the plugin is installed, new packages will automatically use `backstage:^` ranges for `@backstage/*` dependencies. + ## 0.34.4-next.2 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index 5b62c9a02a..19d9428979 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/cli", - "version": "0.34.4-next.2", + "version": "0.34.4-next.3", "description": "CLI for developing Backstage plugins and apps", "backstage": { "role": "cli" diff --git a/packages/core-components/CHANGELOG.md b/packages/core-components/CHANGELOG.md index 807d844712..90b0695ab9 100644 --- a/packages/core-components/CHANGELOG.md +++ b/packages/core-components/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/core-components +## 0.18.2-next.3 + +### Patch Changes + +- 431130c: Added `renderEdge` prop to `` component in `@backstage/core-components` to allow custom rendering of graph edges. + ## 0.18.2-next.2 ### Patch Changes diff --git a/packages/core-components/package.json b/packages/core-components/package.json index 3418bbe033..fdde2c7e79 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/core-components", - "version": "0.18.2-next.2", + "version": "0.18.2-next.3", "description": "Core components used by Backstage plugins and apps", "backstage": { "role": "web-library" diff --git a/packages/create-app/CHANGELOG.md b/packages/create-app/CHANGELOG.md index baa76026b6..dfff2af4f3 100644 --- a/packages/create-app/CHANGELOG.md +++ b/packages/create-app/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/create-app +## 0.7.5-next.3 + +### Patch Changes + +- Bumped create-app version. + ## 0.7.5-next.2 ### Patch Changes diff --git a/packages/create-app/package.json b/packages/create-app/package.json index eac44e445a..9fa8af4c1b 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/create-app", - "version": "0.7.5-next.2", + "version": "0.7.5-next.3", "description": "A CLI that helps you create your own Backstage app", "backstage": { "role": "cli" diff --git a/packages/frontend-plugin-api/CHANGELOG.md b/packages/frontend-plugin-api/CHANGELOG.md index e12aedb385..9f6a380b07 100644 --- a/packages/frontend-plugin-api/CHANGELOG.md +++ b/packages/frontend-plugin-api/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/frontend-plugin-api +## 0.12.1-next.2 + +### Patch Changes + +- 8ed53eb: Added `coreExtensionData.title`, especially useful for creating extensible layout with tabbed pages, but available for use for other cases too. +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + ## 0.12.1-next.1 ### Patch Changes diff --git a/packages/frontend-plugin-api/package.json b/packages/frontend-plugin-api/package.json index 15e557101c..0dd0748f97 100644 --- a/packages/frontend-plugin-api/package.json +++ b/packages/frontend-plugin-api/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/frontend-plugin-api", - "version": "0.12.1-next.1", + "version": "0.12.1-next.2", "backstage": { "role": "web-library" }, diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 2efdbb2b9e..95314bf768 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/ui +## 0.7.2-next.2 + +### Patch Changes + +- 3c921c5: Making href mandatory in tabs that are part of a Header component +- 5c21e45: Add react router for internal routing for ButtonLinks +- 9781815: Remove auto selection of tabs for tabs that all have href defined +- f6dff5b: Using react router for internal links in the Menu component + ## 0.7.2-next.1 ### Patch Changes diff --git a/packages/ui/package.json b/packages/ui/package.json index 448905ab9d..fd6ecd169c 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/ui", - "version": "0.7.2-next.1", + "version": "0.7.2-next.2", "backstage": { "role": "web-library" }, diff --git a/plugins/app-visualizer/CHANGELOG.md b/plugins/app-visualizer/CHANGELOG.md index ea0b147aff..cdd5db4986 100644 --- a/plugins/app-visualizer/CHANGELOG.md +++ b/plugins/app-visualizer/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-app-visualizer +## 0.1.24-next.2 + +### Patch Changes + +- 4406144: Ensure that the text rendering has react keys for all elements +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + ## 0.1.24-next.1 ### Patch Changes diff --git a/plugins/app-visualizer/package.json b/plugins/app-visualizer/package.json index fa30acefe2..f55c085ed0 100644 --- a/plugins/app-visualizer/package.json +++ b/plugins/app-visualizer/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-app-visualizer", - "version": "0.1.24-next.1", + "version": "0.1.24-next.2", "description": "Visualizes the Backstage app structure", "backstage": { "role": "frontend-plugin", diff --git a/plugins/catalog-backend-module-aws/CHANGELOG.md b/plugins/catalog-backend-module-aws/CHANGELOG.md index a77ccf785c..2ee7746b87 100644 --- a/plugins/catalog-backend-module-aws/CHANGELOG.md +++ b/plugins/catalog-backend-module-aws/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-catalog-backend-module-aws +## 0.4.16-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + ## 0.4.16-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-aws/package.json b/plugins/catalog-backend-module-aws/package.json index 39b199d03d..eef358548a 100644 --- a/plugins/catalog-backend-module-aws/package.json +++ b/plugins/catalog-backend-module-aws/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-aws", - "version": "0.4.16-next.1", + "version": "0.4.16-next.2", "description": "A Backstage catalog backend module that helps integrate towards AWS", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-azure/CHANGELOG.md b/plugins/catalog-backend-module-azure/CHANGELOG.md index 8f04f5cae5..d170204031 100644 --- a/plugins/catalog-backend-module-azure/CHANGELOG.md +++ b/plugins/catalog-backend-module-azure/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-catalog-backend-module-azure +## 0.3.10-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + ## 0.3.10-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-azure/package.json b/plugins/catalog-backend-module-azure/package.json index a390224e50..2b2ef5fe35 100644 --- a/plugins/catalog-backend-module-azure/package.json +++ b/plugins/catalog-backend-module-azure/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-azure", - "version": "0.3.10-next.1", + "version": "0.3.10-next.2", "description": "A Backstage catalog backend module that helps integrate towards Azure", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md index bce5bc231b..f9ac3b6966 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-cloud/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-catalog-backend-module-bitbucket-cloud +## 0.5.4-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + ## 0.5.4-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-cloud/package.json b/plugins/catalog-backend-module-bitbucket-cloud/package.json index e10df5a382..e77dfa9ee0 100644 --- a/plugins/catalog-backend-module-bitbucket-cloud/package.json +++ b/plugins/catalog-backend-module-bitbucket-cloud/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-cloud", - "version": "0.5.4-next.1", + "version": "0.5.4-next.2", "description": "A Backstage catalog backend module that helps integrate towards Bitbucket Cloud", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md index cb7767ce16..fe2cae0334 100644 --- a/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/catalog-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-catalog-backend-module-bitbucket-server +## 0.5.4-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + ## 0.5.4-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-bitbucket-server/package.json b/plugins/catalog-backend-module-bitbucket-server/package.json index 21d6ece100..c9021d42c1 100644 --- a/plugins/catalog-backend-module-bitbucket-server/package.json +++ b/plugins/catalog-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-bitbucket-server", - "version": "0.5.4-next.1", + "version": "0.5.4-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-gerrit/CHANGELOG.md b/plugins/catalog-backend-module-gerrit/CHANGELOG.md index c1f9fe3867..0235f98580 100644 --- a/plugins/catalog-backend-module-gerrit/CHANGELOG.md +++ b/plugins/catalog-backend-module-gerrit/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-catalog-backend-module-gerrit +## 0.3.7-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + ## 0.3.7-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gerrit/package.json b/plugins/catalog-backend-module-gerrit/package.json index 7427ed0906..e345190ece 100644 --- a/plugins/catalog-backend-module-gerrit/package.json +++ b/plugins/catalog-backend-module-gerrit/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gerrit", - "version": "0.3.7-next.1", + "version": "0.3.7-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "catalog", diff --git a/plugins/catalog-backend-module-github-org/CHANGELOG.md b/plugins/catalog-backend-module-github-org/CHANGELOG.md index df63d6fb8f..61b5aa19dd 100644 --- a/plugins/catalog-backend-module-github-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-github-org/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-github-org +## 0.3.15-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies +- Updated dependencies + - @backstage/plugin-catalog-backend-module-github@0.11.1-next.2 + ## 0.3.15-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github-org/package.json b/plugins/catalog-backend-module-github-org/package.json index 0329bebbf6..93bc6517e0 100644 --- a/plugins/catalog-backend-module-github-org/package.json +++ b/plugins/catalog-backend-module-github-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github-org", - "version": "0.3.15-next.1", + "version": "0.3.15-next.2", "description": "The github-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-github/CHANGELOG.md b/plugins/catalog-backend-module-github/CHANGELOG.md index 2921c3960d..da546ffe8e 100644 --- a/plugins/catalog-backend-module-github/CHANGELOG.md +++ b/plugins/catalog-backend-module-github/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-catalog-backend-module-github +## 0.11.1-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + ## 0.11.1-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-github/package.json b/plugins/catalog-backend-module-github/package.json index c91bb5e96a..32c8a14614 100644 --- a/plugins/catalog-backend-module-github/package.json +++ b/plugins/catalog-backend-module-github/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-github", - "version": "0.11.1-next.1", + "version": "0.11.1-next.2", "description": "A Backstage catalog backend module that helps integrate towards GitHub", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md b/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md index b162bf1103..b6e85af5fd 100644 --- a/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab-org/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-catalog-backend-module-gitlab-org +## 0.2.14-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies +- Updated dependencies + - @backstage/plugin-catalog-backend-module-gitlab@0.7.4-next.2 + ## 0.2.14-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab-org/package.json b/plugins/catalog-backend-module-gitlab-org/package.json index 80c1ba769c..9be7de1635 100644 --- a/plugins/catalog-backend-module-gitlab-org/package.json +++ b/plugins/catalog-backend-module-gitlab-org/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab-org", - "version": "0.2.14-next.1", + "version": "0.2.14-next.2", "description": "The gitlab-org backend module for the catalog plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-gitlab/CHANGELOG.md b/plugins/catalog-backend-module-gitlab/CHANGELOG.md index 18a1915ee6..91dbf57f9e 100644 --- a/plugins/catalog-backend-module-gitlab/CHANGELOG.md +++ b/plugins/catalog-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-catalog-backend-module-gitlab +## 0.7.4-next.2 + +### Patch Changes + +- 0443119: Fixed an issue in `GitlabDiscoveryEntityProvider` where entity fetching could fail for projects with special characters or that had been renamed or moved. +- 99fcf98: Removed unused dependencies + ## 0.7.4-next.1 ### Patch Changes diff --git a/plugins/catalog-backend-module-gitlab/package.json b/plugins/catalog-backend-module-gitlab/package.json index 0c20cdd30a..1de716499e 100644 --- a/plugins/catalog-backend-module-gitlab/package.json +++ b/plugins/catalog-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-gitlab", - "version": "0.7.4-next.1", + "version": "0.7.4-next.2", "description": "A Backstage catalog backend module that helps integrate towards GitLab", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-msgraph/CHANGELOG.md b/plugins/catalog-backend-module-msgraph/CHANGELOG.md index 3db73151fe..9bd2ff31d0 100644 --- a/plugins/catalog-backend-module-msgraph/CHANGELOG.md +++ b/plugins/catalog-backend-module-msgraph/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-catalog-backend-module-msgraph +## 0.8.1-next.1 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + ## 0.8.1-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 35d38e12d4..bcf0ae17a3 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-msgraph", - "version": "0.8.1-next.0", + "version": "0.8.1-next.1", "description": "A Backstage catalog backend module that helps integrate towards Microsoft Graph", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md index cdbee9bfb8..7645b8d390 100644 --- a/plugins/catalog-backend-module-puppetdb/CHANGELOG.md +++ b/plugins/catalog-backend-module-puppetdb/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-catalog-backend-module-puppetdb +## 0.2.15-next.1 + +### Patch Changes + +- 99fcf98: Removed unused dependencies + ## 0.2.15-next.0 ### Patch Changes diff --git a/plugins/catalog-backend-module-puppetdb/package.json b/plugins/catalog-backend-module-puppetdb/package.json index d76b965b90..4a01305a1a 100644 --- a/plugins/catalog-backend-module-puppetdb/package.json +++ b/plugins/catalog-backend-module-puppetdb/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-backend-module-puppetdb", - "version": "0.2.15-next.0", + "version": "0.2.15-next.1", "description": "A Backstage catalog backend module that helps integrate towards PuppetDB", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/catalog-graph/CHANGELOG.md b/plugins/catalog-graph/CHANGELOG.md index b492c41a37..41c3c1c519 100644 --- a/plugins/catalog-graph/CHANGELOG.md +++ b/plugins/catalog-graph/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-catalog-graph +## 0.5.2-next.2 + +### Patch Changes + +- 431130c: Added `renderEdge` prop to `` component in `@backstage/core-components` to allow custom rendering of graph edges. +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + ## 0.5.2-next.1 ### Patch Changes diff --git a/plugins/catalog-graph/package.json b/plugins/catalog-graph/package.json index f455dbce31..7531a926a4 100644 --- a/plugins/catalog-graph/package.json +++ b/plugins/catalog-graph/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-catalog-graph", - "version": "0.5.2-next.1", + "version": "0.5.2-next.2", "backstage": { "role": "frontend-plugin", "pluginId": "catalog-graph", diff --git a/plugins/home/CHANGELOG.md b/plugins/home/CHANGELOG.md index 68ef6448a5..85e2a009f4 100644 --- a/plugins/home/CHANGELOG.md +++ b/plugins/home/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-home +## 0.8.13-next.3 + +### Patch Changes + +- e7d59d3: fix(home): correct `clearAll` logic to properly handle `deletable` flag +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + ## 0.8.13-next.2 ### Patch Changes diff --git a/plugins/home/package.json b/plugins/home/package.json index 910d6c036f..060f090974 100644 --- a/plugins/home/package.json +++ b/plugins/home/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-home", - "version": "0.8.13-next.2", + "version": "0.8.13-next.3", "description": "A Backstage plugin that helps you build a home page", "backstage": { "role": "frontend-plugin", diff --git a/plugins/kubernetes-cluster/CHANGELOG.md b/plugins/kubernetes-cluster/CHANGELOG.md index 527c13c88d..be3fed6035 100644 --- a/plugins/kubernetes-cluster/CHANGELOG.md +++ b/plugins/kubernetes-cluster/CHANGELOG.md @@ -1,5 +1,13 @@ # @backstage/plugin-kubernetes-cluster +## 0.0.30-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + ## 0.0.30-next.1 ### Patch Changes diff --git a/plugins/kubernetes-cluster/package.json b/plugins/kubernetes-cluster/package.json index ea1bb80570..033e1138f4 100644 --- a/plugins/kubernetes-cluster/package.json +++ b/plugins/kubernetes-cluster/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes-cluster", - "version": "0.0.30-next.1", + "version": "0.0.30-next.2", "description": "A Backstage plugin that shows details of Kubernetes clusters", "backstage": { "role": "frontend-plugin", diff --git a/plugins/kubernetes/CHANGELOG.md b/plugins/kubernetes/CHANGELOG.md index 62ffb354bf..670ff085f6 100644 --- a/plugins/kubernetes/CHANGELOG.md +++ b/plugins/kubernetes/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-kubernetes +## 0.12.12-next.2 + +### Patch Changes + +- 99fcf98: Removed unused dependencies +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + ## 0.12.12-next.1 ### Patch Changes diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json index 2fe8506310..113deee19f 100644 --- a/plugins/kubernetes/package.json +++ b/plugins/kubernetes/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-kubernetes", - "version": "0.12.12-next.1", + "version": "0.12.12-next.2", "description": "A Backstage plugin that integrates towards Kubernetes", "backstage": { "role": "frontend-plugin", diff --git a/plugins/notifications-backend-module-email/CHANGELOG.md b/plugins/notifications-backend-module-email/CHANGELOG.md index 99f2277dad..cf891bebc1 100644 --- a/plugins/notifications-backend-module-email/CHANGELOG.md +++ b/plugins/notifications-backend-module-email/CHANGELOG.md @@ -1,5 +1,12 @@ # @backstage/plugin-notifications-backend-module-email +## 0.3.14-next.1 + +### Patch Changes + +- b8cf31a: chore(deps): bump `nodemailer` from 6.9.16 to 7.0.7 +- f5e0963: Removed unused dependencies + ## 0.3.14-next.0 ### Patch Changes diff --git a/plugins/notifications-backend-module-email/package.json b/plugins/notifications-backend-module-email/package.json index 7f5711d27d..94a3635ef1 100644 --- a/plugins/notifications-backend-module-email/package.json +++ b/plugins/notifications-backend-module-email/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend-module-email", - "version": "0.3.14-next.0", + "version": "0.3.14-next.1", "description": "The email backend module for the notifications plugin.", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/notifications-backend/CHANGELOG.md b/plugins/notifications-backend/CHANGELOG.md index 713066e692..d99785fd12 100644 --- a/plugins/notifications-backend/CHANGELOG.md +++ b/plugins/notifications-backend/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-notifications-backend +## 0.5.11-next.2 + +### Patch Changes + +- f5e0963: Removed unused dependencies + ## 0.5.11-next.1 ### Patch Changes diff --git a/plugins/notifications-backend/package.json b/plugins/notifications-backend/package.json index e03f07c1c9..0f270b1e37 100644 --- a/plugins/notifications-backend/package.json +++ b/plugins/notifications-backend/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications-backend", - "version": "0.5.11-next.1", + "version": "0.5.11-next.2", "backstage": { "role": "backend-plugin", "pluginId": "notifications", diff --git a/plugins/notifications/CHANGELOG.md b/plugins/notifications/CHANGELOG.md index caedf21e35..b5a6da6ba1 100644 --- a/plugins/notifications/CHANGELOG.md +++ b/plugins/notifications/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-notifications +## 0.5.10-next.3 + +### Patch Changes + +- f5e0963: Removed unused dependencies +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + ## 0.5.10-next.2 ### Patch Changes diff --git a/plugins/notifications/package.json b/plugins/notifications/package.json index 9d7e36c1ac..68996bc7c0 100644 --- a/plugins/notifications/package.json +++ b/plugins/notifications/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-notifications", - "version": "0.5.10-next.2", + "version": "0.5.10-next.3", "backstage": { "role": "frontend-plugin", "pluginId": "notifications", diff --git a/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md b/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md index 9df81bc074..055f52a047 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-bitbucket-server/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-scaffolder-backend-module-bitbucket-server +## 0.2.14-next.2 + +### Patch Changes + +- f5e0963: Removed unused dependencies + ## 0.2.14-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-bitbucket-server/package.json b/plugins/scaffolder-backend-module-bitbucket-server/package.json index 53564814d1..f53b075403 100644 --- a/plugins/scaffolder-backend-module-bitbucket-server/package.json +++ b/plugins/scaffolder-backend-module-bitbucket-server/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-bitbucket-server", - "version": "0.2.14-next.1", + "version": "0.2.14-next.2", "description": "The Bitbucket Server module for @backstage/plugin-scaffolder-backend", "backstage": { "role": "backend-plugin-module", diff --git a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md index c1312cc2a6..c0ea9e94dd 100644 --- a/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md +++ b/plugins/scaffolder-backend-module-gitlab/CHANGELOG.md @@ -1,5 +1,11 @@ # @backstage/plugin-scaffolder-backend-module-gitlab +## 0.9.6-next.2 + +### Patch Changes + +- f5e0963: Removed unused dependencies + ## 0.9.6-next.1 ### Patch Changes diff --git a/plugins/scaffolder-backend-module-gitlab/package.json b/plugins/scaffolder-backend-module-gitlab/package.json index c9644543a5..d34526b65b 100644 --- a/plugins/scaffolder-backend-module-gitlab/package.json +++ b/plugins/scaffolder-backend-module-gitlab/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder-backend-module-gitlab", - "version": "0.9.6-next.1", + "version": "0.9.6-next.2", "backstage": { "role": "backend-plugin-module", "pluginId": "scaffolder", diff --git a/plugins/scaffolder/CHANGELOG.md b/plugins/scaffolder/CHANGELOG.md index 649965149d..8abe46b3c7 100644 --- a/plugins/scaffolder/CHANGELOG.md +++ b/plugins/scaffolder/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-scaffolder +## 1.34.2-next.3 + +### Patch Changes + +- d9aed74: Forward `ui:disabled` in `OwnedEntityPicker` to allow disabling it +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + ## 1.34.2-next.2 ### Patch Changes diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 21e57a97c8..4a64a18ca4 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-scaffolder", - "version": "1.34.2-next.2", + "version": "1.34.2-next.3", "description": "The Backstage plugin that helps you create new things", "backstage": { "role": "frontend-plugin", diff --git a/plugins/signals/CHANGELOG.md b/plugins/signals/CHANGELOG.md index 1e41067d82..02e57ebeca 100644 --- a/plugins/signals/CHANGELOG.md +++ b/plugins/signals/CHANGELOG.md @@ -1,5 +1,14 @@ # @backstage/plugin-signals +## 0.0.24-next.3 + +### Patch Changes + +- 7b41d9d: Remove `app-root-element:signals/signals-display` which was not doing anything useful +- Updated dependencies + - @backstage/core-components@0.18.2-next.3 + - @backstage/frontend-plugin-api@0.12.1-next.2 + ## 0.0.24-next.2 ### Patch Changes diff --git a/plugins/signals/package.json b/plugins/signals/package.json index 13bf863b60..d67709a5ca 100644 --- a/plugins/signals/package.json +++ b/plugins/signals/package.json @@ -1,6 +1,6 @@ { "name": "@backstage/plugin-signals", - "version": "0.0.24-next.2", + "version": "0.0.24-next.3", "backstage": { "role": "frontend-plugin", "pluginId": "signals", From 74dcd32da46125c1c18d33ad8137a2e0ee784072 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 7 Oct 2025 17:45:12 +0100 Subject: [PATCH 096/244] Update sidebars.ts Signed-off-by: Charles de Dreuille --- microsite/sidebars.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/microsite/sidebars.ts b/microsite/sidebars.ts index b7e89825ca..2d5065400b 100644 --- a/microsite/sidebars.ts +++ b/microsite/sidebars.ts @@ -396,17 +396,7 @@ export default { 'conf/index', 'conf/reading', 'conf/writing', - 'conf/defining', - { - type: 'category', - label: 'User Interface', - items: [ - 'conf/user-interface/index', - 'conf/user-interface/logo', - 'conf/user-interface/icons', - 'conf/user-interface/sidebar', - ], - }, + 'conf/defining' ], Framework: [ { @@ -551,6 +541,16 @@ export default { 'tooling/package-metadata', ], }, + { + type: 'category', + label: 'User Interface', + items: [ + 'conf/user-interface/index', + 'conf/user-interface/logo', + 'conf/user-interface/icons', + 'conf/user-interface/sidebar', + ], + }, ], Tutorials: [ { 'Non-technical': ['overview/adopting'] }, From 1ac09a8060abf264d9558ceed17f7cc547779dfb Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 7 Oct 2025 18:01:11 +0100 Subject: [PATCH 097/244] Update docusaurus.config.ts Signed-off-by: Charles de Dreuille --- microsite/docusaurus.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/docusaurus.config.ts b/microsite/docusaurus.config.ts index 83f2f75689..206dbba97f 100644 --- a/microsite/docusaurus.config.ts +++ b/microsite/docusaurus.config.ts @@ -272,7 +272,7 @@ const config: Config = { { from: '/docs/getting-started/app-custom-theme', to: '/docs/conf/user-interface', - } + }, ], }), [ From 79d72fa86e3dc00c4af07066ed243ed4bf0a3a16 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 7 Oct 2025 18:15:18 +0100 Subject: [PATCH 098/244] Update sidebars.ts Signed-off-by: Charles de Dreuille --- microsite/sidebars.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsite/sidebars.ts b/microsite/sidebars.ts index 2d5065400b..1f05660d7e 100644 --- a/microsite/sidebars.ts +++ b/microsite/sidebars.ts @@ -396,7 +396,7 @@ export default { 'conf/index', 'conf/reading', 'conf/writing', - 'conf/defining' + 'conf/defining', ], Framework: [ { From 43afbe50aa3c30968b8443dbbf69c637673069c5 Mon Sep 17 00:00:00 2001 From: Gabriel Dugny Date: Tue, 7 Oct 2025 19:29:14 +0200 Subject: [PATCH 099/244] feat(techdocs): POC livereload for techdocs-cli serve (#30541) * feat(techdocs): POC livereload for techdocs-cli serve Signed-off-by: Gabriel Dugny * chore: techdocs reload tests, refactor Signed-off-by: Gabriel Dugny --------- Signed-off-by: Gabriel Dugny --- .changeset/brown-symbols-create.md | 5 + .../techdocs-cli-embedded-app/app-config.yaml | 4 + .../techdocs-cli-embedded-app/src/App.tsx | 10 + .../src/LiveReloadAddon.test.tsx | 111 +++++++++++ .../src/LiveReloadAddon.tsx | 121 ++++++++++++ packages/techdocs-cli/src/lib/httpServer.ts | 32 +++- .../techdocs-cli/src/lib/livereload.test.ts | 180 ++++++++++++++++++ packages/techdocs-cli/src/lib/livereload.ts | 175 +++++++++++++++++ 8 files changed, 636 insertions(+), 2 deletions(-) create mode 100644 .changeset/brown-symbols-create.md create mode 100644 packages/techdocs-cli-embedded-app/src/LiveReloadAddon.test.tsx create mode 100644 packages/techdocs-cli-embedded-app/src/LiveReloadAddon.tsx create mode 100644 packages/techdocs-cli/src/lib/livereload.test.ts create mode 100644 packages/techdocs-cli/src/lib/livereload.ts diff --git a/.changeset/brown-symbols-create.md b/.changeset/brown-symbols-create.md new file mode 100644 index 0000000000..d4a62b1280 --- /dev/null +++ b/.changeset/brown-symbols-create.md @@ -0,0 +1,5 @@ +--- +'@techdocs/cli': minor +--- + +Techdocs CLI serve supports automatic refresh, relying on `mkdocs` `watch` feature. diff --git a/packages/techdocs-cli-embedded-app/app-config.yaml b/packages/techdocs-cli-embedded-app/app-config.yaml index 6ede05b587..c8dfa1683c 100644 --- a/packages/techdocs-cli-embedded-app/app-config.yaml +++ b/packages/techdocs-cli-embedded-app/app-config.yaml @@ -7,3 +7,7 @@ backend: techdocs: builder: 'external' + sanitizer: + # Allow live reload locally. Added in this config to avoid updating the main techdocs plugin. + allowedCustomElementTagNameRegExp: '^live-reload$' + allowedCustomElementAttributeNameRegExp: '^live-reload-(epoch|request-id)$' diff --git a/packages/techdocs-cli-embedded-app/src/App.tsx b/packages/techdocs-cli-embedded-app/src/App.tsx index 273a828b4a..13d5b925f0 100644 --- a/packages/techdocs-cli-embedded-app/src/App.tsx +++ b/packages/techdocs-cli-embedded-app/src/App.tsx @@ -36,6 +36,7 @@ import * as plugins from './plugins'; import { configLoader } from './config'; import { Root } from './components/Root'; import { techDocsPage, TechDocsThemeToggle } from './components/TechDocsPage'; +import { TechDocsLiveReload } from './LiveReloadAddon'; const app = createApp({ apis, @@ -54,6 +55,14 @@ const ThemeToggleAddon = techdocsPlugin.provide( }), ); +const LiveReloadAddon = techdocsPlugin.provide( + createTechDocsAddonExtension({ + name: 'LiveReloadAddon', + component: TechDocsLiveReload, + location: TechDocsAddonLocations.Content, + }), +); + const routes = ( @@ -71,6 +80,7 @@ const routes = ( > {techDocsPage} + diff --git a/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.test.tsx b/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.test.tsx new file mode 100644 index 0000000000..1a80def9e9 --- /dev/null +++ b/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.test.tsx @@ -0,0 +1,111 @@ +/* + * 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 { render } from '@testing-library/react'; +import { TechDocsLiveReload } from './LiveReloadAddon'; + +jest.mock('@backstage/plugin-techdocs-react', () => ({ + useShadowRootElements: jest.fn(() => [ + { + querySelector: jest.fn((selector: string) => { + if (selector === 'live-reload') { + return { + getAttribute: (name: string) => { + if (name === 'live-reload-epoch') return '10'; + if (name === 'live-reload-request-id') return '1'; + return null; + }, + }; + } + return null; + }), + }, + ]), +})); + +describe('TechDocsLiveReload', () => { + const originalXHR = global.XMLHttpRequest; + let originalLocation: Location; + let openSpy: jest.Mock; + let sendSpy: jest.Mock; + + beforeEach(() => { + originalLocation = window.location; + openSpy = jest.fn(); + sendSpy = jest.fn(function (this: any) { + // simulate long-poll response that does NOT trigger reload (epoch unchanged) + setTimeout(() => { + (this as any).status = 200; + (this as any).responseText = '10'; + (this as any).onloadend?.call(this); + }, 0); + }); + + class MockXHR { + onloadend: ((this: any) => void) | null = null; + status = 0; + responseText = ''; + open = openSpy; + send = sendSpy as any; + abort = jest.fn(); + } + + global.XMLHttpRequest = MockXHR as any; + + // Replace window.location with a mutable object for tests + delete (window as any).location; + (window as any).location = { ...originalLocation, reload: jest.fn() }; + jest.spyOn(window, 'addEventListener').mockImplementation(() => {}); + jest.spyOn(window, 'removeEventListener').mockImplementation(() => {}); + Object.defineProperty(document, 'visibilityState', { + value: 'visible', + configurable: true, + }); + }); + + afterEach(() => { + global.XMLHttpRequest = originalXHR; + jest.restoreAllMocks(); + // restore original window.location + delete (window as any).location; + (window as any).location = originalLocation; + }); + + it('polls livereload endpoint and does not reload when epoch unchanged', async () => { + const reloadSpy = window.location.reload as unknown as jest.Mock; + render(); + expect(openSpy).toHaveBeenCalledWith('GET', '/.livereload/10/1'); + // give microtask queue a tick + await new Promise(res => setTimeout(res, 0)); + expect(reloadSpy).not.toHaveBeenCalled(); + }); + + it('reloads when server epoch increases', async () => { + const reloadSpy = window.location.reload as unknown as jest.Mock; + + sendSpy.mockImplementation(function (this: any) { + setTimeout(() => { + (this as any).status = 200; + (this as any).responseText = '11'; + (this as any).onloadend?.call(this); + }, 0); + }); + + render(); + await new Promise(res => setTimeout(res, 0)); + expect(reloadSpy).toHaveBeenCalled(); + }); +}); diff --git a/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.tsx b/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.tsx new file mode 100644 index 0000000000..905a339c72 --- /dev/null +++ b/packages/techdocs-cli-embedded-app/src/LiveReloadAddon.tsx @@ -0,0 +1,121 @@ +/* + * 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 { useShadowRootElements } from '@backstage/plugin-techdocs-react'; +import { useEffect, useRef } from 'react'; + +interface TechDocsLiveReloadProps { + /** Whether to enable livereload (default: true in development) */ + enabled?: boolean; +} + +/** + * LiveReload addon for Techdocs CLI. + * + * Support mkdocs built-in livereload, in a TechDocs CLI preview environment. + * See https://github.com/backstage/backstage/issues/30514 for more details. + */ +export const TechDocsLiveReload = ({ + enabled = true, +}: TechDocsLiveReloadProps) => { + const body = useShadowRootElements(['body']); + const reqRef = useRef(null); + const timeoutRef = useRef(null); + const LIVE_RELOAD_ELEMENT = 'live-reload'; + const LIVE_RELOAD_ATTR_EPOCH = 'live-reload-epoch'; + const LIVE_RELOAD_ATTR_REQUEST_ID = 'live-reload-request-id'; + const CLI_LIVERELOAD_PATH = '/.livereload'; + + useEffect(() => { + if (!enabled || !body[0]) { + return undefined; + } + + const liveReloadElement = body[0].querySelector(LIVE_RELOAD_ELEMENT); + + if (!liveReloadElement) { + return undefined; + } + + const epoch = parseInt( + liveReloadElement.getAttribute(LIVE_RELOAD_ATTR_EPOCH) || '0', + 10, + ); + const requestId = parseInt( + liveReloadElement.getAttribute(LIVE_RELOAD_ATTR_REQUEST_ID) || '0', + 10, + ); + + if (!epoch || !requestId) { + return undefined; + } + + const livereloadUrl = CLI_LIVERELOAD_PATH; + + const poll = () => { + reqRef.current = new XMLHttpRequest(); + reqRef.current.onloadend = function handleLoadEnd(this: XMLHttpRequest) { + if (parseFloat(this.responseText) > epoch) { + window.location.reload(); + } else { + timeoutRef.current = setTimeout(poll, this.status === 200 ? 0 : 3000); + } + }; + reqRef.current.open('GET', `${livereloadUrl}/${epoch}/${requestId}`); + reqRef.current.send(); + }; + + const stop = () => { + if (reqRef.current) { + reqRef.current.abort(); + reqRef.current = null; + } + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + timeoutRef.current = null; + } + }; + + // Stop when tab is inactive + const handleVisibilityChange = () => { + if (document.visibilityState === 'visible') { + poll(); + } else { + stop(); + } + }; + + const handleBeforeUnload = () => { + stop(); + }; + + // Start polling if page is visible + if (document.visibilityState === 'visible') { + poll(); + } + + document.addEventListener('visibilitychange', handleVisibilityChange); + window.addEventListener('beforeunload', handleBeforeUnload); + + return () => { + stop(); + document.removeEventListener('visibilitychange', handleVisibilityChange); + window.removeEventListener('beforeunload', handleBeforeUnload); + }; + }, [body, enabled]); + + return null; +}; diff --git a/packages/techdocs-cli/src/lib/httpServer.ts b/packages/techdocs-cli/src/lib/httpServer.ts index c38bc86d7a..d7e8f62ea0 100644 --- a/packages/techdocs-cli/src/lib/httpServer.ts +++ b/packages/techdocs-cli/src/lib/httpServer.ts @@ -18,6 +18,10 @@ import serveHandler from 'serve-handler'; import http from 'http'; import httpProxy from 'http-proxy'; import { createLogger } from './utility'; +import { + proxyHtmlWithLivereloadInjection, + proxyMkdocsLivereload, +} from './livereload'; export default class HTTPServer { private readonly proxyEndpoint: string; @@ -59,8 +63,8 @@ export default class HTTPServer { const proxyHandler = this.createProxy(); const server = http.createServer( (request: http.IncomingMessage, response: http.ServerResponse) => { - // This endpoind is used by the frontend to issue a cookie for the user. - // But the MkDocs server doesn't expose it as a the Backestage backend does. + // This endpoint is used by the frontend to issue a cookie for the user. + // But the MkDocs server doesn't expose it as a the Backstage backend does. // So we need to fake it here to prevent 404 errors. if (request.url === '/api/techdocs/.backstage/auth/v1/cookie') { const oneHourInMilliseconds = 60 * 60 * 1000; @@ -72,6 +76,19 @@ export default class HTTPServer { } if (request.url?.startsWith(this.proxyEndpoint)) { + // Handle HTML files with livereload parameter injection + if (request.url?.endsWith('.html')) { + proxyHtmlWithLivereloadInjection({ + request, + response, + mkdocsTargetAddress: this.mkdocsTargetAddress, + proxyEndpoint: this.proxyEndpoint, + onError: (error: Error) => reject(error), + }); + return; + } + + // Handle non-HTML files with regular proxy const [proxy, forwardPath] = proxyHandler(request); proxy.on('error', (error: Error) => { @@ -93,6 +110,17 @@ export default class HTTPServer { return; } + // This endpoint is used by the frontend to pass livereload requests to the mkdocs server. + if (request.url?.startsWith('/.livereload')) { + proxyMkdocsLivereload({ + request, + response, + mkdocsTargetAddress: this.mkdocsTargetAddress, + onError: (error: Error) => reject(error), + }); + return; + } + serveHandler(request, response, { public: this.backstageBundleDir, trailingSlash: true, diff --git a/packages/techdocs-cli/src/lib/livereload.test.ts b/packages/techdocs-cli/src/lib/livereload.test.ts new file mode 100644 index 0000000000..b21251c45a --- /dev/null +++ b/packages/techdocs-cli/src/lib/livereload.test.ts @@ -0,0 +1,180 @@ +/* + * 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 http from 'http'; +import { + injectLivereloadParameters, + proxyHtmlWithLivereloadInjection, + proxyMkdocsLivereload, +} from './livereload'; + +// Note: This mock returns a singleton proxy object so tests can access the +// registered event handlers (e.g. `proxyRes`) from code under test. +jest.mock('http-proxy', () => { + const handlers: Record = {}; + const fakeProxy = { + on: jest.fn((event: string, cb: Function) => { + handlers[event] = cb; + }), + web: jest.fn((_req: unknown, _res: unknown) => { + // no-op; tests will manually trigger handlers['proxyRes'] when needed + }), + __handlers: handlers, + }; + const create = jest.fn(() => fakeProxy); + return { + __esModule: true, + default: { createProxyServer: create }, + createProxyServer: create, + }; +}); + +describe('livereload helpers', () => { + describe('injectLivereloadParameters', () => { + it('injects live-reload element when mkdocs script is present', () => { + const html = + ''; + const result = injectLivereloadParameters(html); + expect(result).toContain(''); + }); + + it('returns original html when mkdocs script is absent', () => { + const html = '

No livereload

'; + const result = injectLivereloadParameters(html); + expect(result).toBe(html); + }); + }); + + describe('proxyHtmlWithLivereloadInjection', () => { + it('injects parameters into HTML responses and sets CORS headers', () => { + const { createProxyServer } = jest.requireMock('http-proxy') as any; + const proxy = createProxyServer(); + + const req = { + url: '/api/techdocs/some/path/index.html', + } as unknown as http.IncomingMessage; + const headers: Record = {}; + const res = { + setHeader: (k: string, v: any) => { + headers[k] = String(v); + }, + end: jest.fn(), + } as unknown as http.ServerResponse; + + proxyHtmlWithLivereloadInjection({ + request: req, + response: res, + mkdocsTargetAddress: 'http://localhost:8000', + proxyEndpoint: '/api/techdocs/', + onError: () => {}, + }); + + // Simulate mkdocs proxy response with HTML + const proxyRes: any = { + headers: { 'content-type': 'text/html; charset=utf-8' }, + on: (event: string, cb: Function) => { + if (event === 'data') { + cb(''); + } + if (event === 'end') { + cb(); + } + }, + pipe: jest.fn(), + }; + + (proxy as any).__handlers.proxyRes(proxyRes, {} as any, res); + + expect(res.end).toHaveBeenCalled(); + const injectedHtml = (res.end as jest.Mock).mock.calls[0][0] as string; + expect(injectedHtml).toContain(' { + const { createProxyServer } = jest.requireMock('http-proxy') as any; + const proxy = createProxyServer(); + + const req = { + url: '/api/techdocs/some/path/asset.css', + } as unknown as http.IncomingMessage; + const headers: Record = {}; + const res = { + setHeader: (k: string, v: any) => { + headers[k] = String(v); + }, + end: jest.fn(), + } as unknown as http.ServerResponse; + + proxyHtmlWithLivereloadInjection({ + request: req, + response: res, + mkdocsTargetAddress: 'http://localhost:8000', + proxyEndpoint: '/api/techdocs/', + onError: () => {}, + }); + + const proxyRes: any = { + headers: { 'content-type': 'text/css' }, + on: jest.fn(), + pipe: jest.fn(), + }; + + (proxy as any).__handlers.proxyRes(proxyRes, {} as any, res); + + expect(res.end).not.toHaveBeenCalled(); + expect(proxyRes.pipe).toHaveBeenCalledWith(res); + expect(headers['Access-Control-Allow-Origin']).toBe('*'); + expect(headers['Access-Control-Allow-Methods']).toBe('GET, OPTIONS'); + }); + }); + + describe('proxyMkdocsLivereload', () => { + it('rewrites path and sets CORS headers', () => { + const { createProxyServer } = jest.requireMock('http-proxy') as any; + const proxy = createProxyServer(); + + const req = { + url: '/.livereload/1/2', + } as unknown as http.IncomingMessage; + const headers: Record = {}; + const res = { + setHeader: (k: string, v: any) => { + headers[k] = String(v); + }, + } as unknown as http.ServerResponse; + + proxyMkdocsLivereload({ + request: req, + response: res, + mkdocsTargetAddress: 'http://localhost:8000', + onError: () => {}, + }); + + expect(req.url).toBe('/livereload/1/2'); + expect(headers['Access-Control-Allow-Origin']).toBe('*'); + expect(headers['Access-Control-Allow-Methods']).toBe('GET, OPTIONS'); + expect(headers['Access-Control-Allow-Headers']).toBe('Content-Type'); + expect((proxy as any).web).toHaveBeenCalled(); + }); + }); +}); diff --git a/packages/techdocs-cli/src/lib/livereload.ts b/packages/techdocs-cli/src/lib/livereload.ts new file mode 100644 index 0000000000..c108971b82 --- /dev/null +++ b/packages/techdocs-cli/src/lib/livereload.ts @@ -0,0 +1,175 @@ +/* + * 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 http from 'http'; +import httpProxy from 'http-proxy'; + +/** + * Livereload support for techdocs-cli. + * + * Context: + * - MkDocs implements autoreload using a long-poll endpoint `/livereload` and a script that injects + * a call like: `livereload(epoch, request_id)`, where `epoch` is derived from Python's + * `time.monotonic()`. + * - Node.js monotonic clocks (`process.hrtime`/`performance.now`) are not compatible with Python's + * value across processes and platforms. We therefore CANNOT reliably re-create the same epoch on + * the frontend or in this CLI, and must read the values produced by MkDocs itself. + * - The MkDocs script tag is removed by DOM sanitization (DomPurify) in TechDocs, so we can't rely + * on the script being present in the embedded app. To bridge this, we extract the parameters on + * the server side while proxying HTML and inject them as a safe custom element that survives + * sanitization: ``. + * - The frontend addon reads that element and polls `/.livereload` (served by techdocs-cli), which + * this module maps to MkDocs `/livereload` with permissive CORS headers. + * - Quality-of-life: if extraction fails or the endpoint is unavailable, normal docs still work. + * + * See issue for background and rationale: https://github.com/backstage/backstage/issues/30514 + */ + +const LIVE_RELOAD_ELEMENT = 'live-reload'; +const LIVE_RELOAD_ATTR_EPOCH = 'live-reload-epoch'; +const LIVE_RELOAD_ATTR_REQUEST_ID = 'live-reload-request-id'; +const CLI_LIVERELOAD_PATH = '/.livereload'; +const MKDOCS_LIVERELOAD_PATH = '/livereload'; +const CONTENT_TYPE_HTML = 'text/html'; +const HEADER_CONTENT_LENGTH = 'content-length'; + +const BODY_START_RE = /]*>/; +// Matches mkdocs injected call livereload(epoch, requestId) +const MKDOCS_LIVERELOAD_CALL_RE = /livereload\(\s*(\d+)\s*,\s*(\d+)\s*\)\s*;?/; + +/** + * Extract livereload parameters from mkdocs HTML and inject them as a custom element. + * The injected element will later be read by the frontend addon even after DOM sanitization. + * + * Note: + * - we don't add to because of DomPurify sanitization. + * - we add close to the body opening to avoid reading too far into the body. + * - we should use streamed injection to improve performance. + */ +export function injectLivereloadParameters(html: string): string { + const livereloadMatch = html.match(MKDOCS_LIVERELOAD_CALL_RE); + + // If we couldn't find livereload parameters, return original HTML untouched. + if (!livereloadMatch) { + return html; + } + + const [, epoch, requestId] = livereloadMatch; + // Insert a minimal custom element that the frontend addon can discover post-sanitization. + // Note: embedded app needs a custom config to allow the element to survive sanitization. + const liveReloadTag = `<${LIVE_RELOAD_ELEMENT} ${LIVE_RELOAD_ATTR_EPOCH}="${epoch}" ${LIVE_RELOAD_ATTR_REQUEST_ID}="${requestId}">`; + + // Naively find where to insert the livereload tag. + const bodyStart = html.match(BODY_START_RE); + const bodyStartIndex = bodyStart?.index ?? 0; + const bodyStartLength = bodyStart?.[0]?.length ?? 0; + if (bodyStartIndex === 0 || bodyStartLength === 0) { + return html; + } + const bodyEndIndex = bodyStartIndex + bodyStartLength; + + return html.slice(0, bodyEndIndex) + liveReloadTag + html.slice(bodyEndIndex); +} + +function setCorsHeaders(response: http.ServerResponse) { + response.setHeader('Access-Control-Allow-Origin', '*'); + response.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS'); +} + +/** + * Proxies a mkdocs HTML response, injecting livereload parameters into the HTML body. + */ +export function proxyHtmlWithLivereloadInjection(options: { + request: http.IncomingMessage; + response: http.ServerResponse; + mkdocsTargetAddress: string; + proxyEndpoint: string; + onError: (error: Error) => void; +}): void { + const { request, response, mkdocsTargetAddress, proxyEndpoint, onError } = + options; + + const htmlProxy = httpProxy.createProxyServer({ + target: mkdocsTargetAddress, + selfHandleResponse: true, + }); + + htmlProxy.on('error', onError); + + // Intercept HTML responses to inject `` + htmlProxy.on('proxyRes', (proxyRes, _req, res) => { + const contentType = proxyRes.headers['content-type']; + const contentEncoding = proxyRes.headers['content-encoding']; + const isHtml = + contentType && + typeof contentType === 'string' && + contentType.startsWith(CONTENT_TYPE_HTML); + if (isHtml && !contentEncoding) { + const chunks: Buffer[] = []; + proxyRes.on('data', (chunk: Buffer | string) => { + chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); + }); + proxyRes.on('end', () => { + const body = Buffer.concat(chunks).toString('utf8'); + const modifiedHtml = injectLivereloadParameters(body); + res.statusCode = (proxyRes.statusCode as number | undefined) ?? 200; + Object.keys(proxyRes.headers).forEach(key => { + if (key.toLowerCase() !== HEADER_CONTENT_LENGTH) { + res.setHeader(key, proxyRes.headers[key]!); + } + }); + setCorsHeaders(res); + res.end(modifiedHtml); + }); + } else { + res.statusCode = (proxyRes.statusCode as number | undefined) ?? 200; + Object.keys(proxyRes.headers).forEach(key => { + res.setHeader(key, proxyRes.headers[key]!); + }); + setCorsHeaders(res); + proxyRes.pipe(res); + } + }); + + const forwardPath = + request.url?.replace(new RegExp(`^${proxyEndpoint}`, 'i'), '') || ''; + request.url = forwardPath; + htmlProxy.web(request, response); +} + +/** + * Proxies mkdocs livereload long-polling requests, mapping the CLI path to mkdocs path. + */ +export function proxyMkdocsLivereload(options: { + request: http.IncomingMessage; + response: http.ServerResponse; + mkdocsTargetAddress: string; + onError: (error: Error) => void; +}): void { + const { request, response, mkdocsTargetAddress, onError } = options; + + const proxy = httpProxy.createProxyServer({ target: mkdocsTargetAddress }); + proxy.on('error', onError); + + setCorsHeaders(response); + response.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + + request.url = request.url?.replace( + CLI_LIVERELOAD_PATH, + MKDOCS_LIVERELOAD_PATH, + ); + proxy.web(request, response); +} From 1013eb72cb06d431ee3a8f02fa6b95f538730ea1 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 17:04:39 +0200 Subject: [PATCH 100/244] Revert "frontend-test-utils: render the element as Page" This reverts commit 23c72e7e6537dfc972a5b16486cf8d517ddd32bb. Signed-off-by: Vincenzo Scamporlino --- .../src/app/renderInTestApp.test.tsx | 41 +++++++------------ .../src/app/renderInTestApp.tsx | 21 ++++++---- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx index 4da1c4632c..8e1b1e1ea0 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.test.tsx @@ -20,19 +20,15 @@ import { MockAnalyticsApi, TestApiProvider, } from '@backstage/frontend-test-utils'; -import { - analyticsApiRef, - PageBlueprint, - useAnalytics, -} from '@backstage/frontend-plugin-api'; +import { analyticsApiRef, useAnalytics } from '@backstage/frontend-plugin-api'; +import { Routes, Route } from 'react-router-dom'; import { renderInTestApp } from './renderInTestApp'; -import { Route, Routes } from 'react-router-dom'; describe('renderInTestApp', () => { it('should render the given component in a page', async () => { const IndexPage = () =>
Index Page
; renderInTestApp(); - expect(await screen.findByText('Index Page')).toBeInTheDocument(); + expect(screen.getByText('Index Page')).toBeInTheDocument(); }); it('should works with apis provider', async () => { @@ -59,7 +55,7 @@ describe('renderInTestApp', () => { , ); - fireEvent.click(await screen.findByRole('link', { name: 'See details' })); + fireEvent.click(screen.getByRole('link', { name: 'See details' })); expect(analyticsApiMock.getEvents()).toEqual( expect.arrayContaining([ @@ -72,25 +68,16 @@ describe('renderInTestApp', () => { }); it('should support setting different locations in the history stack', async () => { - renderInTestApp(

Index page

, { - extensions: [ - PageBlueprint.make({ - name: 'second-page', - params: defineParams => - defineParams({ - path: '/second-page', - loader: async () => ( - - Second page} /> - Subpage} /> - - ), - }), - }), - ], - initialRouteEntries: ['/second-page/subpage'], - }); + renderInTestApp( + + Index Page} /> + Second Page} /> + , + { + initialRouteEntries: ['/second-page'], + }, + ); - expect(await screen.findByText('Subpage')).toBeInTheDocument(); + expect(screen.getByText('Second Page')).toBeInTheDocument(); }); }); diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index 8f52f349fe..e1b35eba6c 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -31,7 +31,6 @@ import { NavItemBlueprint, createFrontendPlugin, FrontendFeature, - PageBlueprint, } from '@backstage/frontend-plugin-api'; import appPlugin from '@backstage/plugin-app'; @@ -108,6 +107,12 @@ const appPluginOverride = appPlugin.withOverrides({ appPlugin.getExtension('sign-in-page:app').override({ disabled: true, }), + appPlugin.getExtension('app/layout').override({ + disabled: true, + }), + appPlugin.getExtension('app/routes').override({ + disabled: true, + }), appPlugin.getExtension('app/nav').override({ output: [coreExtensionData.reactElement], factory(_originalFactory, { inputs }) { @@ -147,6 +152,13 @@ export function renderInTestApp( options?: TestAppOptions, ): RenderResult { const extensions: Array = [ + createExtension({ + attachTo: { id: 'app/root', input: 'children' }, + output: [coreExtensionData.reactElement], + factory: () => { + return [coreExtensionData.reactElement(element)]; + }, + }), RouterBlueprint.make({ params: { component: ({ children }) => ( @@ -185,13 +197,6 @@ export function renderInTestApp( extensions.push(...options.extensions); } - extensions.push( - PageBlueprint.make({ - name: 'mocked-root-page', - params: define => define({ path: '/', loader: async () => element }), - }), - ); - const features: FrontendFeature[] = [ createFrontendPlugin({ pluginId: 'test', From 898859f41b40615691642802593a7b816262c077 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 20:56:58 +0200 Subject: [PATCH 101/244] frontend-plugin-api: migrate to renderTestApp Signed-off-by: Vincenzo Scamporlino --- .../AppRootWrapperBlueprint.test.tsx | 16 ++++---- .../SwappableComponentBlueprint.test.tsx | 38 +++++++------------ 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.test.tsx index b4ad8ed2d2..0f26af3243 100644 --- a/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/blueprints/AppRootWrapperBlueprint.test.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +import { Fragment } from 'react'; import { AppRootWrapperBlueprint } from './AppRootWrapperBlueprint'; import { screen, waitFor } from '@testing-library/react'; import { @@ -21,7 +21,7 @@ import { createExtension, createExtensionInput, } from '../wiring'; -import { renderInTestApp } from '@backstage/frontend-test-utils'; +import { renderTestApp } from '@backstage/frontend-test-utils'; describe('AppRootWrapperBlueprint', () => { it('should return an extension with sensible defaults', () => { @@ -63,7 +63,7 @@ describe('AppRootWrapperBlueprint', () => { }, }); - renderInTestApp(
, { extensions: [extension] }); + renderTestApp({ extensions: [extension] }); await waitFor(() => expect(screen.getByText('Hello')).toBeInTheDocument()); }); @@ -83,16 +83,18 @@ describe('AppRootWrapperBlueprint', () => { component: ({ children }) => (
{children} - {inputs.children.flatMap(c => - c.get(coreExtensionData.reactElement), - )} + {inputs.children.flatMap((c, index) => ( + + {c.get(coreExtensionData.reactElement)} + + ))}
), }); }, }); - renderInTestApp(
, { + renderTestApp({ extensions: [ extension, createExtension({ diff --git a/packages/frontend-plugin-api/src/blueprints/SwappableComponentBlueprint.test.tsx b/packages/frontend-plugin-api/src/blueprints/SwappableComponentBlueprint.test.tsx index fae4bf7ebf..f51750b1e7 100644 --- a/packages/frontend-plugin-api/src/blueprints/SwappableComponentBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/blueprints/SwappableComponentBlueprint.test.tsx @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { renderInTestApp } from '@backstage/frontend-test-utils'; +import { renderTestApp } from '@backstage/frontend-test-utils'; import { createSwappableComponent } from '../components'; import { SwappableComponentBlueprint } from './SwappableComponentBlueprint'; import { PageBlueprint } from './PageBlueprint'; -import { waitFor, screen } from '@testing-library/react'; +import { screen } from '@testing-library/react'; describe('SwappableComponentBlueprint', () => { it('should allow defining a component override for a component ref', () => { @@ -48,21 +48,19 @@ describe('SwappableComponentBlueprint', () => { loader: () => (props: { hello: string }) =>
{props.hello}
, }); - renderInTestApp(
, { + renderTestApp({ extensions: [ PageBlueprint.make({ params: define => define({ - // todo(blam): there's a bug that this path cannot be `/`? - path: '/test', + path: '/', loader: async () => , }), }), ], - initialRouteEntries: ['/test'], }); - await waitFor(() => expect(screen.getByText('test!')).toBeInTheDocument()); + expect(await screen.findByText('test!')).toBeInTheDocument(); }); it('should render a component ref without a default implementation', async () => { @@ -70,22 +68,19 @@ describe('SwappableComponentBlueprint', () => { id: 'test.component', }); - renderInTestApp(
, { + renderTestApp({ extensions: [ PageBlueprint.make({ params: define => define({ - path: '/test', + path: '/', loader: async () => , }), }), ], - initialRouteEntries: ['/test'], }); - await waitFor(() => - expect(screen.getByTestId('test.component')).toBeInTheDocument(), - ); + expect(await screen.findByTestId('test.component')).toBeInTheDocument(); }); it('should render a component ref with an async loader implementation', async () => { @@ -95,21 +90,20 @@ describe('SwappableComponentBlueprint', () => {
{props.hello}
, }); - renderInTestApp(
, { + renderTestApp({ extensions: [ PageBlueprint.make({ params: define => define({ // todo(blam): there's a bug that this path cannot be `/`? - path: '/test', + path: '/', loader: async () => , }), }), ], - initialRouteEntries: ['/test'], }); - await waitFor(() => expect(screen.getByText('test!')).toBeInTheDocument()); + expect(await screen.findByText('test!')).toBeInTheDocument(); }); it('should render a component ref with an async loader implementation and prop transform', async () => { @@ -120,22 +114,18 @@ describe('SwappableComponentBlueprint', () => { transformProps: ({ hello }) => ({ hello: `tr ${hello}` }), }); - renderInTestApp(
, { + renderTestApp({ extensions: [ PageBlueprint.make({ params: define => define({ - // todo(blam): there's a bug that this path cannot be `/`? - path: '/test', + path: '/', loader: async () => , }), }), ], - initialRouteEntries: ['/test'], }); - await waitFor(() => - expect(screen.getByText('tr test!')).toBeInTheDocument(), - ); + expect(await screen.findByText('tr test!')).toBeInTheDocument(); }); }); From 4a494abf78cec101e8bbabd04d05aa96b3a25a76 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 20:57:39 +0200 Subject: [PATCH 102/244] frontend-test-utils: introduce renderTestApp and mark features option as deprecated Signed-off-by: Vincenzo Scamporlino --- packages/frontend-test-utils/src/app/index.ts | 1 + .../src/app/renderInTestApp.tsx | 2 + .../src/app/renderTestApp.tsx | 81 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 packages/frontend-test-utils/src/app/renderTestApp.tsx diff --git a/packages/frontend-test-utils/src/app/index.ts b/packages/frontend-test-utils/src/app/index.ts index 6c6ef26e4c..9db67dbb49 100644 --- a/packages/frontend-test-utils/src/app/index.ts +++ b/packages/frontend-test-utils/src/app/index.ts @@ -21,3 +21,4 @@ export { } from './createExtensionTester'; export { renderInTestApp, type TestAppOptions } from './renderInTestApp'; +export { renderTestApp, type RenderTestAppOptions } from './renderTestApp'; diff --git a/packages/frontend-test-utils/src/app/renderInTestApp.tsx b/packages/frontend-test-utils/src/app/renderInTestApp.tsx index e1b35eba6c..2b8efb643f 100644 --- a/packages/frontend-test-utils/src/app/renderInTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderInTestApp.tsx @@ -69,6 +69,8 @@ export type TestAppOptions = { /** * Additional extensions to add to the test app. + * + * @deprecated Use `renderTestApp` instead. */ extensions?: ExtensionDefinition[]; diff --git a/packages/frontend-test-utils/src/app/renderTestApp.tsx b/packages/frontend-test-utils/src/app/renderTestApp.tsx new file mode 100644 index 0000000000..1644ee1c30 --- /dev/null +++ b/packages/frontend-test-utils/src/app/renderTestApp.tsx @@ -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 { createSpecializedApp } from '@backstage/frontend-app-api'; +import { + coreExtensionData, + createFrontendPlugin, + ExtensionDefinition, + FrontendFeature, +} from '@backstage/frontend-plugin-api'; +import { render } from '@testing-library/react'; +import appPlugin from '@backstage/plugin-app'; +import { JsonObject } from '@backstage/types'; +import { ConfigReader } from '@backstage/config'; + +export type RenderTestAppOptions = { + /** + * Additional configuration passed to the app when rendering elements inside it. + */ + config?: JsonObject; + /** + * Additional extensions to add to the test app. + */ + extensions: ExtensionDefinition[]; + + /** + * Additional features to add to the test app. + */ + features?: FrontendFeature[]; +}; + +const appPluginOverride = appPlugin.withOverrides({ + extensions: [ + appPlugin.getExtension('sign-in-page:app').override({ + disabled: true, + }), + ], +}); + +export function renderTestApp(options: RenderTestAppOptions) { + const features: FrontendFeature[] = [ + createFrontendPlugin({ + pluginId: 'test', + extensions: options.extensions, + }), + appPluginOverride, + ]; + + if (options.features) { + features.push(...options.features); + } + + const app = createSpecializedApp({ + features, + config: options.config + ? ConfigReader.fromConfigs([ + { + context: 'render-config', + data: options.config, + }, + ]) + : undefined, + }); + + return render( + app.tree.root.instance!.getData(coreExtensionData.reactElement), + ); +} From 7db384cef28fb61a113c7624de6c1c2800eff4d7 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 20:58:42 +0200 Subject: [PATCH 103/244] app: migrate to renderTestApp Signed-off-by: Vincenzo Scamporlino --- .../DefaultSwappableComponentsApi.test.tsx | 81 ++++++++++++++++--- .../app/src/extensions/DialogDisplay.test.tsx | 4 +- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/plugins/app/src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx b/plugins/app/src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx index 07ef891926..bdd81f338c 100644 --- a/plugins/app/src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx +++ b/plugins/app/src/apis/SwappableComponentsApi/DefaultSwappableComponentsApi.test.tsx @@ -16,6 +16,7 @@ import { ApiBlueprint, + AppRootElementBlueprint, createExtensionInput, createFrontendModule, createSwappableComponent, @@ -24,7 +25,7 @@ import { } from '@backstage/frontend-plugin-api'; import { DefaultSwappableComponentsApi } from './DefaultSwappableComponentsApi'; import { render, screen } from '@testing-library/react'; -import { renderInTestApp } from '@backstage/frontend-test-utils'; +import { renderInTestApp, renderTestApp } from '@backstage/frontend-test-utils'; const { ref: testRefA } = createSwappableComponent({ id: 'test.a' }); const { ref: testRefB1 } = createSwappableComponent({ id: 'test.b' }); @@ -149,8 +150,17 @@ describe('DefaultSwappableComponentsApi', () => { id: 'test.mock', }); - renderInTestApp(, { - extensions: [api], + renderTestApp({ + extensions: [ + AppRootElementBlueprint.make({ + name: 'derp', + params: define => + define({ + element: , + }), + }), + api, + ], }); await expect( @@ -164,8 +174,17 @@ describe('DefaultSwappableComponentsApi', () => { loader: () => () =>
test.mock
, }); - renderInTestApp(, { - extensions: [api], + renderTestApp({ + extensions: [ + AppRootElementBlueprint.make({ + name: 'derp', + params: define => + define({ + element: , + }), + }), + api, + ], }); await expect( @@ -179,8 +198,17 @@ describe('DefaultSwappableComponentsApi', () => { loader: async () => () =>
test.mock
, }); - renderInTestApp(, { - extensions: [api], + renderTestApp({ + extensions: [ + AppRootElementBlueprint.make({ + name: 'derp', + params: define => + define({ + element: , + }), + }), + api, + ], }); await expect( @@ -202,8 +230,17 @@ describe('DefaultSwappableComponentsApi', () => { }), }); - renderInTestApp(, { - extensions: [api], + renderTestApp({ + extensions: [ + AppRootElementBlueprint.make({ + name: 'derp', + params: define => + define({ + element: , + }), + }), + api, + ], features: [ createFrontendModule({ pluginId: 'app', @@ -231,8 +268,17 @@ describe('DefaultSwappableComponentsApi', () => { }), }); - renderInTestApp(, { - extensions: [api], + renderTestApp({ + extensions: [ + AppRootElementBlueprint.make({ + name: 'derp', + params: define => + define({ + element: , + }), + }), + api, + ], features: [ createFrontendModule({ pluginId: 'app', @@ -264,8 +310,17 @@ describe('DefaultSwappableComponentsApi', () => { }), }); - renderInTestApp(, { - extensions: [api], + renderTestApp({ + extensions: [ + AppRootElementBlueprint.make({ + name: 'derp', + params: define => + define({ + element: , + }), + }), + api, + ], features: [ createFrontendModule({ pluginId: 'app', diff --git a/plugins/app/src/extensions/DialogDisplay.test.tsx b/plugins/app/src/extensions/DialogDisplay.test.tsx index 8f7eb4e857..dbad551fcb 100644 --- a/plugins/app/src/extensions/DialogDisplay.test.tsx +++ b/plugins/app/src/extensions/DialogDisplay.test.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { renderInTestApp } from '@backstage/frontend-test-utils'; +import { renderTestApp } from '@backstage/frontend-test-utils'; import { act, useEffect } from 'react'; import { AppRootElementBlueprint, @@ -29,7 +29,7 @@ async function withDialogApi( callback: (dialogApi: DialogApi) => Promise, ) { const deferred = createDeferred(); - await renderInTestApp(
, { + await renderTestApp({ extensions: [ AppRootElementBlueprint.makeWithOverrides({ name: 'derp', From c41dd803c6cfe646054ca9b23a60a4025a930f99 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 21:04:00 +0200 Subject: [PATCH 104/244] frontend-test-utils: expand changeset Signed-off-by: Vincenzo Scamporlino --- .changeset/fluffy-cities-sip.md | 1 - .changeset/real-seals-dress.md | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .changeset/real-seals-dress.md diff --git a/.changeset/fluffy-cities-sip.md b/.changeset/fluffy-cities-sip.md index f6692d4e27..1f82540e38 100644 --- a/.changeset/fluffy-cities-sip.md +++ b/.changeset/fluffy-cities-sip.md @@ -1,5 +1,4 @@ --- -'@backstage/frontend-test-utils': patch '@backstage/plugin-app': patch --- diff --git a/.changeset/real-seals-dress.md b/.changeset/real-seals-dress.md new file mode 100644 index 0000000000..7606db6638 --- /dev/null +++ b/.changeset/real-seals-dress.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-test-utils': patch +--- + +Add a new utility `renderTestApp` to `@backstage/frontend-test-utils` that simplifies rendering extensions within the Backstage application context for testing purposes. This utility replaces the use of `renderInTestApp` when the `extensions` option is needed. From 6c23efd539d6938b3c03b8c4f3d38d533e6c8d81 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 21:44:36 +0200 Subject: [PATCH 105/244] frontend-test-utils: api-reports Signed-off-by: Vincenzo Scamporlino --- packages/frontend-test-utils/report.api.md | 13 +++++++++++++ .../frontend-test-utils/src/app/renderTestApp.tsx | 11 +++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/frontend-test-utils/report.api.md b/packages/frontend-test-utils/report.api.md index db31c082ea..58e5282f48 100644 --- a/packages/frontend-test-utils/report.api.md +++ b/packages/frontend-test-utils/report.api.md @@ -29,6 +29,7 @@ import { RouteRef } from '@backstage/frontend-plugin-api'; import { TestApiProvider } from '@backstage/test-utils'; import { TestApiProviderProps } from '@backstage/test-utils'; import { TestApiRegistry } from '@backstage/test-utils'; +import { testingLibraryDomTypesQueries } from '@testing-library/dom/types/queries'; import { withLogCollector } from '@backstage/test-utils'; export { ApiMock }; @@ -119,6 +120,18 @@ export function renderInTestApp( options?: TestAppOptions, ): RenderResult; +// @public +export function renderTestApp( + options: RenderTestAppOptions, +): RenderResult; + +// @public +export type RenderTestAppOptions = { + config?: JsonObject; + extensions: ExtensionDefinition[]; + features?: FrontendFeature[]; +}; + export { TestApiProvider }; export { TestApiProviderProps }; diff --git a/packages/frontend-test-utils/src/app/renderTestApp.tsx b/packages/frontend-test-utils/src/app/renderTestApp.tsx index 1644ee1c30..827d14283c 100644 --- a/packages/frontend-test-utils/src/app/renderTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderTestApp.tsx @@ -26,6 +26,11 @@ import appPlugin from '@backstage/plugin-app'; import { JsonObject } from '@backstage/types'; import { ConfigReader } from '@backstage/config'; +/** + * Options for `renderTestApp`. + * + * @public + */ export type RenderTestAppOptions = { /** * Additional configuration passed to the app when rendering elements inside it. @@ -50,6 +55,12 @@ const appPluginOverride = appPlugin.withOverrides({ ], }); +/** + * Renders the provided extensions inside a Backstage app, returning the same + * utilities as `@testing-library/react` `render` function. + * + * @public + */ export function renderTestApp(options: RenderTestAppOptions) { const features: FrontendFeature[] = [ createFrontendPlugin({ From 980bce1ff8fcc1434072a842b23723aa47403fa4 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 22:36:16 +0200 Subject: [PATCH 106/244] core-compat-api: use renderTestApp Signed-off-by: Vincenzo Scamporlino --- .../src/collectLegacyRoutes.test.tsx | 4 ++-- .../core-compat-api/src/convertLegacyApp.test.tsx | 14 +++++++------- packages/frontend-test-utils/report.api.md | 2 +- .../frontend-test-utils/src/app/renderTestApp.tsx | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx index fe4166016e..c5138dac3d 100644 --- a/packages/core-compat-api/src/collectLegacyRoutes.test.tsx +++ b/packages/core-compat-api/src/collectLegacyRoutes.test.tsx @@ -39,7 +39,7 @@ import { useApp, } from '@backstage/core-plugin-api'; import { screen } from '@testing-library/react'; -import { renderInTestApp } from '@backstage/frontend-test-utils'; +import { renderTestApp } from '@backstage/frontend-test-utils'; const exampleApiRef = createApiRef({ id: 'plugin.example.service', @@ -304,7 +304,7 @@ describe('collectLegacyRoutes', () => { , ); - renderInTestApp(
, { features }); + renderTestApp({ features }); await expect( screen.findByText('plugins: app, test'), diff --git a/packages/core-compat-api/src/convertLegacyApp.test.tsx b/packages/core-compat-api/src/convertLegacyApp.test.tsx index 7bbe13867c..1cb2b757e3 100644 --- a/packages/core-compat-api/src/convertLegacyApp.test.tsx +++ b/packages/core-compat-api/src/convertLegacyApp.test.tsx @@ -27,7 +27,7 @@ import { createRouteRef, } from '@backstage/core-plugin-api'; import { EntityLayout, EntitySwitch, isKind } from '@backstage/plugin-catalog'; -import { renderInTestApp } from '@backstage/frontend-test-utils'; +import { renderTestApp } from '@backstage/frontend-test-utils'; import { default as catalogPlugin } from '@backstage/plugin-catalog/alpha'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { catalogApiMock } from '@backstage/plugin-catalog-react/testUtils'; @@ -263,7 +263,7 @@ describe('convertLegacyApp', () => { }); // Overview - const renderOverviewTest = await renderInTestApp(
, { + const renderOverviewTest = await renderTestApp({ features: [catalogOverride, ...converted], initialRouteEntries: ['/catalog/default/test/x'], }); @@ -272,7 +272,7 @@ describe('convertLegacyApp', () => { ).resolves.toBeInTheDocument(); renderOverviewTest.unmount(); - const renderOverviewOther = await renderInTestApp(
, { + const renderOverviewOther = await renderTestApp({ features: [catalogOverride, ...converted], initialRouteEntries: ['/catalog/default/other/x'], }); @@ -282,7 +282,7 @@ describe('convertLegacyApp', () => { renderOverviewOther.unmount(); // Foo tab - const renderFooTest = await renderInTestApp(
, { + const renderFooTest = await renderTestApp({ features: [catalogOverride, ...converted], initialRouteEntries: ['/catalog/default/test/x/foo'], }); @@ -291,7 +291,7 @@ describe('convertLegacyApp', () => { ).resolves.toBeInTheDocument(); renderFooTest.unmount(); - const renderFooOther = await renderInTestApp(
, { + const renderFooOther = await renderTestApp({ features: [catalogOverride, ...converted], initialRouteEntries: ['/catalog/default/other/x/foo'], }); @@ -301,7 +301,7 @@ describe('convertLegacyApp', () => { renderFooOther.unmount(); // Bar tab - const renderBarTest = await renderInTestApp(
, { + const renderBarTest = await renderTestApp({ features: [catalogOverride, ...converted], initialRouteEntries: ['/catalog/default/test/x/bar'], }); @@ -310,7 +310,7 @@ describe('convertLegacyApp', () => { ).resolves.toBeInTheDocument(); renderBarTest.unmount(); - const renderBarOther = await renderInTestApp(
, { + const renderBarOther = await renderTestApp({ features: [catalogOverride, ...converted], initialRouteEntries: ['/catalog/default/other/x/bar'], }); diff --git a/packages/frontend-test-utils/report.api.md b/packages/frontend-test-utils/report.api.md index 58e5282f48..bd008feb19 100644 --- a/packages/frontend-test-utils/report.api.md +++ b/packages/frontend-test-utils/report.api.md @@ -128,7 +128,7 @@ export function renderTestApp( // @public export type RenderTestAppOptions = { config?: JsonObject; - extensions: ExtensionDefinition[]; + extensions?: ExtensionDefinition[]; features?: FrontendFeature[]; }; diff --git a/packages/frontend-test-utils/src/app/renderTestApp.tsx b/packages/frontend-test-utils/src/app/renderTestApp.tsx index 827d14283c..f19dcd7d5f 100644 --- a/packages/frontend-test-utils/src/app/renderTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderTestApp.tsx @@ -39,7 +39,7 @@ export type RenderTestAppOptions = { /** * Additional extensions to add to the test app. */ - extensions: ExtensionDefinition[]; + extensions?: ExtensionDefinition[]; /** * Additional features to add to the test app. From 116e05e29409250517a75ff5335d7e11eb6acfd4 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Tue, 7 Oct 2025 23:04:44 +0200 Subject: [PATCH 107/244] frontend-test-utils: add initialRouteEntries option Signed-off-by: Vincenzo Scamporlino --- packages/frontend-test-utils/report.api.md | 1 + .../src/app/renderTestApp.tsx | 41 +++++++++++++++---- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/packages/frontend-test-utils/report.api.md b/packages/frontend-test-utils/report.api.md index bd008feb19..b22fa6f808 100644 --- a/packages/frontend-test-utils/report.api.md +++ b/packages/frontend-test-utils/report.api.md @@ -130,6 +130,7 @@ export type RenderTestAppOptions = { config?: JsonObject; extensions?: ExtensionDefinition[]; features?: FrontendFeature[]; + initialRouteEntries?: string[]; }; export { TestApiProvider }; diff --git a/packages/frontend-test-utils/src/app/renderTestApp.tsx b/packages/frontend-test-utils/src/app/renderTestApp.tsx index f19dcd7d5f..e8d90cadd6 100644 --- a/packages/frontend-test-utils/src/app/renderTestApp.tsx +++ b/packages/frontend-test-utils/src/app/renderTestApp.tsx @@ -20,11 +20,18 @@ import { createFrontendPlugin, ExtensionDefinition, FrontendFeature, + RouterBlueprint, } from '@backstage/frontend-plugin-api'; import { render } from '@testing-library/react'; import appPlugin from '@backstage/plugin-app'; import { JsonObject } from '@backstage/types'; import { ConfigReader } from '@backstage/config'; +import { MemoryRouter } from 'react-router-dom'; + +const DEFAULT_MOCK_CONFIG = { + app: { baseUrl: 'http://localhost:3000' }, + backend: { baseUrl: 'http://localhost:7007' }, +}; /** * Options for `renderTestApp`. @@ -45,6 +52,11 @@ export type RenderTestAppOptions = { * Additional features to add to the test app. */ features?: FrontendFeature[]; + + /** + * Initial route entries to use for the router. + */ + initialRouteEntries?: string[]; }; const appPluginOverride = appPlugin.withOverrides({ @@ -62,10 +74,23 @@ const appPluginOverride = appPlugin.withOverrides({ * @public */ export function renderTestApp(options: RenderTestAppOptions) { + const extensions = [ + RouterBlueprint.make({ + params: { + component: ({ children }) => ( + + {children} + + ), + }, + }), + ...(options.extensions ?? []), + ]; + const features: FrontendFeature[] = [ createFrontendPlugin({ pluginId: 'test', - extensions: options.extensions, + extensions, }), appPluginOverride, ]; @@ -76,14 +101,12 @@ export function renderTestApp(options: RenderTestAppOptions) { const app = createSpecializedApp({ features, - config: options.config - ? ConfigReader.fromConfigs([ - { - context: 'render-config', - data: options.config, - }, - ]) - : undefined, + config: ConfigReader.fromConfigs([ + { + context: 'render-config', + data: options?.config ?? DEFAULT_MOCK_CONFIG, + }, + ]), }); return render( From 7dcedff2fbf180fda446563a31daedabf83bdeb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 8 Oct 2025 10:17:19 +0200 Subject: [PATCH 108/244] bump create-app sqlite version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/modern-cats-double.md | 5 +++++ .../templates/next-app/packages/backend/package.json.hbs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/modern-cats-double.md diff --git a/.changeset/modern-cats-double.md b/.changeset/modern-cats-double.md new file mode 100644 index 0000000000..0c5681aaad --- /dev/null +++ b/.changeset/modern-cats-double.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Bump `better-sqlite3` to the latest version diff --git a/packages/create-app/templates/next-app/packages/backend/package.json.hbs b/packages/create-app/templates/next-app/packages/backend/package.json.hbs index 483c0b7a4e..518683ffd7 100644 --- a/packages/create-app/templates/next-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/next-app/packages/backend/package.json.hbs @@ -44,7 +44,7 @@ "@backstage/plugin-signals-backend": "^{{version '@backstage/plugin-signals-backend'}}", "@backstage/plugin-techdocs-backend": "^{{version '@backstage/plugin-techdocs-backend'}}", "app": "link:../app", - "better-sqlite3": "^9.0.0", + "better-sqlite3": "^12.0.0", "node-gyp": "^10.0.0", "pg": "^8.11.3" }, From 74b810a301fb4065b159eada0fc6928499db69fd Mon Sep 17 00:00:00 2001 From: birdhb Date: Wed, 8 Oct 2025 10:37:44 +0100 Subject: [PATCH 109/244] Update .changeset/eighty-cows-care.md Co-authored-by: Patrik Oldsberg Signed-off-by: birdhb --- .changeset/eighty-cows-care.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/eighty-cows-care.md b/.changeset/eighty-cows-care.md index 73ec239b36..d4c9fafa4d 100644 --- a/.changeset/eighty-cows-care.md +++ b/.changeset/eighty-cows-care.md @@ -2,4 +2,4 @@ '@backstage/ui': minor --- -**Breaking** We are adding a new component `PasswordField`. We will be removing support for types `password` and `search` on `TextField`. +**BREAKING**: Added a new `PasswordField` component. As part of this change, the `password` and `search` types have been removed from `TextField`. From b2f6a5ab2441317b1c071611cf224bdf0211ff62 Mon Sep 17 00:00:00 2001 From: RedlineTriad <39059512+RedlineTriad@users.noreply.github.com> Date: Wed, 8 Oct 2025 09:50:11 +0000 Subject: [PATCH 110/244] fix: BitbuckerUrlReader ignoring provided token #31348 Signed-off-by: RedlineTriad <39059512+RedlineTriad@users.noreply.github.com> --- .changeset/warm-moments-repeat.md | 5 +++++ .../urlReader/lib/BitbucketUrlReader.test.ts | 21 +++++++++++++++++++ .../urlReader/lib/BitbucketUrlReader.ts | 16 +++++++++++++- 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 .changeset/warm-moments-repeat.md diff --git a/.changeset/warm-moments-repeat.md b/.changeset/warm-moments-repeat.md new file mode 100644 index 0000000000..a72387d720 --- /dev/null +++ b/.changeset/warm-moments-repeat.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-defaults': patch +--- + +Fix #31348 issue where BitbucketUrlReader ignored provided token and instead always used integration credentials diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts index 29217ea1f5..f06bf41953 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.test.ts @@ -130,6 +130,27 @@ describe('BitbucketUrlReader', () => { expect(buffer.toString()).toBe('foo'); }); + it('should be able to readUrl using provided token', async () => { + worker.use( + rest.get( + 'https://api.bitbucket.org/2.0/repositories/backstage-verification/test-template/src/master/template.yaml', + (req, res, ctx) => { + expect(req.headers.get('authorization')).toBe( + 'Bearer manual-token', + ); + return res(ctx.status(200), ctx.body('foo')); + }, + ), + ); + + const result = await bitbucketProcessor.readUrl( + 'https://bitbucket.org/backstage-verification/test-template/src/master/template.yaml', + { token: 'manual-token' }, + ); + const buffer = await result.buffer(); + expect(buffer.toString()).toBe('foo'); + }); + it('should be able to readUrl via stream without ETag', async () => { worker.use( rest.get( diff --git a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts index 4c6de31aa4..913c24c69f 100644 --- a/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts +++ b/packages/backend-defaults/src/entrypoints/urlReader/lib/BitbucketUrlReader.ts @@ -93,13 +93,27 @@ export class BitbucketUrlReader implements UrlReaderService { return response.buffer(); } + private getCredentials = async (options?: { + token?: string; + }): Promise<{ headers: Record }> => { + if (options?.token) { + return { + headers: { + Authorization: `Bearer ${options.token}`, + }, + }; + } + + return await getBitbucketRequestOptions(this.integration.config); + }; + async readUrl( url: string, options?: UrlReaderServiceReadUrlOptions, ): Promise { const { etag, lastModifiedAfter, signal } = options ?? {}; const bitbucketUrl = getBitbucketFileFetchUrl(url, this.integration.config); - const requestOptions = getBitbucketRequestOptions(this.integration.config); + const requestOptions = await this.getCredentials(options); let response: Response; try { From ed9729d2ee165404ac309c9628640d7ab42c0c63 Mon Sep 17 00:00:00 2001 From: Brent Swisher Date: Wed, 8 Oct 2025 11:11:00 -0400 Subject: [PATCH 111/244] Add dsn to output schema Signed-off-by: Brent Swisher --- .../src/actions/fetchDSN.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.ts b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.ts index d5078ce300..47fd4be39f 100644 --- a/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.ts +++ b/plugins/scaffolder-backend-module-sentry/src/actions/fetchDSN.ts @@ -52,6 +52,14 @@ export function createSentryFetchDSNAction(options: { config: Config }) { }) .optional(), }, + output: { + dsn: z => + z + .string({ + description: 'The public DSN of the Sentry project', + }) + .optional(), + }, }, async handler(ctx) { const { organizationSlug, projectSlug, authToken } = ctx.input; From 9e085a2acc40679cd3c50bf12f2ab5b36253352d Mon Sep 17 00:00:00 2001 From: Brent Swisher Date: Wed, 8 Oct 2025 11:18:40 -0400 Subject: [PATCH 112/244] Update API report with new output schema Signed-off-by: Brent Swisher --- plugins/scaffolder-backend-module-sentry/report.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend-module-sentry/report.api.md b/plugins/scaffolder-backend-module-sentry/report.api.md index 7e4701e609..6fbece93c8 100644 --- a/plugins/scaffolder-backend-module-sentry/report.api.md +++ b/plugins/scaffolder-backend-module-sentry/report.api.md @@ -35,7 +35,7 @@ export function createSentryFetchDSNAction(options: { authToken?: string | undefined; }, { - [x: string]: any; + dsn?: string | undefined; }, 'v2' >; From 019f3a64aa995252da1758289ae65faa9c0ea53e Mon Sep 17 00:00:00 2001 From: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:28:08 -0400 Subject: [PATCH 113/244] Create doc-landing-page.md using html for table (#30884) * Create doc-landing-page.md using html for table HTML is used for the tables in this new doc landing page. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md Changed id of documentation and corrected some spelling mistakes. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md rearrange table and add links Incorporated PR suggestions. Added trial links in two different flavors to see which way works. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md fix prettier spacing Changed all indents to 2 spaces to try to fix prettier errors. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md changed top to "top" for valign attribute Changed valign=top to valign="top" to see if it fixes prettier errors. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md changes double quotes to single quotes Changed all double quotes to single quotes and removed all hrefs to see if I can get the file to pass the prettier check. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md fix prettier errors Hopefully, fixed prettier errors by removing extra lines. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md try to fix prettier errors Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md added links for understanding, using, and administering backstage Added links for each of the bullet points in "Understanding Backstage", "Using Backstage" and "Backstage Administration". Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md added remainder of links Added links for additional features, plugin development, references, and contributing to Backstage. Changed "Scaffolder" bullet to "Software Templates (aka Scaffolder)" Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md to remove Update a Component The document explaining how to update a component has not yet been written. So removing this bullet until the updating documentation exists. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update docusaurus.config.ts for new doc landing page Changed landing page from What is Backstage to the new doc-landing-page.md file. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Update doc-landing-page.md added new technical overview Added a bullet under Learn about Backstage for the new Technical Overview. Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> * Apply suggestion from @aramissennyeydd Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> --------- Signed-off-by: milliehartnt123 <108491788+milliehartnt123@users.noreply.github.com> Signed-off-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> Co-authored-by: Aramis Sennyey <159921952+aramissennyeydd@users.noreply.github.com> --- docs/landing-page/doc-landing-page.md | 109 ++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 docs/landing-page/doc-landing-page.md diff --git a/docs/landing-page/doc-landing-page.md b/docs/landing-page/doc-landing-page.md new file mode 100644 index 0000000000..cb1b889851 --- /dev/null +++ b/docs/landing-page/doc-landing-page.md @@ -0,0 +1,109 @@ +--- +id: doc-landing-page +title: Documentation +description: Documentation landing page. +--- + +## Understand, try, and administer Backstage + + + + + + + + + + + + + + +
Understand BackstageTry BackstageAdministrationAdditional Features
Learn about Backstage.

+ +
Build a customizable Backstage app.
+ +
Configure, Deploy, & Upgrade.

+ +
Additional Backstage Features

+ +
+ +## Plugin Development, references, and how to contribute + + + + + + + + + + + + +
Plugin DevelopmentReferencesContribute to Backstage
Creating and Configuring Plugins

+ +
Glossary, FAQ, and other reference material.
+ +
Contributions are welcome and greatly appreciated!
+ +
From ee0e5b3257b50a9548f7d37d3422f45868878346 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Wed, 8 Oct 2025 17:46:15 +0200 Subject: [PATCH 114/244] docs: fix monospace font usage Signed-off-by: Vincenzo Scamporlino --- docs-ui/src/app/theming/page.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-ui/src/app/theming/page.mdx b/docs-ui/src/app/theming/page.mdx index 92b5256791..455b2cd7f5 100644 --- a/docs-ui/src/app/theming/page.mdx +++ b/docs-ui/src/app/theming/page.mdx @@ -446,7 +446,7 @@ monospace font that we use for code blocks and tables. - --bui-font-mono + --bui-font-monospace The monospace font for the theme. From 69729c759fe20291f135b754e42612889292ba3a Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 8 Oct 2025 17:16:06 +0100 Subject: [PATCH 115/244] Remove CSS baseline from UnifiedThemeProvider Signed-off-by: Charles de Dreuille --- .../theme/src/unified/UnifiedThemeProvider.tsx | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/packages/theme/src/unified/UnifiedThemeProvider.tsx b/packages/theme/src/unified/UnifiedThemeProvider.tsx index 64694aff37..45358c13da 100644 --- a/packages/theme/src/unified/UnifiedThemeProvider.tsx +++ b/packages/theme/src/unified/UnifiedThemeProvider.tsx @@ -15,7 +15,6 @@ */ import { ReactNode } from 'react'; -import CssBaseline from '@material-ui/core/CssBaseline'; import { ThemeProvider, StylesProvider, @@ -68,7 +67,7 @@ import { useApplyThemeAttributes } from './useApplyThemeAttributes'; export function UnifiedThemeProvider( props: UnifiedThemeProviderProps, ): JSX.Element { - const { children, theme, noCssBaseline = false } = props; + const { children, theme } = props; const v4Theme = theme.getTheme('v4') as Mui4Theme; const v5Theme = theme.getTheme('v5') as Mui5Theme; @@ -78,17 +77,7 @@ export function UnifiedThemeProvider( 'backstage', ); - let cssBaseline: JSX.Element | undefined = undefined; - if (!noCssBaseline) { - cssBaseline = ; - } - - let result = ( - <> - {cssBaseline} - {children} - - ); + let result = children as JSX.Element; if (v4Theme) { result = ( From c396392c5c2d70c3fe8f571b4a87e72bb5aea12f Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 8 Oct 2025 17:22:17 +0100 Subject: [PATCH 116/244] Fix body background Signed-off-by: Charles de Dreuille --- packages/ui/css/styles.css | 4 ++++ packages/ui/src/css/core.css | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index d93ba87829..61051fdf07 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -9098,6 +9098,10 @@ } } +body { + background-color: var(--bui-bg); +} + :root { --bui-font-regular: system-ui; --bui-font-monospace: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace; diff --git a/packages/ui/src/css/core.css b/packages/ui/src/css/core.css index 088d4d6f2b..a8ab7cfc6b 100644 --- a/packages/ui/src/css/core.css +++ b/packages/ui/src/css/core.css @@ -30,6 +30,10 @@ } } +body { + background-color: var(--bui-bg); +} + /* Light theme tokens */ :root { /* Font families */ From 865bce8ac9bae088fcd9769cabab1c6009153b98 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 8 Oct 2025 17:35:45 +0100 Subject: [PATCH 117/244] Remove noCssBaseline Signed-off-by: Charles de Dreuille --- .changeset/salty-baths-buy.md | 5 +++++ .changeset/warm-dancers-call.md | 5 +++++ packages/theme/report.api.md | 2 -- packages/theme/src/unified/UnifiedThemeProvider.tsx | 1 - 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 .changeset/salty-baths-buy.md create mode 100644 .changeset/warm-dancers-call.md diff --git a/.changeset/salty-baths-buy.md b/.changeset/salty-baths-buy.md new file mode 100644 index 0000000000..c3b72189eb --- /dev/null +++ b/.changeset/salty-baths-buy.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Added a background color default on the body diff --git a/.changeset/warm-dancers-call.md b/.changeset/warm-dancers-call.md new file mode 100644 index 0000000000..62cdfb9baf --- /dev/null +++ b/.changeset/warm-dancers-call.md @@ -0,0 +1,5 @@ +--- +'@backstage/theme': minor +--- + +**BREAKING**: Removed noCssBaseline prop in UnifiedThemeProvider. diff --git a/packages/theme/report.api.md b/packages/theme/report.api.md index ebdae12a05..18ac96ecec 100644 --- a/packages/theme/report.api.md +++ b/packages/theme/report.api.md @@ -459,8 +459,6 @@ export interface UnifiedThemeProviderProps { // (undocumented) children: ReactNode; // (undocumented) - noCssBaseline?: boolean; - // (undocumented) theme: UnifiedTheme; } ``` diff --git a/packages/theme/src/unified/UnifiedThemeProvider.tsx b/packages/theme/src/unified/UnifiedThemeProvider.tsx index 45358c13da..d0886cd146 100644 --- a/packages/theme/src/unified/UnifiedThemeProvider.tsx +++ b/packages/theme/src/unified/UnifiedThemeProvider.tsx @@ -37,7 +37,6 @@ import { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material export interface UnifiedThemeProviderProps { children: ReactNode; theme: UnifiedTheme; - noCssBaseline?: boolean; } /** From 5f8ba7c1fb75928446591266a075f3c1c87980a9 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 8 Oct 2025 21:17:55 +0100 Subject: [PATCH 118/244] Update react-aria-components Signed-off-by: Charles de Dreuille --- packages/ui/package.json | 2 +- yarn.lock | 2673 +++++++++++++++++++------------------- 2 files changed, 1337 insertions(+), 1338 deletions(-) diff --git a/packages/ui/package.json b/packages/ui/package.json index fd6ecd169c..85f4440690 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -42,7 +42,7 @@ "@remixicon/react": "^4.6.0", "@tanstack/react-table": "^8.21.3", "clsx": "^2.1.1", - "react-aria-components": "^1.10.1" + "react-aria-components": "^1.13.0" }, "devDependencies": { "@backstage/cli": "workspace:^", diff --git a/yarn.lock b/yarn.lock index 81c9de6628..865c2a931e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7528,7 +7528,7 @@ __metadata: lightningcss: "npm:^1.29.1" mini-css-extract-plugin: "npm:^2.9.2" react: "npm:^18.0.2" - react-aria-components: "npm:^1.10.1" + react-aria-components: "npm:^1.13.0" react-dom: "npm:^18.0.2" react-router-dom: "npm:^6.3.0" storybook: "npm:^9.1.7" @@ -9619,12 +9619,12 @@ __metadata: languageName: unknown linkType: soft -"@internationalized/date@npm:^3.8.2": - version: 3.8.2 - resolution: "@internationalized/date@npm:3.8.2" +"@internationalized/date@npm:^3.10.0": + version: 3.10.0 + resolution: "@internationalized/date@npm:3.10.0" dependencies: "@swc/helpers": "npm:^0.5.0" - checksum: 10/ca281d8785acff520ba4782d4eb0c542bb6c2783dbd3eb5457aeddbb68b9674f860fc00c6dd467f39c12eff9a04381742b07f0b9e210a115c094507e046d7b5a + checksum: 10/5940667ea2b0be54b798088ef995f787508bf4305d3741babc8b1f48de008c872555a5440ae61fa7399461a7339d3257fb8e86cc2111e72e185fc37d99e06392 languageName: node linkType: hard @@ -9638,12 +9638,12 @@ __metadata: languageName: node linkType: hard -"@internationalized/number@npm:^3.6.3": - version: 3.6.3 - resolution: "@internationalized/number@npm:3.6.3" +"@internationalized/number@npm:^3.6.5": + version: 3.6.5 + resolution: "@internationalized/number@npm:3.6.5" dependencies: "@swc/helpers": "npm:^0.5.0" - checksum: 10/b6f1793d12f89aca4c5bd88b60643739c4b02cade50a42c61192a2a5e0a913088ee35e4013b7ef3f675bdc919ebaf9a1631f1c40b1ceffd998f3fc14201a01c3 + checksum: 10/f80618842b9b8ea04e235277911eeb8e2ee129f1b266b94704a9f773df7536486c25db41ae708f6c2f4845cdb0a25e7d1856332370daba6c530528ac0ee997e3 languageName: node linkType: hard @@ -14544,929 +14544,928 @@ __metadata: languageName: node linkType: hard -"@react-aria/autocomplete@npm:3.0.0-beta.5": - version: 3.0.0-beta.5 - resolution: "@react-aria/autocomplete@npm:3.0.0-beta.5" - dependencies: - "@react-aria/combobox": "npm:^3.12.5" - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/listbox": "npm:^3.14.6" - "@react-aria/searchfield": "npm:^3.8.6" - "@react-aria/textfield": "npm:^3.17.5" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/autocomplete": "npm:3.0.0-beta.2" - "@react-stately/combobox": "npm:^3.10.6" - "@react-types/autocomplete": "npm:3.0.0-alpha.32" - "@react-types/button": "npm:^3.12.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/f8b4427b310a4bd221cb0e38b031a4150c306f7d1177926c5a2bea0dd4370db6e49e220ca2358c283ea4c009f0a65611340486d161193f7943659a60e20a1881 - languageName: node - linkType: hard - -"@react-aria/breadcrumbs@npm:^3.5.26": - version: 3.5.26 - resolution: "@react-aria/breadcrumbs@npm:3.5.26" - dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/link": "npm:^3.8.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/breadcrumbs": "npm:^3.7.14" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/e0b9fe416cb84281e207ab12644d3bf21d6af82b4ec5d5ac204209ef6aff9abcc242660c23b2f3ef3572aa0f1e72dcc33905066f720afa1ccfc3cf3d4b916c31 - languageName: node - linkType: hard - -"@react-aria/button@npm:^3.13.3": - version: 3.13.3 - resolution: "@react-aria/button@npm:3.13.3" - dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/toolbar": "npm:3.0.0-beta.18" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/toggle": "npm:^3.8.5" - "@react-types/button": "npm:^3.12.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/c360899930f648c56f16bf5d0d2d8c01b5d59449b87fff4e758e68127aa8e453396ffbdc6ee0fa2fbcf18fce73472041da36d21929b2d28bd55770bbfd75e384 - languageName: node - linkType: hard - -"@react-aria/calendar@npm:^3.8.3": - version: 3.8.3 - resolution: "@react-aria/calendar@npm:3.8.3" - dependencies: - "@internationalized/date": "npm:^3.8.2" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/live-announcer": "npm:^3.4.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/calendar": "npm:^3.8.2" - "@react-types/button": "npm:^3.12.2" - "@react-types/calendar": "npm:^3.7.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/53570c8c95fced3704a908ba218ee316db46f5c58352a5970f3b0a863257d8293dd732b0aaeb983921358f45acd50df623db88afa49df4d6735508d08369212b - languageName: node - linkType: hard - -"@react-aria/checkbox@npm:^3.15.7": - version: 3.15.7 - resolution: "@react-aria/checkbox@npm:3.15.7" - dependencies: - "@react-aria/form": "npm:^3.0.18" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/toggle": "npm:^3.11.5" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/checkbox": "npm:^3.6.15" - "@react-stately/form": "npm:^3.1.5" - "@react-stately/toggle": "npm:^3.8.5" - "@react-types/checkbox": "npm:^3.9.5" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/a041baf3977d41f0f46db184b80da9f4d928209ca0bd764cb43202e5fc2f7a1ed44d7b9963d38f11dab934bf0ac5c0ee9311894b8177ed890c4f174b0640b8c8 - languageName: node - linkType: hard - -"@react-aria/collections@npm:3.0.0-rc.3": +"@react-aria/autocomplete@npm:3.0.0-rc.3": version: 3.0.0-rc.3 - resolution: "@react-aria/collections@npm:3.0.0-rc.3" + resolution: "@react-aria/autocomplete@npm:3.0.0-rc.3" dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/ssr": "npm:^3.9.9" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - use-sync-external-store: "npm:^1.4.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/a7a6ba15554ba6f3047cf6898a222e800b8317d4f0b05dbe11cf4301bc3aaa249ea2ae855ec4b0afd9f95c33e47f9ad10227299f6c382995155d91a94ce91493 - languageName: node - linkType: hard - -"@react-aria/color@npm:^3.0.9": - version: 3.0.9 - resolution: "@react-aria/color@npm:3.0.9" - dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/numberfield": "npm:^3.11.16" - "@react-aria/slider": "npm:^3.7.21" - "@react-aria/spinbutton": "npm:^3.6.16" - "@react-aria/textfield": "npm:^3.17.5" - "@react-aria/utils": "npm:^3.29.1" - "@react-aria/visually-hidden": "npm:^3.8.25" - "@react-stately/color": "npm:^3.8.6" - "@react-stately/form": "npm:^3.1.5" - "@react-types/color": "npm:^3.0.6" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/combobox": "npm:^3.14.0" + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/listbox": "npm:^3.15.0" + "@react-aria/searchfield": "npm:^3.8.9" + "@react-aria/textfield": "npm:^3.18.2" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/autocomplete": "npm:3.0.0-beta.3" + "@react-stately/combobox": "npm:^3.12.0" + "@react-types/autocomplete": "npm:3.0.0-alpha.35" + "@react-types/button": "npm:^3.14.1" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/387b1609bafa89297525384925f5c7e290f5a2b592488daae4482873518401b0b5f1eb712000a3ad823f66888937499d3e0522b85ae9adc1e819ea8761abf19a + checksum: 10/7acddd01b0f07bdbd2cf09d01a8b0fb9551d27656a92adf995411620a1599f8ff6421a72de1fcd56611d5eced49073cae48aee8127f3620fc1ca38d4ce3dcb62 languageName: node linkType: hard -"@react-aria/combobox@npm:^3.12.5": - version: 3.12.5 - resolution: "@react-aria/combobox@npm:3.12.5" +"@react-aria/breadcrumbs@npm:^3.5.29": + version: 3.5.29 + resolution: "@react-aria/breadcrumbs@npm:3.5.29" dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/listbox": "npm:^3.14.6" - "@react-aria/live-announcer": "npm:^3.4.3" - "@react-aria/menu": "npm:^3.18.5" - "@react-aria/overlays": "npm:^3.27.3" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/textfield": "npm:^3.17.5" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/combobox": "npm:^3.10.6" - "@react-stately/form": "npm:^3.1.5" - "@react-types/button": "npm:^3.12.2" - "@react-types/combobox": "npm:^3.13.6" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/link": "npm:^3.8.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/breadcrumbs": "npm:^3.7.17" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/171d27bb3a2eefc3c5e3ecdca1d760e44116a68d6169bfa214b05caf840aa879033855a3c1ea273f8d288d066800182f4f8a1299c3dbb7f0dff137db78ad9c41 + checksum: 10/875c2280539362e33200a9869dc52e5cec8a7407e068faa70cc190eaf266135448410acf9dd37b59bd86e53f330ac32e7598ceec468a2339cc04f18f826c4cbc languageName: node linkType: hard -"@react-aria/datepicker@npm:^3.14.5": - version: 3.14.5 - resolution: "@react-aria/datepicker@npm:3.14.5" - dependencies: - "@internationalized/date": "npm:^3.8.2" - "@internationalized/number": "npm:^3.6.3" - "@internationalized/string": "npm:^3.2.7" - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/form": "npm:^3.0.18" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/spinbutton": "npm:^3.6.16" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/datepicker": "npm:^3.14.2" - "@react-stately/form": "npm:^3.1.5" - "@react-types/button": "npm:^3.12.2" - "@react-types/calendar": "npm:^3.7.2" - "@react-types/datepicker": "npm:^3.12.2" - "@react-types/dialog": "npm:^3.5.19" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/440475577e9aee6c18c5e8f5d2c91f22f5a528ee283b472627eb8cf226c7a2125fa537b30b7e5f20e9d6325631e13c5dfa23f88d6f7e6c1e9fd41eff8ccb7590 - languageName: node - linkType: hard - -"@react-aria/dialog@npm:^3.5.27": - version: 3.5.27 - resolution: "@react-aria/dialog@npm:3.5.27" - dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/overlays": "npm:^3.27.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/dialog": "npm:^3.5.19" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/21257bb14352ab611e5659ce555cd845d8de51d30eea0cf7882b5119848c2136cd35f796a3031bbbcbc9640bffadeb35eee6f6254b34f2791c5a739c550e60da - languageName: node - linkType: hard - -"@react-aria/disclosure@npm:^3.0.6": - version: 3.0.6 - resolution: "@react-aria/disclosure@npm:3.0.6" - dependencies: - "@react-aria/ssr": "npm:^3.9.9" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/disclosure": "npm:^3.0.5" - "@react-types/button": "npm:^3.12.2" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/c1e602d6bc91b8b4884b2ec4ef4c3f1ea3d3052ead219a73eb4be110348ef0bde8fd3a68af92e7d8af83a59465b208e8a0d363b1ecffde53134516ce13f0361a - languageName: node - linkType: hard - -"@react-aria/dnd@npm:^3.10.1": - version: 3.10.1 - resolution: "@react-aria/dnd@npm:3.10.1" - dependencies: - "@internationalized/string": "npm:^3.2.7" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/live-announcer": "npm:^3.4.3" - "@react-aria/overlays": "npm:^3.27.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/dnd": "npm:^3.6.0" - "@react-types/button": "npm:^3.12.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/bf1058f59d20054571541455d9fa25eff469363b6f65852d237d9479bee4d6323fc3bd8497115d16e93d4396ab2faba0317875416c93d65a1a566881771624c1 - languageName: node - linkType: hard - -"@react-aria/focus@npm:^3.20.5": - version: 3.20.5 - resolution: "@react-aria/focus@npm:3.20.5" - dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - clsx: "npm:^2.0.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/543c2f18c1d4f10940662608ca67947d1bc22630ae272e73136b36c2aefec61243148668201442132825bf4e9c0ab64add86c9870b9a51cb7bde2dfab7453a6e - languageName: node - linkType: hard - -"@react-aria/form@npm:^3.0.18": - version: 3.0.18 - resolution: "@react-aria/form@npm:3.0.18" - dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/form": "npm:^3.1.5" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/8c3edfaf3f2be28a16d7b0dcf00c677926e6e505fe26ebc348201f6f4e9e44aced1f17400a6c19717b18a3378be28438f269b438317a18f2070529fe2ac1e770 - languageName: node - linkType: hard - -"@react-aria/grid@npm:^3.14.2": +"@react-aria/button@npm:^3.14.2": version: 3.14.2 - resolution: "@react-aria/grid@npm:3.14.2" + resolution: "@react-aria/button@npm:3.14.2" dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/live-announcer": "npm:^3.4.3" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/grid": "npm:^3.11.3" - "@react-stately/selection": "npm:^3.20.3" - "@react-types/checkbox": "npm:^3.9.5" - "@react-types/grid": "npm:^3.3.3" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/toolbar": "npm:3.0.0-beta.21" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/toggle": "npm:^3.9.2" + "@react-types/button": "npm:^3.14.1" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/5f19539b1fe01d82b3693166269acae3fe74467b318f257babca79e5689b932ec83e5d7894ea0cbfd5e568fae3ffa61d04ae049a8967af09384f12d8e75792fa + checksum: 10/d6891ab39a81b349a80ac2c381a5663e33caf209d29aa536b0a8ca2963898b011913593c71f4bceb3f48a54a95cd5bc842b0ffbb33498d38a120d1a6d28f932b languageName: node linkType: hard -"@react-aria/gridlist@npm:^3.13.2": - version: 3.13.2 - resolution: "@react-aria/gridlist@npm:3.13.2" +"@react-aria/calendar@npm:^3.9.2": + version: 3.9.2 + resolution: "@react-aria/calendar@npm:3.9.2" dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/grid": "npm:^3.14.2" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/list": "npm:^3.12.3" - "@react-stately/tree": "npm:^3.9.0" - "@react-types/shared": "npm:^3.30.0" + "@internationalized/date": "npm:^3.10.0" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/live-announcer": "npm:^3.4.4" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/calendar": "npm:^3.9.0" + "@react-types/button": "npm:^3.14.1" + "@react-types/calendar": "npm:^3.8.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/ea5e2f986fc74b627afe4918f94aa8cc778f146d7781822ce55788bb59a90e5765446d7c0bb5bcc86c1e4dd17ced3bd52ab6f703a50e8253bef25b70d3be0b56 + checksum: 10/3697b14765895c864db1a9393b86e0370cda01fab44464e9c1966150d7c793bcc9fd1e7a50d34022b0730fcaf9fd1995d431ccb1b5518eb086ccfb4b35e47ff2 languageName: node linkType: hard -"@react-aria/i18n@npm:^3.12.10": - version: 3.12.10 - resolution: "@react-aria/i18n@npm:3.12.10" +"@react-aria/checkbox@npm:^3.16.2": + version: 3.16.2 + resolution: "@react-aria/checkbox@npm:3.16.2" dependencies: - "@internationalized/date": "npm:^3.8.2" - "@internationalized/message": "npm:^3.1.8" - "@internationalized/number": "npm:^3.6.3" - "@internationalized/string": "npm:^3.2.7" - "@react-aria/ssr": "npm:^3.9.9" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/form": "npm:^3.1.2" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/toggle": "npm:^3.12.2" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/checkbox": "npm:^3.7.2" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/toggle": "npm:^3.9.2" + "@react-types/checkbox": "npm:^3.10.2" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/6f331ceb62a1364d32f2336257ed82715f712e27d3e04a173296efc320f6532626561e883c2c3639ef4efdcd03498005e87d7160d8942ea8255d18d57770d3a0 + checksum: 10/77058d41d78b8feea4801022ba56f225b69f9b6577edc42a747dea21e4b38ea8d343f3a38455e9ae47a95a41b77e37fa0929a7136507f7b446111919f5e34478 languageName: node linkType: hard -"@react-aria/interactions@npm:^3.25.3": - version: 3.25.3 - resolution: "@react-aria/interactions@npm:3.25.3" +"@react-aria/collections@npm:^3.0.0": + version: 3.0.0 + resolution: "@react-aria/collections@npm:3.0.0" dependencies: - "@react-aria/ssr": "npm:^3.9.9" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/flags": "npm:^3.1.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/21754f3e15c35430262b8e283d00010543c8855bac9b9feeb701c967394940d4063b63380b59637c7da8e9b922f29edb3525d15d6005202a6dc22fd32a0d951f - languageName: node - linkType: hard - -"@react-aria/label@npm:^3.7.19": - version: 3.7.19 - resolution: "@react-aria/label@npm:3.7.19" - dependencies: - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/984a97ac0bca6487031bc006d8b697766d990e78e381d5e230414429542e51d84197459b45b834069615d9f17f5b162e671e464e62f78854ac8fbb458d1b3346 - languageName: node - linkType: hard - -"@react-aria/landmark@npm:^3.0.4": - version: 3.0.4 - resolution: "@react-aria/landmark@npm:3.0.4" - dependencies: - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/ssr": "npm:^3.9.10" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" use-sync-external-store: "npm:^1.4.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/ab1d9cc93e83b0f486157dc878474e59b601631220bb688840c55baf6ccfd65d8fe2a04adaaa055f0e2883f3e7428b74d52cc13d32e15f930c0cb1c189309ee8 + checksum: 10/2704d35e0cc67e8e2f7fa61f593160768a633e2ff3ced45f01806928dc15738dcd005c49ff7130c0c92fbaabf0b0624833e54b7d24a10181c7910a469a9da52b languageName: node linkType: hard -"@react-aria/link@npm:^3.8.3": - version: 3.8.3 - resolution: "@react-aria/link@npm:3.8.3" +"@react-aria/color@npm:^3.1.2": + version: 3.1.2 + resolution: "@react-aria/color@npm:3.1.2" dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/link": "npm:^3.6.2" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/numberfield": "npm:^3.12.2" + "@react-aria/slider": "npm:^3.8.2" + "@react-aria/spinbutton": "npm:^3.6.19" + "@react-aria/textfield": "npm:^3.18.2" + "@react-aria/utils": "npm:^3.31.0" + "@react-aria/visually-hidden": "npm:^3.8.28" + "@react-stately/color": "npm:^3.9.2" + "@react-stately/form": "npm:^3.2.2" + "@react-types/color": "npm:^3.1.2" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/978f875a81616f46706da3596dfb52845af93420c3b2ce29d83c8eed5203cd0b5bdd3f988039dff3e3420de668927be46c2971333d628fa7af3f83b7796159f8 + checksum: 10/8b2c29097e86e2fa30bb5a53777dd09a7b2b24f6fb44ac1847275345aa895bb663735dcdc94bac90ba6fee074f11fe571f7effc5ba4ac4adb0bc87f67705479c languageName: node linkType: hard -"@react-aria/listbox@npm:^3.14.6": - version: 3.14.6 - resolution: "@react-aria/listbox@npm:3.14.6" +"@react-aria/combobox@npm:^3.14.0": + version: 3.14.0 + resolution: "@react-aria/combobox@npm:3.14.0" dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/list": "npm:^3.12.3" - "@react-types/listbox": "npm:^3.7.1" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/listbox": "npm:^3.15.0" + "@react-aria/live-announcer": "npm:^3.4.4" + "@react-aria/menu": "npm:^3.19.3" + "@react-aria/overlays": "npm:^3.30.0" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/textfield": "npm:^3.18.2" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/combobox": "npm:^3.12.0" + "@react-stately/form": "npm:^3.2.2" + "@react-types/button": "npm:^3.14.1" + "@react-types/combobox": "npm:^3.13.9" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/068a1e5d56516436dbc8bde6e3a98db7ec277f0a0ce73ce6334e762c196570ae751dc0b0503f1e66624569d89ce412bc9292fa67f5a52db03db3104bb1d2f300 + checksum: 10/e583a99133b884e49b5848271a18d3dcbc6fdb4fb9aa9477d2164790b7386ada3316f6a4c19af3e8d989ed9c6207af12e2377c2f1644e8114afd916697a26c33 languageName: node linkType: hard -"@react-aria/live-announcer@npm:^3.4.3": - version: 3.4.3 - resolution: "@react-aria/live-announcer@npm:3.4.3" +"@react-aria/datepicker@npm:^3.15.2": + version: 3.15.2 + resolution: "@react-aria/datepicker@npm:3.15.2" dependencies: - "@swc/helpers": "npm:^0.5.0" - checksum: 10/73e3fc9bc2796cbccbcd0e01e2b4bd62d0b1a3915b1d0f01d2054141033c6b2a5275a7b7c52bdc0a3b9ef738881b4a84bb5d6df57d1ee066278e5bdf40a8f979 - languageName: node - linkType: hard - -"@react-aria/menu@npm:^3.18.5": - version: 3.18.5 - resolution: "@react-aria/menu@npm:3.18.5" - dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/overlays": "npm:^3.27.3" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/menu": "npm:^3.9.5" - "@react-stately/selection": "npm:^3.20.3" - "@react-stately/tree": "npm:^3.9.0" - "@react-types/button": "npm:^3.12.2" - "@react-types/menu": "npm:^3.10.2" - "@react-types/shared": "npm:^3.30.0" + "@internationalized/date": "npm:^3.10.0" + "@internationalized/number": "npm:^3.6.5" + "@internationalized/string": "npm:^3.2.7" + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/form": "npm:^3.1.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/spinbutton": "npm:^3.6.19" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/datepicker": "npm:^3.15.2" + "@react-stately/form": "npm:^3.2.2" + "@react-types/button": "npm:^3.14.1" + "@react-types/calendar": "npm:^3.8.0" + "@react-types/datepicker": "npm:^3.13.2" + "@react-types/dialog": "npm:^3.5.22" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/409f21cfa7d9cca62ca7c21b047bd72314181782b2d6ea0bb16a33075280653eef1b4d9c4b0ad15ebe72ec59e12103f3b1f86e6e7cd8886571956d6d099ae200 + checksum: 10/05f9b7bda5e5aa304ea4eebfded8040ea040b12284f2aa67f6b2a9e5458526a1e8dfbe077a53989a8633debb8184123e0907186f5b511c5a4c85a48f4c755f4b languageName: node linkType: hard -"@react-aria/meter@npm:^3.4.24": - version: 3.4.24 - resolution: "@react-aria/meter@npm:3.4.24" +"@react-aria/dialog@npm:^3.5.31": + version: 3.5.31 + resolution: "@react-aria/dialog@npm:3.5.31" dependencies: - "@react-aria/progress": "npm:^3.4.24" - "@react-types/meter": "npm:^3.4.10" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/overlays": "npm:^3.30.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/dialog": "npm:^3.5.22" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/980e46d3b784c59523ea9eb342c28e2a29e0549937da4def5f61ce011abb2da40f833dbe3f14550ffcd384860e08d4e8ee286e58834100b04c7de93fa5587e50 + checksum: 10/ea5d197b13d1441b45b5288382f9f25cf4ecec07ea6c8e989ce62b5f0ce2eaa7e6afe7e40fc808451b040eda2c41aa64f8e510d5205b26a5a07324b86468e53d languageName: node linkType: hard -"@react-aria/numberfield@npm:^3.11.16": - version: 3.11.16 - resolution: "@react-aria/numberfield@npm:3.11.16" +"@react-aria/disclosure@npm:^3.1.0": + version: 3.1.0 + resolution: "@react-aria/disclosure@npm:3.1.0" dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/spinbutton": "npm:^3.6.16" - "@react-aria/textfield": "npm:^3.17.5" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/form": "npm:^3.1.5" - "@react-stately/numberfield": "npm:^3.9.13" - "@react-types/button": "npm:^3.12.2" - "@react-types/numberfield": "npm:^3.8.12" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/ssr": "npm:^3.9.10" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/disclosure": "npm:^3.0.8" + "@react-types/button": "npm:^3.14.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/3e83938fe4fe76ef662c543734988b56d60824d8d2d19de5adffe06191106aa98b2b6dd4241ed49fc3e7ad3e1c4c43cbdd81c6fc32d728959e5b377faf8ffdcd + checksum: 10/34f5a0b5c7130fc686025f8015cefe219b84ed153dbca93ee4b47b2f598ca833ed161426dc76d2f09ee480b88741df046fcbb600516eb77b919afcb80b1b61a3 languageName: node linkType: hard -"@react-aria/overlays@npm:^3.26.1, @react-aria/overlays@npm:^3.27.3": - version: 3.27.3 - resolution: "@react-aria/overlays@npm:3.27.3" +"@react-aria/dnd@npm:^3.11.3": + version: 3.11.3 + resolution: "@react-aria/dnd@npm:3.11.3" dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/ssr": "npm:^3.9.9" - "@react-aria/utils": "npm:^3.29.1" - "@react-aria/visually-hidden": "npm:^3.8.25" - "@react-stately/overlays": "npm:^3.6.17" - "@react-types/button": "npm:^3.12.2" - "@react-types/overlays": "npm:^3.8.16" - "@react-types/shared": "npm:^3.30.0" + "@internationalized/string": "npm:^3.2.7" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/live-announcer": "npm:^3.4.4" + "@react-aria/overlays": "npm:^3.30.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/dnd": "npm:^3.7.1" + "@react-types/button": "npm:^3.14.1" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/8cee1a99bc9ff4ecf0577b76f54cccaf684dde2278d0c270e82c683ef6f42bb8100de4596ae411e775643a3765abbd87fdb1c5d46bf05481ed9df9ed9b82276a + checksum: 10/48c58ab1fdb0e4dfce2e5933b580df3e46c0407535a28d2434fc6921d049bde45d0b3b94b7f3f4775e683e77c4a5b17ccfd9894c345230b7f49c7c0742663dce languageName: node linkType: hard -"@react-aria/progress@npm:^3.4.24": - version: 3.4.24 - resolution: "@react-aria/progress@npm:3.4.24" +"@react-aria/focus@npm:^3.21.2": + version: 3.21.2 + resolution: "@react-aria/focus@npm:3.21.2" dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/progress": "npm:^3.5.13" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/e7e4cf6f904f1b35a54704aa6d473c4eb239130ba8fbba71f6298b68a92c067162132fb5adf1e6f8960bdc8a2913004d979e088575761b0ba5252c28cdf62b0b - languageName: node - linkType: hard - -"@react-aria/radio@npm:^3.11.5": - version: 3.11.5 - resolution: "@react-aria/radio@npm:3.11.5" - dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/form": "npm:^3.0.18" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/radio": "npm:^3.10.14" - "@react-types/radio": "npm:^3.8.10" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/63bbca9ad7a065453f60bb759c0377a8febeb0e4582807726d7eef36a05c806d6d0c9d86ad7b73c42cc0a1c47bab5a1d0369e0d670fc4f58924662395418b24d - languageName: node - linkType: hard - -"@react-aria/searchfield@npm:^3.8.6": - version: 3.8.6 - resolution: "@react-aria/searchfield@npm:3.8.6" - dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/textfield": "npm:^3.17.5" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/searchfield": "npm:^3.5.13" - "@react-types/button": "npm:^3.12.2" - "@react-types/searchfield": "npm:^3.6.3" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/7db3dd61084e49c9d2c9fa9aa10821087aff91cfadeade78b559cd1877c67a49dcdd238b48a8b2501cd7070b9123d276e8ef6170cb5438cdce28ef6889eea366 - languageName: node - linkType: hard - -"@react-aria/select@npm:^3.15.7": - version: 3.15.7 - resolution: "@react-aria/select@npm:3.15.7" - dependencies: - "@react-aria/form": "npm:^3.0.18" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/listbox": "npm:^3.14.6" - "@react-aria/menu": "npm:^3.18.5" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-aria/visually-hidden": "npm:^3.8.25" - "@react-stately/select": "npm:^3.6.14" - "@react-types/button": "npm:^3.12.2" - "@react-types/select": "npm:^3.9.13" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/8e0974ddc558051c384a7d9da1eeea4623cbe4a61f0f0402aebeb4be23a1cb5875b839608dcc6aaca4ab6c288143c202eb0fa2ee3ed8f62b7e33d142604f2fba - languageName: node - linkType: hard - -"@react-aria/selection@npm:^3.24.3": - version: 3.24.3 - resolution: "@react-aria/selection@npm:3.24.3" - dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/selection": "npm:^3.20.3" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/f2575161b69d87e7c5ee7d0d658c96c97e815a0de74d121f3744efcfb62f181efd3250f3842b0347d54e9d27c85b41292728927efb3bcc2bdcf8873d92647eb1 - languageName: node - linkType: hard - -"@react-aria/separator@npm:^3.4.10": - version: 3.4.10 - resolution: "@react-aria/separator@npm:3.4.10" - dependencies: - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/706aed510aa306f70ff98a82061995f3fb1ffa6ca0134b282ac9a776441fe4241ff87f8008fa04761b3edaadf8020c96f55720821a7ff4b5c362cad3eb7ed98a - languageName: node - linkType: hard - -"@react-aria/slider@npm:^3.7.21": - version: 3.7.21 - resolution: "@react-aria/slider@npm:3.7.21" - dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/slider": "npm:^3.6.5" - "@react-types/shared": "npm:^3.30.0" - "@react-types/slider": "npm:^3.7.12" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/1a063533b33f224adf782840664e517a8034a28129648908b7391c648c4141c58103dc9733c81f12b1848320669dcca64a059a3279c4114ae81df796a274da59 - languageName: node - linkType: hard - -"@react-aria/spinbutton@npm:^3.6.16": - version: 3.6.16 - resolution: "@react-aria/spinbutton@npm:3.6.16" - dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/live-announcer": "npm:^3.4.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/button": "npm:^3.12.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/2f032d3206738902e91661b0e5ff1cdd75005c40b75a219bbf6aab48b3aad16d1d1090c873ab2e1e0400dee74db56c455948ff2ebe0a6c7f1edb200dfea826e5 - languageName: node - linkType: hard - -"@react-aria/ssr@npm:^3.9.9": - version: 3.9.9 - resolution: "@react-aria/ssr@npm:3.9.9" - dependencies: - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/d0675357b51784e9dbe3add97aa0e6acc810ab0ef01d1c7a317ff8ead5eae64d66c60cc751ea3d10f874bb381e445099bb31cb7f1955801848ce6dce91b588a2 - languageName: node - linkType: hard - -"@react-aria/switch@npm:^3.7.5": - version: 3.7.5 - resolution: "@react-aria/switch@npm:3.7.5" - dependencies: - "@react-aria/toggle": "npm:^3.11.5" - "@react-stately/toggle": "npm:^3.8.5" - "@react-types/shared": "npm:^3.30.0" - "@react-types/switch": "npm:^3.5.12" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/1f716296b444b1db28bd55493ddabbdc403fc48a865cbbd0e383e69e2e42b97e778446383740330cf7e76a4a2dcc0de6f84fed1cddd0f0760b6ffa34118794cb - languageName: node - linkType: hard - -"@react-aria/table@npm:^3.17.5": - version: 3.17.5 - resolution: "@react-aria/table@npm:3.17.5" - dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/grid": "npm:^3.14.2" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/live-announcer": "npm:^3.4.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-aria/visually-hidden": "npm:^3.8.25" - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/flags": "npm:^3.1.2" - "@react-stately/table": "npm:^3.14.3" - "@react-types/checkbox": "npm:^3.9.5" - "@react-types/grid": "npm:^3.3.3" - "@react-types/shared": "npm:^3.30.0" - "@react-types/table": "npm:^3.13.1" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/d10e2432b66b0279413fec031673172ed8c49d93185cd1657511467b04ec780bc089a7e45d75c9ba71c94419355107e961e679acd254da8a19d446e1c9343a70 - languageName: node - linkType: hard - -"@react-aria/tabs@npm:^3.10.5": - version: 3.10.5 - resolution: "@react-aria/tabs@npm:3.10.5" - dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/tabs": "npm:^3.8.3" - "@react-types/shared": "npm:^3.30.0" - "@react-types/tabs": "npm:^3.3.16" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/39db9d4d5a0e87e7cbdb91bcdc5385e02fd21cb1e1c181ecf226e6b0fba9c948c03623cceb11d831a87056c6bc3a0528a7e7a9f58292b0c4dfaa6b9cce56f3bb - languageName: node - linkType: hard - -"@react-aria/tag@npm:^3.6.2": - version: 3.6.2 - resolution: "@react-aria/tag@npm:3.6.2" - dependencies: - "@react-aria/gridlist": "npm:^3.13.2" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/list": "npm:^3.12.3" - "@react-types/button": "npm:^3.12.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/fbfb3a9769077bcc23199aacd80c83b42e89f752d0690c6a5751d9a95b6e760365be2915fa134db9ad040355b341b150270f553ece6f791378a27102e90e7fca - languageName: node - linkType: hard - -"@react-aria/textfield@npm:^3.17.5": - version: 3.17.5 - resolution: "@react-aria/textfield@npm:3.17.5" - dependencies: - "@react-aria/form": "npm:^3.0.18" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/form": "npm:^3.1.5" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/shared": "npm:^3.30.0" - "@react-types/textfield": "npm:^3.12.3" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/59f2df9650b8acb961a1eaec59bb8a0b18ef6b0b1f3d8bbc2f398ae4fcfc8b3a2a2c22c357319bb53bc166b4e2c624ab58187104621b164de22f465ab342f72d - languageName: node - linkType: hard - -"@react-aria/toast@npm:^3.0.5": - version: 3.0.5 - resolution: "@react-aria/toast@npm:3.0.5" - dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/landmark": "npm:^3.0.4" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/toast": "npm:^3.1.1" - "@react-types/button": "npm:^3.12.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/d674bde2446e29b44fe393386da154d8a467954edf29c9c2cdb922972ea6f962e4f16220c03a410bb0be555b9f96f96f71146762123b9d9187e081a74696bee2 - languageName: node - linkType: hard - -"@react-aria/toggle@npm:^3.11.5": - version: 3.11.5 - resolution: "@react-aria/toggle@npm:3.11.5" - dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/toggle": "npm:^3.8.5" - "@react-types/checkbox": "npm:^3.9.5" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/6490a53496b317d3f12c93e347b2d9dd0e7e4835d66eb0823612d3918836338566c0ed2ac22bf4d94649c6019bf411d9c9a1b8f49d420d52eab8f737c2c3f8c5 - languageName: node - linkType: hard - -"@react-aria/toolbar@npm:3.0.0-beta.18": - version: 3.0.0-beta.18 - resolution: "@react-aria/toolbar@npm:3.0.0-beta.18" - dependencies: - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/0ea1d0d73dad265773678fc66712800840b20558d3e19f0b6aa1f0953ba57e48be9ad293d1f48db3e609b017998ded11227d1aebfb998bcfbe05467498318ced - languageName: node - linkType: hard - -"@react-aria/tooltip@npm:^3.8.5": - version: 3.8.5 - resolution: "@react-aria/tooltip@npm:3.8.5" - dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/tooltip": "npm:^3.5.5" - "@react-types/shared": "npm:^3.30.0" - "@react-types/tooltip": "npm:^3.4.18" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/4398c4ca41ab302b8e50a86c07909b461275bf5025c0163ecb5ae57bbe98e15164927ed58a1137a235996626b19d5397916736ee3257d8bc33d09ec0b1d3f70e - languageName: node - linkType: hard - -"@react-aria/tree@npm:^3.1.1": - version: 3.1.1 - resolution: "@react-aria/tree@npm:3.1.1" - dependencies: - "@react-aria/gridlist": "npm:^3.13.2" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/tree": "npm:^3.9.0" - "@react-types/button": "npm:^3.12.2" - "@react-types/shared": "npm:^3.30.0" - "@swc/helpers": "npm:^0.5.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/d387de7a9de81df8f45a16882ddb24ecf8da06638822b8be4d66357b0b3edd67a85aa185f8cf947c4c8f9036c396bea406dd5e277ef0f74828a29d2dd86fd809 - languageName: node - linkType: hard - -"@react-aria/utils@npm:^3.29.1": - version: 3.29.1 - resolution: "@react-aria/utils@npm:3.29.1" - dependencies: - "@react-aria/ssr": "npm:^3.9.9" - "@react-stately/flags": "npm:^3.1.2" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" clsx: "npm:^2.0.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/90af5ee5b9c7db063ba66a28cfecb8594f356c2b0fc4cce2fcee94543f3b160214e4a9c280e83355af89452b88b1def8856493705c770874da7121ba1d3d0cc0 + checksum: 10/4bce20d956c24ab08b707e84896afafd66b3496971efb6dd611dae1c4c1f47a5c99c786a96b2fd0eb083a7c9ba5368ac04ce3a937cc48fdcc8bb85f81e7a3098 languageName: node linkType: hard -"@react-aria/virtualizer@npm:^4.1.7": - version: 4.1.7 - resolution: "@react-aria/virtualizer@npm:4.1.7" +"@react-aria/form@npm:^3.1.2": + version: 3.1.2 + resolution: "@react-aria/form@npm:3.1.2" dependencies: - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-stately/virtualizer": "npm:^4.4.1" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/form": "npm:^3.2.2" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/4bb747314ac96da76c64490041ab95f4a0889bab7e5805b0e18cb71bdb290ae73932ddd866657cfcdfac8382d6b3017c3dfb1a91ae415a6d1ab45b11d88f66ec + checksum: 10/140d8cb830fab6fc4d885e79fbdfc92f06af43134b6ab68ec93b58fec25220b823b58698bd9bbd574bc21d1c0d443813df89b44f5ea33b5bcd314128560bd4fd languageName: node linkType: hard -"@react-aria/visually-hidden@npm:^3.8.25": - version: 3.8.25 - resolution: "@react-aria/visually-hidden@npm:3.8.25" +"@react-aria/grid@npm:^3.14.5": + version: 3.14.5 + resolution: "@react-aria/grid@npm:3.14.5" dependencies: - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/live-announcer": "npm:^3.4.4" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/grid": "npm:^3.11.6" + "@react-stately/selection": "npm:^3.20.6" + "@react-types/checkbox": "npm:^3.10.2" + "@react-types/grid": "npm:^3.3.6" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/362a793beac35fde101e598f4cac9cd98394b9a0171309842e2428b25074ee696358c45d2ded8244bc40a9db8471440994be59b0f347d2c643092c6445aaca61 + checksum: 10/7e8731b55366b05f619259fbeb149b63d7c17158e25a2ebaacbe3368f50e71f054e4cef3a943ca6076d3ebf0242cfcb155ff276ab984a7495dc46f6b5b13f1d2 + languageName: node + linkType: hard + +"@react-aria/gridlist@npm:^3.14.1": + version: 3.14.1 + resolution: "@react-aria/gridlist@npm:3.14.1" + dependencies: + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/grid": "npm:^3.14.5" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/list": "npm:^3.13.1" + "@react-stately/tree": "npm:^3.9.3" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/1d7ff55a869a3157edd266b5d14a9e1380561bcb8d949fdd43e983e64932ec251aa7221e6156e93ea977b8942c5b9b8f9aae5f04ebc2ed27eef9be2b7e00b5ab + languageName: node + linkType: hard + +"@react-aria/i18n@npm:^3.12.13": + version: 3.12.13 + resolution: "@react-aria/i18n@npm:3.12.13" + dependencies: + "@internationalized/date": "npm:^3.10.0" + "@internationalized/message": "npm:^3.1.8" + "@internationalized/number": "npm:^3.6.5" + "@internationalized/string": "npm:^3.2.7" + "@react-aria/ssr": "npm:^3.9.10" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/a5464213e626c60d63e0dbab84907ab452c53022a27a5c482c8f86f23c96b53522e52005c5cfc829f388c807eaf246cded69d5bee24b9e0fc08f34f9b0359e82 + languageName: node + linkType: hard + +"@react-aria/interactions@npm:^3.25.6": + version: 3.25.6 + resolution: "@react-aria/interactions@npm:3.25.6" + dependencies: + "@react-aria/ssr": "npm:^3.9.10" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/flags": "npm:^3.1.2" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/fd30e14107d919be25909ca8f69fb99d88aa1f1ead523717a390a40be6d774e40de47dd7f9fcc7e6d66e0f4abc12238001a10d2128cbd7af9b141641cacf6da4 + languageName: node + linkType: hard + +"@react-aria/label@npm:^3.7.22": + version: 3.7.22 + resolution: "@react-aria/label@npm:3.7.22" + dependencies: + "@react-aria/utils": "npm:^3.31.0" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/2bbfca230465057230597fd23f47ebe591bb5307ff7e37a082a4922e132f1310b69a06dcb4905c356b674b159bd09c2ca690e0526d9f303bed8f66eeb8a61b13 + languageName: node + linkType: hard + +"@react-aria/landmark@npm:^3.0.7": + version: 3.0.7 + resolution: "@react-aria/landmark@npm:3.0.7" + dependencies: + "@react-aria/utils": "npm:^3.31.0" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + use-sync-external-store: "npm:^1.4.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/b86cbd8356fa08e01318644082b9ef948cb3d61695c3dfdb5bdc67a59ce3e3f774c91bf62795280c7ac620b87f9d7e66635c7e02a2c2eb2663b3e2b6a77a448a + languageName: node + linkType: hard + +"@react-aria/link@npm:^3.8.6": + version: 3.8.6 + resolution: "@react-aria/link@npm:3.8.6" + dependencies: + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/link": "npm:^3.6.5" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/7f0fd02e7eb5c69ba5e280c57b0e7ec6568fbca231159f591201f9d753bd2f985613d0f75a54465f292a617684a55d8f5f10585538ce1fbc3f9f29fb3d339529 + languageName: node + linkType: hard + +"@react-aria/listbox@npm:^3.15.0": + version: 3.15.0 + resolution: "@react-aria/listbox@npm:3.15.0" + dependencies: + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/list": "npm:^3.13.1" + "@react-types/listbox": "npm:^3.7.4" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/e361b11ab4ae521a3e4d41ea811f15e2863b97aa9e65c19eef06c38b9f378191c34dfedf545d1ea4667aa0b89aa157712ed6f78950d71cfc712643666cc59d7a + languageName: node + linkType: hard + +"@react-aria/live-announcer@npm:^3.4.4": + version: 3.4.4 + resolution: "@react-aria/live-announcer@npm:3.4.4" + dependencies: + "@swc/helpers": "npm:^0.5.0" + checksum: 10/058859f7c0895bccd902f038586333016d7a33d38508e5edaf0f4c809a00217c19db3aa00604e78f3a788e399c3701a8d7fe95e2eb29c8ae754ff4bb62da1f7a + languageName: node + linkType: hard + +"@react-aria/menu@npm:^3.19.3": + version: 3.19.3 + resolution: "@react-aria/menu@npm:3.19.3" + dependencies: + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/overlays": "npm:^3.30.0" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/menu": "npm:^3.9.8" + "@react-stately/selection": "npm:^3.20.6" + "@react-stately/tree": "npm:^3.9.3" + "@react-types/button": "npm:^3.14.1" + "@react-types/menu": "npm:^3.10.5" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/04987d1fae12979335a755093b74e0a9c61d2bf1f207111bca2a8513ea43962b282315976d33e5f06d3e2e1fc1927e2f9030365c4e4a26024e156ebcb88a8d9c + languageName: node + linkType: hard + +"@react-aria/meter@npm:^3.4.27": + version: 3.4.27 + resolution: "@react-aria/meter@npm:3.4.27" + dependencies: + "@react-aria/progress": "npm:^3.4.27" + "@react-types/meter": "npm:^3.4.13" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/b79bc0f2a96b53ec427a25315cdec4a50dd1bc1cb1fbff9f84847c0bb2597851a514ecbbf4b0fbb18b165bc007142ad45bd432641301b8db990e09f281563d39 + languageName: node + linkType: hard + +"@react-aria/numberfield@npm:^3.12.2": + version: 3.12.2 + resolution: "@react-aria/numberfield@npm:3.12.2" + dependencies: + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/spinbutton": "npm:^3.6.19" + "@react-aria/textfield": "npm:^3.18.2" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/numberfield": "npm:^3.10.2" + "@react-types/button": "npm:^3.14.1" + "@react-types/numberfield": "npm:^3.8.15" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/7ec498b0d3bf6a55e891e61d1693a6395a3e7b89a04d81af433a0cb3dd673603ce5dd7f861d39658a5fe6c0cd48356c8120c39b9a4495563d9b13af0f8c0b3ca + languageName: node + linkType: hard + +"@react-aria/overlays@npm:^3.26.1, @react-aria/overlays@npm:^3.30.0": + version: 3.30.0 + resolution: "@react-aria/overlays@npm:3.30.0" + dependencies: + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/ssr": "npm:^3.9.10" + "@react-aria/utils": "npm:^3.31.0" + "@react-aria/visually-hidden": "npm:^3.8.28" + "@react-stately/overlays": "npm:^3.6.20" + "@react-types/button": "npm:^3.14.1" + "@react-types/overlays": "npm:^3.9.2" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/32c25162b55078cf18ca6f514065d97982a9447b1ec9d75fda4db69fa909cd5dcc3d5b4c8917edecce7d8dd5b20bc51c3862945110c0badef021c86878e8fb4d + languageName: node + linkType: hard + +"@react-aria/progress@npm:^3.4.27": + version: 3.4.27 + resolution: "@react-aria/progress@npm:3.4.27" + dependencies: + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/progress": "npm:^3.5.16" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/7b0ac3c2da6205096e94b4d72a2b2b0250f864cace05b562e49b86986dbebbab633e62fcc39ffa915974318de37d5f6256b1f584d8e33ebca70e564d32b3aca2 + languageName: node + linkType: hard + +"@react-aria/radio@npm:^3.12.2": + version: 3.12.2 + resolution: "@react-aria/radio@npm:3.12.2" + dependencies: + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/form": "npm:^3.1.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/radio": "npm:^3.11.2" + "@react-types/radio": "npm:^3.9.2" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/709bdd0515e797f2bf37dc17f55e46103aa918a4549880c15ecca7c03adc0716e5650376b1cc877437b12e5df4e3050138699707e4ec9fa611614a1e38b98eb0 + languageName: node + linkType: hard + +"@react-aria/searchfield@npm:^3.8.9": + version: 3.8.9 + resolution: "@react-aria/searchfield@npm:3.8.9" + dependencies: + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/textfield": "npm:^3.18.2" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/searchfield": "npm:^3.5.16" + "@react-types/button": "npm:^3.14.1" + "@react-types/searchfield": "npm:^3.6.6" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/a088f7b1c434aea1d4603acb34e591c8f11a1532a41407b68336933a73e1e5f55b07bb6323642af5ebeebe39756e1e60943487d77d69882409c491fd816e86f4 + languageName: node + linkType: hard + +"@react-aria/select@npm:^3.17.0": + version: 3.17.0 + resolution: "@react-aria/select@npm:3.17.0" + dependencies: + "@react-aria/form": "npm:^3.1.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/listbox": "npm:^3.15.0" + "@react-aria/menu": "npm:^3.19.3" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-aria/visually-hidden": "npm:^3.8.28" + "@react-stately/select": "npm:^3.8.0" + "@react-types/button": "npm:^3.14.1" + "@react-types/select": "npm:^3.11.0" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/e986470eb5d8c675fbd5753e0051827c94dad00c5472015d4744e4e9233e7a4ff97f4634e94c5686ef9f65f2b6ffa894b24f3a07bde0437de6fe5802901969cd + languageName: node + linkType: hard + +"@react-aria/selection@npm:^3.26.0": + version: 3.26.0 + resolution: "@react-aria/selection@npm:3.26.0" + dependencies: + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/selection": "npm:^3.20.6" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/6c3c59993c719cfdfd42ef9c753212e7bddf30c348117726e8abfe977876f583e0d0b6fa4ce73e46f1fa53e79e42f0866a333e257cef400c4a24bd5d1c81c379 + languageName: node + linkType: hard + +"@react-aria/separator@npm:^3.4.13": + version: 3.4.13 + resolution: "@react-aria/separator@npm:3.4.13" + dependencies: + "@react-aria/utils": "npm:^3.31.0" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/4326c36d002f3931c8c717b7aacbe30943d42ca190fe400a151d8f480dd65359a0bc9192da33213d4e8215bbfd47436de07fedfe957e83be4101a926d116862e + languageName: node + linkType: hard + +"@react-aria/slider@npm:^3.8.2": + version: 3.8.2 + resolution: "@react-aria/slider@npm:3.8.2" + dependencies: + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/slider": "npm:^3.7.2" + "@react-types/shared": "npm:^3.32.1" + "@react-types/slider": "npm:^3.8.2" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/3b9115eaf61f722929dcb739cd910b9e84f04644fdce8add21bc0f9305a3e7d0948c2e417afe424783b22738d52060505a32187aba1e7aca19dd572ebb6d10ed + languageName: node + linkType: hard + +"@react-aria/spinbutton@npm:^3.6.19": + version: 3.6.19 + resolution: "@react-aria/spinbutton@npm:3.6.19" + dependencies: + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/live-announcer": "npm:^3.4.4" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/button": "npm:^3.14.1" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/9b87a1c87a09ddde141bb23e8e3ce1b1137cb1931df848d6fd3bbcd0773b3579045413b725686629da02c22733ad5b5dfc57e06c5fefaf07f8cfb8c4e2334997 + languageName: node + linkType: hard + +"@react-aria/ssr@npm:^3.9.10": + version: 3.9.10 + resolution: "@react-aria/ssr@npm:3.9.10" + dependencies: + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/3b414b5b174769e874014604749d9beaf2556f360f61d3df3223bca6150c16dd37fbf16800e669a2b0045bd221df70212756991a426a7a472c56aac6c0dabd1b + languageName: node + linkType: hard + +"@react-aria/switch@npm:^3.7.8": + version: 3.7.8 + resolution: "@react-aria/switch@npm:3.7.8" + dependencies: + "@react-aria/toggle": "npm:^3.12.2" + "@react-stately/toggle": "npm:^3.9.2" + "@react-types/shared": "npm:^3.32.1" + "@react-types/switch": "npm:^3.5.15" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/2a9cc90fb6f9593c8b41517d83e4a2e05f77ba544ee41d5beeb865329863ca70afa5beec94230512d3eab44d62f0c0c25110323ba89745ba64e05bee0f34c4ec + languageName: node + linkType: hard + +"@react-aria/table@npm:^3.17.8": + version: 3.17.8 + resolution: "@react-aria/table@npm:3.17.8" + dependencies: + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/grid": "npm:^3.14.5" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/live-announcer": "npm:^3.4.4" + "@react-aria/utils": "npm:^3.31.0" + "@react-aria/visually-hidden": "npm:^3.8.28" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/flags": "npm:^3.1.2" + "@react-stately/table": "npm:^3.15.1" + "@react-types/checkbox": "npm:^3.10.2" + "@react-types/grid": "npm:^3.3.6" + "@react-types/shared": "npm:^3.32.1" + "@react-types/table": "npm:^3.13.4" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/39281b279c2efea9342877e4e2cb1af38f776a7349bcbe6e6daabf281e01445c28b8c7cd38c4f3cfeaea42a126552fd332fc242abd1e5e009c9252e3f1b88512 + languageName: node + linkType: hard + +"@react-aria/tabs@npm:^3.10.8": + version: 3.10.8 + resolution: "@react-aria/tabs@npm:3.10.8" + dependencies: + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/tabs": "npm:^3.8.6" + "@react-types/shared": "npm:^3.32.1" + "@react-types/tabs": "npm:^3.3.19" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/eae72fb6636ae1352ceec509605d35018d96f66aacab896748697da9f6b1e166c7bff88a0ffcfdee2869f653464df401d857906f44bdce5d5b9887b75f533287 + languageName: node + linkType: hard + +"@react-aria/tag@npm:^3.7.2": + version: 3.7.2 + resolution: "@react-aria/tag@npm:3.7.2" + dependencies: + "@react-aria/gridlist": "npm:^3.14.1" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/list": "npm:^3.13.1" + "@react-types/button": "npm:^3.14.1" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/757daed07380eee13a05b1ba0b72e062db689526dd67087cd34726a6003b4791cb450c9765be3ea32208ce1a430903db3885d07700cb8775cd8bcd97b8124cb4 + languageName: node + linkType: hard + +"@react-aria/textfield@npm:^3.18.2": + version: 3.18.2 + resolution: "@react-aria/textfield@npm:3.18.2" + dependencies: + "@react-aria/form": "npm:^3.1.2" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/shared": "npm:^3.32.1" + "@react-types/textfield": "npm:^3.12.6" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/2713e3c42f502ecd1d8a505b01c404a6531d1450d8c422a12ac477d1d45dd5e11e9da48807e75c4915948f579969b4b894f1dda14d87ce3790ab67659b20a396 + languageName: node + linkType: hard + +"@react-aria/toast@npm:^3.0.8": + version: 3.0.8 + resolution: "@react-aria/toast@npm:3.0.8" + dependencies: + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/landmark": "npm:^3.0.7" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/toast": "npm:^3.1.2" + "@react-types/button": "npm:^3.14.1" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/b8b21566723e9038f15517934c45c3e6406f28d476a682421aee270f01852e8a46f0170af13c3a5c8e80926169ebd7802d5def0115876e395dedad4fc9409f49 + languageName: node + linkType: hard + +"@react-aria/toggle@npm:^3.12.2": + version: 3.12.2 + resolution: "@react-aria/toggle@npm:3.12.2" + dependencies: + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/toggle": "npm:^3.9.2" + "@react-types/checkbox": "npm:^3.10.2" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/f6b9ce00d7a6bb0e7b6123826761cb7f40b9c7736ce8edc14b39f1865cd9165c086da8a3f6e27ddae8c8557f54f421bb0b4761c455dae81ed037a765b84b5cb7 + languageName: node + linkType: hard + +"@react-aria/toolbar@npm:3.0.0-beta.21": + version: 3.0.0-beta.21 + resolution: "@react-aria/toolbar@npm:3.0.0-beta.21" + dependencies: + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/ada5f50c4409997d46e4af0b739f1fada6d3c6ac0bdd3a7eef7ad2a440a53eaeebbd0685d19deb4b7c21832882dbe27a5a8162bf89135d2c930fbaf4bb5e0365 + languageName: node + linkType: hard + +"@react-aria/tooltip@npm:^3.8.8": + version: 3.8.8 + resolution: "@react-aria/tooltip@npm:3.8.8" + dependencies: + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/tooltip": "npm:^3.5.8" + "@react-types/shared": "npm:^3.32.1" + "@react-types/tooltip": "npm:^3.4.21" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/eddb4736b3813b26fdb21ce07cef170215a900a233d859605ad17a2c72c66ca8cc2fe105d3920f9b24fce0eb18e050551268dc25a9c5d4b987b7eca1e60b24e9 + languageName: node + linkType: hard + +"@react-aria/tree@npm:^3.1.4": + version: 3.1.4 + resolution: "@react-aria/tree@npm:3.1.4" + dependencies: + "@react-aria/gridlist": "npm:^3.14.1" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/tree": "npm:^3.9.3" + "@react-types/button": "npm:^3.14.1" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/ed3e48d011b846026b4c3bf78a96fbe91ff892d995a94e94ff6f5218dcbd6736660507dee1e06aac9ce48f9f66fdc8898cf8486192cecad428242b5b4930fde8 + languageName: node + linkType: hard + +"@react-aria/utils@npm:^3.31.0": + version: 3.31.0 + resolution: "@react-aria/utils@npm:3.31.0" + dependencies: + "@react-aria/ssr": "npm:^3.9.10" + "@react-stately/flags": "npm:^3.1.2" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + clsx: "npm:^2.0.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/b021d2c3704ce934ec41cfc4d87fa6904fb3e007030e31b824cd8287053e866076cb7c7f072d6ed2fee82ca68f2e3f4677f3d58d7938e4b3315831f1fdea4d90 + languageName: node + linkType: hard + +"@react-aria/virtualizer@npm:^4.1.10": + version: 4.1.10 + resolution: "@react-aria/virtualizer@npm:4.1.10" + dependencies: + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-stately/virtualizer": "npm:^4.4.4" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/a9d1083ee2e424a33cbe5520fc86fd5194a77555b3be21792f648a723770998320220bc32e49ae1551ce5e00b024520ad0bca6ca0d7fdee86bc6216eb1cf78dc + languageName: node + linkType: hard + +"@react-aria/visually-hidden@npm:^3.8.28": + version: 3.8.28 + resolution: "@react-aria/visually-hidden@npm:3.8.28" + dependencies: + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/utils": "npm:^3.31.0" + "@react-types/shared": "npm:^3.32.1" + "@swc/helpers": "npm:^0.5.0" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/07e61b18d385127353014c2bd2bb9bba5035ac064988fa1bfc2f13d8050ccc9488891d4d3fbe6c79a808bfed7f06f1867b89ec1c975818712a36266040d76597 languageName: node linkType: hard @@ -15493,151 +15492,150 @@ __metadata: languageName: node linkType: hard -"@react-stately/autocomplete@npm:3.0.0-beta.2": - version: 3.0.0-beta.2 - resolution: "@react-stately/autocomplete@npm:3.0.0-beta.2" +"@react-stately/autocomplete@npm:3.0.0-beta.3": + version: 3.0.0-beta.3 + resolution: "@react-stately/autocomplete@npm:3.0.0-beta.3" dependencies: - "@react-stately/utils": "npm:^3.10.7" + "@react-stately/utils": "npm:^3.10.8" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/836e593688c33ab118547b60fae93ffb1e9e440aed0ffc8c382290f414bfdc313a88964a00a6bd8b7e7b9aca691538b66adfaafee6065b93cedeb80c5aeef675 + checksum: 10/3920ce479e577730870bc6845ee888a44a9a1f90188cf68efb60c74a8264b5886c9059b0cedc07b82fcb26afd770bff5fc971bef0d93ff6ba7d07024a3e628cd languageName: node linkType: hard -"@react-stately/calendar@npm:^3.8.2": - version: 3.8.2 - resolution: "@react-stately/calendar@npm:3.8.2" +"@react-stately/calendar@npm:^3.9.0": + version: 3.9.0 + resolution: "@react-stately/calendar@npm:3.9.0" dependencies: - "@internationalized/date": "npm:^3.8.2" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/calendar": "npm:^3.7.2" - "@react-types/shared": "npm:^3.30.0" + "@internationalized/date": "npm:^3.10.0" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/calendar": "npm:^3.8.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/d2858a42dc2c324248c4c1ddb6f6fe66de11bfe2703c85f0fd739075712f668427212207626ed35af2fcbe15cd0ee6e2ad53eafe98766fd7352e0e2f134435c4 + checksum: 10/6021927974cfaee9b48e07c4a4744105d1076fbad841aafdbd8633deb105c56f724a2a2f51285b426755873c3c2c8ae677649c9c38431433e7cf9e8dea7b334c languageName: node linkType: hard -"@react-stately/checkbox@npm:^3.6.15": - version: 3.6.15 - resolution: "@react-stately/checkbox@npm:3.6.15" +"@react-stately/checkbox@npm:^3.7.2": + version: 3.7.2 + resolution: "@react-stately/checkbox@npm:3.7.2" dependencies: - "@react-stately/form": "npm:^3.1.5" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/checkbox": "npm:^3.9.5" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/checkbox": "npm:^3.10.2" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/4c2b5213395e59432c59609b3cd2ca8316cf77f18716dcee2abe31af5c4a12fac3125408799b0631771e1095fc5924de7850e09c3fa6e53f56c0f79debc0db77 + checksum: 10/e0dda0c536ee43b2b925b9bf2932fdf5d27370b55d069633bb1e4d6a9dfb0db783ed0119ab0893ec192aa4099da0341f39fd2065bfd2e6c89ca3997e92e83ca1 languageName: node linkType: hard -"@react-stately/collections@npm:^3.12.5": - version: 3.12.5 - resolution: "@react-stately/collections@npm:3.12.5" +"@react-stately/collections@npm:^3.12.8": + version: 3.12.8 + resolution: "@react-stately/collections@npm:3.12.8" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/12024f72ec6602c9447e2bc134da566d99da2e29b41ffba207712be31aaf121b805505397dcfb1ee07dd8d234c40d3018c33364adae271f3231a004775a96fd8 + checksum: 10/da17c50d9323002f8dc05870265d54afa162575ceba83bc42d8ccd5d0ccf3bc0634d3896086e7975e1e7f1d7497de6f09ca0e5b82a697ad04349d5b59eca5a8f languageName: node linkType: hard -"@react-stately/color@npm:^3.8.6": - version: 3.8.6 - resolution: "@react-stately/color@npm:3.8.6" +"@react-stately/color@npm:^3.9.2": + version: 3.9.2 + resolution: "@react-stately/color@npm:3.9.2" dependencies: - "@internationalized/number": "npm:^3.6.3" + "@internationalized/number": "npm:^3.6.5" "@internationalized/string": "npm:^3.2.7" - "@react-stately/form": "npm:^3.1.5" - "@react-stately/numberfield": "npm:^3.9.13" - "@react-stately/slider": "npm:^3.6.5" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/color": "npm:^3.0.6" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/numberfield": "npm:^3.10.2" + "@react-stately/slider": "npm:^3.7.2" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/color": "npm:^3.1.2" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/20ec019c71676c5d336c89b703729c0c8098219c942843a3018e5542fee49c6db56c47b746c4c9cddfb9ea48213a3a860861722fc5b41239e3de827c2ef84351 + checksum: 10/1aaea8dc241911b634ef072352076a8b3eec25300bb6c88ff2ce6147f05d2504688465a0342272b74a8484cdf272d10d2d9abc6cbbb64a111228046369f92ce5 languageName: node linkType: hard -"@react-stately/combobox@npm:^3.10.6": - version: 3.10.6 - resolution: "@react-stately/combobox@npm:3.10.6" +"@react-stately/combobox@npm:^3.12.0": + version: 3.12.0 + resolution: "@react-stately/combobox@npm:3.12.0" dependencies: - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/form": "npm:^3.1.5" - "@react-stately/list": "npm:^3.12.3" - "@react-stately/overlays": "npm:^3.6.17" - "@react-stately/select": "npm:^3.6.14" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/combobox": "npm:^3.13.6" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/list": "npm:^3.13.1" + "@react-stately/overlays": "npm:^3.6.20" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/combobox": "npm:^3.13.9" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/8bc67ee18d1c896620cc11233a8efdaf8ec7f5ec31d068fbbc80e75a54e385617518e2b420f3211c17b905e3cac6026f8b056ae96ee114ea4e897f4ce1951502 + checksum: 10/3471a9c2f60e215784f63085b4ebcb2445ec804b3f0f50261933261afd7c9f7ed6d0675f00b5581aa43763c37561bcf6c6967a0ab485f403b1f8cf33a6b65d40 languageName: node linkType: hard -"@react-stately/data@npm:^3.13.1": - version: 3.13.1 - resolution: "@react-stately/data@npm:3.13.1" +"@react-stately/data@npm:^3.14.1": + version: 3.14.1 + resolution: "@react-stately/data@npm:3.14.1" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/b6eea6a721d4de13ffad7aa12a76012d297e1fbbc919bad35d99f57bf481feb547d56c74467e1dadf8f0cb6be9027e54faa6b10dc4aeb1b46a5c6598218baa2c + checksum: 10/ac069e41036fd534a8ec4e77847234abc35aa02c1901b0abc3af3d5cede0baadb5ce0d5f648fed5d6b2e37f673669f2b21fbf74cfb760f0e99734f1d9e841d33 languageName: node linkType: hard -"@react-stately/datepicker@npm:^3.14.2": - version: 3.14.2 - resolution: "@react-stately/datepicker@npm:3.14.2" +"@react-stately/datepicker@npm:^3.15.2": + version: 3.15.2 + resolution: "@react-stately/datepicker@npm:3.15.2" dependencies: - "@internationalized/date": "npm:^3.8.2" + "@internationalized/date": "npm:^3.10.0" "@internationalized/string": "npm:^3.2.7" - "@react-stately/form": "npm:^3.1.5" - "@react-stately/overlays": "npm:^3.6.17" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/datepicker": "npm:^3.12.2" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/overlays": "npm:^3.6.20" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/datepicker": "npm:^3.13.2" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/dd10f99f32e12eef9d361eb183cd52113a1857613be844da9895b5a8954260ace283e43bd1bae3d73a71f1cb5e6381627999f8a24d4ed320903dba50f864183b + checksum: 10/59ef011e4d56a3a40923d0a2ce02f6150ca4e5c7b9dac638d4f2b512af9a213ea6cda2d8d85b114758f2db2b06a8840a93c5b9c8c30859366249d58d960ed149 languageName: node linkType: hard -"@react-stately/disclosure@npm:^3.0.5": - version: 3.0.5 - resolution: "@react-stately/disclosure@npm:3.0.5" +"@react-stately/disclosure@npm:^3.0.8": + version: 3.0.8 + resolution: "@react-stately/disclosure@npm:3.0.8" dependencies: - "@react-stately/utils": "npm:^3.10.7" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/b1f3f80e6523a0fb0c325064162a59635f560f41dbadd51fd89db02bbad9bafa843b7b1565420444b3b266f2eb92dcf556916b0dabe06d32bb86a2106849c41c + checksum: 10/8a36946589a199a788c07ef6ab04d0a30868db0484c660e5066ba38dd8bb8cef6e00fca324e7645b561fc7f3b3ffa152add555f2971c6be532d9cd3b67237b31 languageName: node linkType: hard -"@react-stately/dnd@npm:^3.6.0": - version: 3.6.0 - resolution: "@react-stately/dnd@npm:3.6.0" +"@react-stately/dnd@npm:^3.7.1": + version: 3.7.1 + resolution: "@react-stately/dnd@npm:3.7.1" dependencies: - "@react-stately/selection": "npm:^3.20.3" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/selection": "npm:^3.20.6" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/9fe59a8d5849af27b5fb0609691bdf0ab14ef8cad8a27405e0c83842d44b171e6d1409716b8e80f12797b187bb553f4acf71a87cd5acd86c76137a3525449194 + checksum: 10/d5500055a5398914556eeb767b141e4192be446990dfecb385b0348a35dc0baf0b0a72567dde806369995e09f5dc27a13fe4261739da7bc8ba483875bd88e694 languageName: node linkType: hard @@ -15650,608 +15648,608 @@ __metadata: languageName: node linkType: hard -"@react-stately/form@npm:^3.1.5": - version: 3.1.5 - resolution: "@react-stately/form@npm:3.1.5" +"@react-stately/form@npm:^3.2.2": + version: 3.2.2 + resolution: "@react-stately/form@npm:3.2.2" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/6c392949ca8ac045163f3716a41f03d6ccbe3fd5704401cbece0ba572d43abbb350f5019534765540d5b511b9aeba70ca2c03dc4ba218074b59a3efbea601564 + checksum: 10/e466309999cb2f28e892b11cdfc7cee2b7d08eefced41d9e346e2c4353dd5fc1864de145a6b332735cdc94b278ff8e6b599489d2aa6945ec5389171f89a633d1 languageName: node linkType: hard -"@react-stately/grid@npm:^3.11.3": - version: 3.11.3 - resolution: "@react-stately/grid@npm:3.11.3" +"@react-stately/grid@npm:^3.11.6": + version: 3.11.6 + resolution: "@react-stately/grid@npm:3.11.6" dependencies: - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/selection": "npm:^3.20.3" - "@react-types/grid": "npm:^3.3.3" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/selection": "npm:^3.20.6" + "@react-types/grid": "npm:^3.3.6" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/09655c28cef0c3007024af0c01982d2c079e558169dcf1994966c2526c6346b442068e2e9700a8abbbbcbd13781cc0eb5b346d974dc9a85dd5c263722d96f5c7 + checksum: 10/b6bc2a24ff37bdf375caa0f73dd6812ec4368f314f7754472f8b5de47ed296c4d3aadab787768c50d17d5606732291f05448891d5b08c0facaf8a1c9f7a70d31 languageName: node linkType: hard -"@react-stately/layout@npm:^4.3.1": - version: 4.3.1 - resolution: "@react-stately/layout@npm:4.3.1" +"@react-stately/layout@npm:^4.5.1": + version: 4.5.1 + resolution: "@react-stately/layout@npm:4.5.1" dependencies: - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/table": "npm:^3.14.3" - "@react-stately/virtualizer": "npm:^4.4.1" - "@react-types/grid": "npm:^3.3.3" - "@react-types/shared": "npm:^3.30.0" - "@react-types/table": "npm:^3.13.1" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/table": "npm:^3.15.1" + "@react-stately/virtualizer": "npm:^4.4.4" + "@react-types/grid": "npm:^3.3.6" + "@react-types/shared": "npm:^3.32.1" + "@react-types/table": "npm:^3.13.4" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/f7d299038aefba602944b5caa81719388427778edc394582dfe14c70f9f485b74a0da6d0eeb6aab843e3fbdd6af251a3678b1a8c76c77f64adb16d695dbd22cd + checksum: 10/a4413d766efdea8decf4549cd773f5a94ce086690195223e605b78ccb9e1c0dd25011bd37a011b805c72a7a9f3a27dc1dd6c8684d9cc2a0b6efaa084fbd337a4 languageName: node linkType: hard -"@react-stately/list@npm:^3.12.3": - version: 3.12.3 - resolution: "@react-stately/list@npm:3.12.3" +"@react-stately/list@npm:^3.13.1": + version: 3.13.1 + resolution: "@react-stately/list@npm:3.13.1" dependencies: - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/selection": "npm:^3.20.3" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/selection": "npm:^3.20.6" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/e8edce5e59e061a4b71621ce7617f4e48cbef5e5c5b6377808e0977f4cad4e541726f255bdeb1c18db867b35ab19883981882bbc27ddbc3e5c26722c496b02f8 + checksum: 10/3da2ca14eaee5f0915c1c79df66268bf1e7cc5d60ce68170515180993941c4c8679033589a8bc38e08138b882a62a8ad69ca727a500c882bd0f4214ce9a69384 languageName: node linkType: hard -"@react-stately/menu@npm:^3.9.5": - version: 3.9.5 - resolution: "@react-stately/menu@npm:3.9.5" +"@react-stately/menu@npm:^3.9.8": + version: 3.9.8 + resolution: "@react-stately/menu@npm:3.9.8" dependencies: - "@react-stately/overlays": "npm:^3.6.17" - "@react-types/menu": "npm:^3.10.2" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/overlays": "npm:^3.6.20" + "@react-types/menu": "npm:^3.10.5" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/a8163b76de49ec10da7129c306304a96e8f4e689450ffdbf6ab5f56fd8b0316db5beb16ebc58da52c19b4abe28954a7200955c41e1a9088e40f5e5d00f975067 + checksum: 10/7798aa91f0af2743d4d441be1a0bac54489413c187d0e926a336cf13482ad4d54c7215426cd6ea288b8bcf621406db6ebaca5209095be5bfb4dfe4464ece7875 languageName: node linkType: hard -"@react-stately/numberfield@npm:^3.9.13": - version: 3.9.13 - resolution: "@react-stately/numberfield@npm:3.9.13" +"@react-stately/numberfield@npm:^3.10.2": + version: 3.10.2 + resolution: "@react-stately/numberfield@npm:3.10.2" dependencies: - "@internationalized/number": "npm:^3.6.3" - "@react-stately/form": "npm:^3.1.5" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/numberfield": "npm:^3.8.12" + "@internationalized/number": "npm:^3.6.5" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/numberfield": "npm:^3.8.15" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/639e2064ed0afd23ec6681b32abca78f9453eb38d11b350247bf4038f6561579f6d444ead6c9c3317c1b1adaaaa22812053cfba8effdd8cb1b199d04b7ce1fbe + checksum: 10/5fd1d4cc1b90a7b03b98a82e47162044a78534291b9baa77847eddd4fb8040bddb91329dfcc7aa2a7cc38ace23817b6c9d52dd7b0f9bd7ce249f763006580797 languageName: node linkType: hard -"@react-stately/overlays@npm:^3.6.17": - version: 3.6.17 - resolution: "@react-stately/overlays@npm:3.6.17" +"@react-stately/overlays@npm:^3.6.20": + version: 3.6.20 + resolution: "@react-stately/overlays@npm:3.6.20" dependencies: - "@react-stately/utils": "npm:^3.10.7" - "@react-types/overlays": "npm:^3.8.16" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/overlays": "npm:^3.9.2" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/9c44f181cd8f0b99a40142aebf3d7e1d1df1e96a789b636a5ee877529e60fddece4ebcf32d9812d9848ce0298bf5cb6202df3b680552b32c89f1276bce3f8a7b + checksum: 10/e9a3023b3fc3d9383d36dbd0a1e6a0d3d84350dee4f5ce6578464d613e063ca32dd6685c4fdfaa774ded24497c9e5c56363b9650c551d5d1a4dbb6d7d1d04382 languageName: node linkType: hard -"@react-stately/radio@npm:^3.10.14": - version: 3.10.14 - resolution: "@react-stately/radio@npm:3.10.14" +"@react-stately/radio@npm:^3.11.2": + version: 3.11.2 + resolution: "@react-stately/radio@npm:3.11.2" dependencies: - "@react-stately/form": "npm:^3.1.5" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/radio": "npm:^3.8.10" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/radio": "npm:^3.9.2" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/45ad56b50f3fcd04c1b335f8f64caceaa6f8483fd84717a461ae04ed8718dabf06f88bf8bd89fcca27d2c6bc548b4a38f0e4ef53ad51f3320aeb85c67b288846 + checksum: 10/182946fb5e963fed62df59d8893ca92443e587bcf3d644b54b991b3acb2124b777af11884e6e31c953becc2dad2226a13238a219747fb596a7e08f0e31e97a22 languageName: node linkType: hard -"@react-stately/searchfield@npm:^3.5.13": - version: 3.5.13 - resolution: "@react-stately/searchfield@npm:3.5.13" +"@react-stately/searchfield@npm:^3.5.16": + version: 3.5.16 + resolution: "@react-stately/searchfield@npm:3.5.16" dependencies: - "@react-stately/utils": "npm:^3.10.7" - "@react-types/searchfield": "npm:^3.6.3" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/searchfield": "npm:^3.6.6" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/6114f1ce0c2e8ddbeedc5b5293783c4e1ecb0cc6f24e09cb6095e32be9b49bdc67619941c16f834850e31acfafd74f4241edaa3529f510ec490a2e6c8e7cdc0b + checksum: 10/879e736c6888e36e227efffa665420c7e4fd2b319c2fb11661d6689fbbdad549129adc1c218e531f79f5e52be5b4c075c3c8120363ca3238fec24195c1976527 languageName: node linkType: hard -"@react-stately/select@npm:^3.6.14": - version: 3.6.14 - resolution: "@react-stately/select@npm:3.6.14" +"@react-stately/select@npm:^3.8.0": + version: 3.8.0 + resolution: "@react-stately/select@npm:3.8.0" dependencies: - "@react-stately/form": "npm:^3.1.5" - "@react-stately/list": "npm:^3.12.3" - "@react-stately/overlays": "npm:^3.6.17" - "@react-types/select": "npm:^3.9.13" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/list": "npm:^3.13.1" + "@react-stately/overlays": "npm:^3.6.20" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/select": "npm:^3.11.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/33116af11830f0d7bf7e10cb03e52ed9c36d17d94674d96440fd73ae8d7da1b93edc4de6170a3681493c76c0ad5c8b24c2961f170b2a784447743775dce32a65 + checksum: 10/d611bbd9d6b55a2dfb31455227efe54c9fc2684f37abd9ba5633b2d1b838bc8fc182e92e64e94ef17c8bbaf351a72daf6089c9d54ce8acad76d3f1be3bdb05aa languageName: node linkType: hard -"@react-stately/selection@npm:^3.20.3": - version: 3.20.3 - resolution: "@react-stately/selection@npm:3.20.3" +"@react-stately/selection@npm:^3.20.6": + version: 3.20.6 + resolution: "@react-stately/selection@npm:3.20.6" dependencies: - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/9903810f5f4e2f37381aba8c81525a819de69316c3bd5d66b29fc5f22e49b3d349d26792e811f7167e16857879c8e6ce8d817d9838c69367481a42977a2022a2 + checksum: 10/b72941f9d23d285b826aa0a5be55e299d934b335d8ebe50c6b061f72b59f860a37549ac4fc0f41a7357eab0d40edb404207cca201fc78915b001b5532e45a9db languageName: node linkType: hard -"@react-stately/slider@npm:^3.6.5": - version: 3.6.5 - resolution: "@react-stately/slider@npm:3.6.5" +"@react-stately/slider@npm:^3.7.2": + version: 3.7.2 + resolution: "@react-stately/slider@npm:3.7.2" dependencies: - "@react-stately/utils": "npm:^3.10.7" - "@react-types/shared": "npm:^3.30.0" - "@react-types/slider": "npm:^3.7.12" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/shared": "npm:^3.32.1" + "@react-types/slider": "npm:^3.8.2" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/121f2f23cad929e7087825ec1a17c51610ac0e62a0b0951d042a6e6a354fcea1751575a7bf6648ae5054a260d89a7613dc0353bf0e9f76553e25c2dce1dba095 + checksum: 10/c11a5374904434bfad5e87767900ed40e12d4341abf74d835b59ab26efb69ad669c86016926f83eae5fb3b3e39c175f775c4457b77eec64d73785c92369a79da languageName: node linkType: hard -"@react-stately/table@npm:^3.14.3": - version: 3.14.3 - resolution: "@react-stately/table@npm:3.14.3" +"@react-stately/table@npm:^3.15.1": + version: 3.15.1 + resolution: "@react-stately/table@npm:3.15.1" dependencies: - "@react-stately/collections": "npm:^3.12.5" + "@react-stately/collections": "npm:^3.12.8" "@react-stately/flags": "npm:^3.1.2" - "@react-stately/grid": "npm:^3.11.3" - "@react-stately/selection": "npm:^3.20.3" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/grid": "npm:^3.3.3" - "@react-types/shared": "npm:^3.30.0" - "@react-types/table": "npm:^3.13.1" + "@react-stately/grid": "npm:^3.11.6" + "@react-stately/selection": "npm:^3.20.6" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/grid": "npm:^3.3.6" + "@react-types/shared": "npm:^3.32.1" + "@react-types/table": "npm:^3.13.4" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/04cd616d526b9b806808ea09ce596dc1fe5fff931deec5ccce3258d0a76ee02c787320004ccc2d3a2d67e54d39f7ab274673210254c8598bd99b767cec8eda1a + checksum: 10/005292a0803de55179a9d27aa7bb68f44865fff64921141fac7aab0fbd5d2adff27a9a70db904f9a57bd6bc8db84036e8ad58b7a1ea57c990829500eb3f3ee6d languageName: node linkType: hard -"@react-stately/tabs@npm:^3.8.3": - version: 3.8.3 - resolution: "@react-stately/tabs@npm:3.8.3" +"@react-stately/tabs@npm:^3.8.6": + version: 3.8.6 + resolution: "@react-stately/tabs@npm:3.8.6" dependencies: - "@react-stately/list": "npm:^3.12.3" - "@react-types/shared": "npm:^3.30.0" - "@react-types/tabs": "npm:^3.3.16" + "@react-stately/list": "npm:^3.13.1" + "@react-types/shared": "npm:^3.32.1" + "@react-types/tabs": "npm:^3.3.19" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/5fb036bc36b5c7fde32c6e7553795fad0f5b2d999837961298341e68d211444ca2a378554c5f73ccf0909e60299cdcd4b0e8c317e57f8c1662e6384957a1ed4a + checksum: 10/ed71a8351b6b9db7c191cbb60acf72121751864b20c1d9a552438a1f4f6c96fdd41469396a17a86ef52287463ef3c8f217167f9498bc5f36e77a621415fac388 languageName: node linkType: hard -"@react-stately/toast@npm:^3.1.1": - version: 3.1.1 - resolution: "@react-stately/toast@npm:3.1.1" +"@react-stately/toast@npm:^3.1.2": + version: 3.1.2 + resolution: "@react-stately/toast@npm:3.1.2" dependencies: "@swc/helpers": "npm:^0.5.0" use-sync-external-store: "npm:^1.4.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/c6ff8b947920e05e3e817cbb478f31c45c64035801456c7c8052c37bea5d966a3ea2c74071c2bed6f2006dec160a6b1204b7cc98965a9c10ca3b4bb4d6765f39 + checksum: 10/771eade3a6f84d7aac3f5766e9cc47826cdb179d58165d12650a843548c13cbf4b4bd3b804a1f367e884e0e28d1d51693cb6f5e7c8391ebdb233cb1dddc015c5 languageName: node linkType: hard -"@react-stately/toggle@npm:^3.8.5": - version: 3.8.5 - resolution: "@react-stately/toggle@npm:3.8.5" +"@react-stately/toggle@npm:^3.9.2": + version: 3.9.2 + resolution: "@react-stately/toggle@npm:3.9.2" dependencies: - "@react-stately/utils": "npm:^3.10.7" - "@react-types/checkbox": "npm:^3.9.5" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/checkbox": "npm:^3.10.2" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/3d8e6c4a39c64fc904355aaa3980e3a63595c24472e3f557716597ac6f9f26299dec5b0843b327b4fe1416436054a65e45ec79073a3be1fad8f093f0d2940864 + checksum: 10/06f0e11cbbda0b479113df6c82e650db9ac772162566fd749da19a3ca274d25831849dc6c67383f4a440be82f61b5dff80e97513763f66bf3994a55febed5827 languageName: node linkType: hard -"@react-stately/tooltip@npm:^3.5.5": - version: 3.5.5 - resolution: "@react-stately/tooltip@npm:3.5.5" +"@react-stately/tooltip@npm:^3.5.8": + version: 3.5.8 + resolution: "@react-stately/tooltip@npm:3.5.8" dependencies: - "@react-stately/overlays": "npm:^3.6.17" - "@react-types/tooltip": "npm:^3.4.18" + "@react-stately/overlays": "npm:^3.6.20" + "@react-types/tooltip": "npm:^3.4.21" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/0744283f1dbb811502311370495b6722a59c251fe20ac2e5373aeed8f655ec9f89d92980426a69b7191c048f7c02e3a66c78a7018452ad4638c82e5b7f99b698 + checksum: 10/fbddb1f0efc6a6275f8f558bf80b984aea0c49f6c0d17fc42fc27e48a02a3c36bc9ca3eed6de9347a3b12289d21e22dc3de159b8b4b8ab21fe18218ab8a0e4ec languageName: node linkType: hard -"@react-stately/tree@npm:^3.9.0": - version: 3.9.0 - resolution: "@react-stately/tree@npm:3.9.0" +"@react-stately/tree@npm:^3.9.3": + version: 3.9.3 + resolution: "@react-stately/tree@npm:3.9.3" dependencies: - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/selection": "npm:^3.20.3" - "@react-stately/utils": "npm:^3.10.7" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/selection": "npm:^3.20.6" + "@react-stately/utils": "npm:^3.10.8" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/6980382c94f87a663124e9488e3cf5f8ea09b05fc2f0017cbb886aa19ce0d8525d8b6b8221f1e293a67543cc06786ea203813218c3444fe7e14b31d9eae65ca3 + checksum: 10/294cc70ffa08280a187a85f72c2402547d71295ddb95b2752fcfa395016947e7fe27116e970df597bab87319e18b3bf1f6b837124fb4bbda8686f7f0018b46ab languageName: node linkType: hard -"@react-stately/utils@npm:^3.10.7": - version: 3.10.7 - resolution: "@react-stately/utils@npm:3.10.7" +"@react-stately/utils@npm:^3.10.8": + version: 3.10.8 + resolution: "@react-stately/utils@npm:3.10.8" dependencies: "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/b9c1a62d4f179e252d08a2f18120a02ffc8704424f257e81e5e74da1222e3acd1e821ce84220d87d9d7b4b6d4dc2fd58d5bb380546d198bf434b700cda8ac3d8 + checksum: 10/7878ec47b132075566708bae630cb86d8237dde976eb3793bba43695abbb29fcaea9d00ea3f4f7244fcda253368f5b2b85263c37665c24e390500cdcc978c6fe languageName: node linkType: hard -"@react-stately/virtualizer@npm:^4.4.1": - version: 4.4.1 - resolution: "@react-stately/virtualizer@npm:4.4.1" +"@react-stately/virtualizer@npm:^4.4.4": + version: 4.4.4 + resolution: "@react-stately/virtualizer@npm:4.4.4" dependencies: - "@react-aria/utils": "npm:^3.29.1" - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" "@swc/helpers": "npm:^0.5.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/aab5c3a647dc43dd5120a6db4cdfdf24aa47f7fcabf273e05947e33af8cba172f4f442499729d53537a2aa46ca7292dcb94c6b4b4c5b017542df42c25a97a128 + checksum: 10/c9d8d4b34250b8c0e91811bc618c654bac3e8eabe7a8ec119abc8f5dbbfa19faa4b31575eb0775773fda0f533fc2835e9a233b4ed0e4ae1835ddb5f0521a18aa languageName: node linkType: hard -"@react-types/autocomplete@npm:3.0.0-alpha.32": - version: 3.0.0-alpha.32 - resolution: "@react-types/autocomplete@npm:3.0.0-alpha.32" +"@react-types/autocomplete@npm:3.0.0-alpha.35": + version: 3.0.0-alpha.35 + resolution: "@react-types/autocomplete@npm:3.0.0-alpha.35" dependencies: - "@react-types/combobox": "npm:^3.13.6" - "@react-types/searchfield": "npm:^3.6.3" - "@react-types/shared": "npm:^3.30.0" + "@react-types/combobox": "npm:^3.13.9" + "@react-types/searchfield": "npm:^3.6.6" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/ad617628499db45b2acb07d2f4a4b7aa0569124ee1b7c35b2f1eb9819a2d09a755ab4d3be489243c0d579fc16485aec24950ce3b132a655f83d302eb0d140f96 + checksum: 10/2a51111a94f5df1ce0b1b137a69ca783fa2fa399b4c305ebc7f137b0aa6a420cfe2a3925d40fda9a7d0d3b832d390823015959eee41b6c6b31f7a6b30739a596 languageName: node linkType: hard -"@react-types/breadcrumbs@npm:^3.7.14": - version: 3.7.14 - resolution: "@react-types/breadcrumbs@npm:3.7.14" +"@react-types/breadcrumbs@npm:^3.7.17": + version: 3.7.17 + resolution: "@react-types/breadcrumbs@npm:3.7.17" dependencies: - "@react-types/link": "npm:^3.6.2" - "@react-types/shared": "npm:^3.30.0" + "@react-types/link": "npm:^3.6.5" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/106fa21ce01b9ee16796ba46d1133b71b466bfc069e9a90d7f00280e177e1f009791db78701565d83c22506bf72b0469756238164d8ffa36c6712f4e95932eac + checksum: 10/e9754d1b8010f3cdfdfcd8abf03cdb5b37dc1038496fcc103569b9f349269b39680979c2293cdc04c376cd1ea7b97b00571d46677b9d4939a60dd01b55f765a6 languageName: node linkType: hard -"@react-types/button@npm:^3.12.2": - version: 3.12.2 - resolution: "@react-types/button@npm:3.12.2" +"@react-types/button@npm:^3.14.1": + version: 3.14.1 + resolution: "@react-types/button@npm:3.14.1" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/d00f7e23fd6cfa863c2d9f0f91ec47fc017666b55775842af3c001fabcf949dfa55b116674bcb841de568eacaf677c3a25e079b4810dcf857547bd9cf6d60917 + checksum: 10/bbbf2e5db83f6b925af154199aaad438d950187862c4ca6f82122c0209632c0c358201ec9b0b503f9b96c8b5b765066af41c6472440ca7ea75b75031d7d9eacf languageName: node linkType: hard -"@react-types/calendar@npm:^3.7.2": - version: 3.7.2 - resolution: "@react-types/calendar@npm:3.7.2" +"@react-types/calendar@npm:^3.8.0": + version: 3.8.0 + resolution: "@react-types/calendar@npm:3.8.0" dependencies: - "@internationalized/date": "npm:^3.8.2" - "@react-types/shared": "npm:^3.30.0" + "@internationalized/date": "npm:^3.10.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/40ad15a5f937844f6626028c8a6e7d36f09e946b4cbdfcd95ff4971f6681abd86260f64aa8298cf86fdde5a0ce2de17e327b8011bb435d0f3faf10fcd9c97f38 + checksum: 10/06fe32c8e5d78eedcb511fa3d18f66582b5664ab85c572538e24b953e8204a7c5f98407df0d028625a1dfdd94223153e8e04d9d7feefd96f7533b90fb82be907 languageName: node linkType: hard -"@react-types/checkbox@npm:^3.9.5": - version: 3.9.5 - resolution: "@react-types/checkbox@npm:3.9.5" - dependencies: - "@react-types/shared": "npm:^3.30.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/25f6c155043f25f55379b613e3e7faa16191f34c04f13acfc75fc5bda5b83d76d3062b177aad2401f9dd1570215714d477ab1d1e3b92a33e24172aa44e9ff79e - languageName: node - linkType: hard - -"@react-types/color@npm:^3.0.6": - version: 3.0.6 - resolution: "@react-types/color@npm:3.0.6" - dependencies: - "@react-types/shared": "npm:^3.30.0" - "@react-types/slider": "npm:^3.7.12" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/33ddf5239ccfdada1ae276a69b020500dae557a0a43c4bb0fb55fcd6122331c7f2adb552ff3706753214964032ea459634708a02f147777dff948045877cc01b - languageName: node - linkType: hard - -"@react-types/combobox@npm:^3.13.6": - version: 3.13.6 - resolution: "@react-types/combobox@npm:3.13.6" - dependencies: - "@react-types/shared": "npm:^3.30.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/8aaf970af426d084ba4b954aeca23cc7779de221a19465c1487d7098a5f637c13bcb6446bf695619e221d78d289cf629b94faa2c86de8bb3f949ff05a5448a13 - languageName: node - linkType: hard - -"@react-types/datepicker@npm:^3.12.2": - version: 3.12.2 - resolution: "@react-types/datepicker@npm:3.12.2" - dependencies: - "@internationalized/date": "npm:^3.8.2" - "@react-types/calendar": "npm:^3.7.2" - "@react-types/overlays": "npm:^3.8.16" - "@react-types/shared": "npm:^3.30.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/21d6b72986b18b25b6380bf85a7a12319de05160a1dee5d0e7484378627dee955c6cda9fbb0b6909e9edcfc82181be1d9e744220fcf82d75357d7208ed2978a9 - languageName: node - linkType: hard - -"@react-types/dialog@npm:^3.5.19": - version: 3.5.19 - resolution: "@react-types/dialog@npm:3.5.19" - dependencies: - "@react-types/overlays": "npm:^3.8.16" - "@react-types/shared": "npm:^3.30.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/07bd55d214d8162f1a700f1ac80cd51468d0defc0d9753309d5e58a0fffbc1eb65a588b6c0709593a41fa8d72cc1f8f8dba0a65b2a336968fdc2ff92afec3596 - languageName: node - linkType: hard - -"@react-types/form@npm:^3.7.13": - version: 3.7.13 - resolution: "@react-types/form@npm:3.7.13" - dependencies: - "@react-types/shared": "npm:^3.30.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/2c55ceb9f5e52a08b60ae0ae95d1db3e57a67d3783eaee2fb37870602afd612153506c13effec98bf4c7b58728a148e9d966c8c3442db560543779b9ef8dd091 - languageName: node - linkType: hard - -"@react-types/grid@npm:^3.3.3": - version: 3.3.3 - resolution: "@react-types/grid@npm:3.3.3" - dependencies: - "@react-types/shared": "npm:^3.30.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/cac232888139186110f7095cbb45ba2525522a296254f44290ad4c87ac2b1e72485d839e2820e7265cbcd6bc4cb8e49c170c52fd57defed16d06a4eb7f7cf047 - languageName: node - linkType: hard - -"@react-types/link@npm:^3.6.2": - version: 3.6.2 - resolution: "@react-types/link@npm:3.6.2" - dependencies: - "@react-types/shared": "npm:^3.30.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/093a3011a98f36dd252d7675365effcba219b9a89e53619e176bdf322042520d5d24e7d9dca04bd63fa6785242f097301c3921d111c43ed888072b0938133435 - languageName: node - linkType: hard - -"@react-types/listbox@npm:^3.7.1": - version: 3.7.1 - resolution: "@react-types/listbox@npm:3.7.1" - dependencies: - "@react-types/shared": "npm:^3.30.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/2040a31a6eae1a0d0fe44f2d6410dfd6e9f99849eaba4fea4b4819ed162f2642d5e023d0badb4f78b2e0d60c4480cacc2d0745f9881f77b83c20b7c2012adf0b - languageName: node - linkType: hard - -"@react-types/menu@npm:^3.10.2": +"@react-types/checkbox@npm:^3.10.2": version: 3.10.2 - resolution: "@react-types/menu@npm:3.10.2" + resolution: "@react-types/checkbox@npm:3.10.2" dependencies: - "@react-types/overlays": "npm:^3.8.16" - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/9b6cc0818f1d63225f7794ca89d0fa25cd771bad4440fa52c403d81d7027b1f83ba600603ede4ee05dee01b57d1240c9eaa7ed890150aa9dff0c8113dc0c85ab + checksum: 10/3d2f8468ce3326825bc820c958dc52b68f11a18ff15a68de2663115b168fecb165a2381cfecf2d7a254bfba66760590d8d76dabae5f48626a15eddf309206516 languageName: node linkType: hard -"@react-types/meter@npm:^3.4.10": - version: 3.4.10 - resolution: "@react-types/meter@npm:3.4.10" +"@react-types/color@npm:^3.1.2": + version: 3.1.2 + resolution: "@react-types/color@npm:3.1.2" dependencies: - "@react-types/progress": "npm:^3.5.13" + "@react-types/shared": "npm:^3.32.1" + "@react-types/slider": "npm:^3.8.2" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/b55f4ca464fc2873662ee50d25cdc1c77995d34d39b6d2831c0b121e47c7b12051017576f51909881a3776003e03263ce899dcf572a9f083794b160320baa754 + checksum: 10/a41e786bd17b1815d5b7414f2dcbc79e655c3a4b8fe2dfa68c200c553f922bab5468a2ea272c76cdf6611d7d3f20518ca31b442729ef7b68141d91839e580410 languageName: node linkType: hard -"@react-types/numberfield@npm:^3.8.12": - version: 3.8.12 - resolution: "@react-types/numberfield@npm:3.8.12" +"@react-types/combobox@npm:^3.13.9": + version: 3.13.9 + resolution: "@react-types/combobox@npm:3.13.9" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/98989cdcd7b7bef45129c54e9bdb919d06f09109c786f0783105c617304ee3ce15c9aad01507d4d9aa0e974ee3b50b230c057ad7a48f634247e374c9668080ae + checksum: 10/0583d24f38b965e5c2cd2b436a7ad374635e183dc7c12145ce9ed0a166d7b6e46ed4685a68c9fb24aed065d1fca644ca3b0606cb360ae5fac3a9881e88ee2f2b languageName: node linkType: hard -"@react-types/overlays@npm:^3.8.16": - version: 3.8.16 - resolution: "@react-types/overlays@npm:3.8.16" +"@react-types/datepicker@npm:^3.13.2": + version: 3.13.2 + resolution: "@react-types/datepicker@npm:3.13.2" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@internationalized/date": "npm:^3.10.0" + "@react-types/calendar": "npm:^3.8.0" + "@react-types/overlays": "npm:^3.9.2" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/12bedf8e79d31827cd9868dcb115d07b9fee7954af5e00c1a46fe87b9f2b08e971af4b1b238faa2ce7ed173600786a83c7b9cfcdee5c7464a42bc581d7dee3a6 + checksum: 10/1f1686360f64051f5eff5e170ab78e890b20e07680b6031c96c77e47085ca022c55997018911095cd61076bdf63470f61c99ac25ef9b493420f69cde6e4763bd languageName: node linkType: hard -"@react-types/progress@npm:^3.5.13": - version: 3.5.13 - resolution: "@react-types/progress@npm:3.5.13" +"@react-types/dialog@npm:^3.5.22": + version: 3.5.22 + resolution: "@react-types/dialog@npm:3.5.22" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/overlays": "npm:^3.9.2" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/f666892cff510323e90b1e72e5351eef4f38eb752e568f46cb30250a7de8b9a4435f3506fc590d748d3a0ce30a5f64d449a88a8656369137d06a584ef667d0a8 + checksum: 10/dedac6cf8a85568344242eb6e7f9c6f9dd9fff31711d23586374a1cfc4f3b7b7bed43fdff633d54135792dcdd9941a8a15a34bbbec1a9d4caff7b869b35dd71e languageName: node linkType: hard -"@react-types/radio@npm:^3.8.10": - version: 3.8.10 - resolution: "@react-types/radio@npm:3.8.10" +"@react-types/form@npm:^3.7.16": + version: 3.7.16 + resolution: "@react-types/form@npm:3.7.16" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/ba87e61b7a84547c417baa9553bdfebf2fcd03d45038f0d6a0031a5d4e6c94f9d9a81fe8a98579c6830dcffad68c71560ccac8fd842d5f2469a05ce275d92250 + checksum: 10/3e8f156318746d31ef7470d366dcc1004f3a59b1a3a3f9e54331921a4b251ff51c6bf76a32be229f6d8c524b5b1292f3c1135597de6b0f52bae2d8c32a542a74 languageName: node linkType: hard -"@react-types/searchfield@npm:^3.6.3": - version: 3.6.3 - resolution: "@react-types/searchfield@npm:3.6.3" +"@react-types/grid@npm:^3.3.6": + version: 3.3.6 + resolution: "@react-types/grid@npm:3.3.6" dependencies: - "@react-types/shared": "npm:^3.30.0" - "@react-types/textfield": "npm:^3.12.3" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/ffe5a909fb94a28c674c1ae798e511d93be5175c3fc8adcadc88e040c6e5aca4cf55565b321219311537c11c5ce70c005aa214d8dc708a4b1583a1f1a68a75f6 + checksum: 10/2b4be0fd8f6d07d3feca68039b89e0c13e1e566d27334a6ca7b6368f073ee55cf026833c5af664c78ccd137716aefd4f46b88f1b97709cd8080d7380c79454df languageName: node linkType: hard -"@react-types/select@npm:^3.9.13": - version: 3.9.13 - resolution: "@react-types/select@npm:3.9.13" +"@react-types/link@npm:^3.6.5": + version: 3.6.5 + resolution: "@react-types/link@npm:3.6.5" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/9fba560d2060eb852289be76f0e0b691bddd48f744f969862da10d38c8963f6931190cb53cc8c5ea01eab3f447b8a680e6da378fe6287ec80d3f48a62d312759 + checksum: 10/59fb6011b146cffcdaae94e8fdd9241cb70697f7e518d39e3aacd14f244db6eea7ba3984d8b13d3ce601e6f160da36fd1bfa56827b2e1df728505e426a8db353 languageName: node linkType: hard -"@react-types/shared@npm:^3.30.0": - version: 3.30.0 - resolution: "@react-types/shared@npm:3.30.0" +"@react-types/listbox@npm:^3.7.4": + version: 3.7.4 + resolution: "@react-types/listbox@npm:3.7.4" + dependencies: + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/58af4134275a347bf18ac5d15e3dcfd07dcf623e1d494f140303e06f2149b7aad86408979e163393346df613f6390a3a387f77a2937f0bf1908c6672a44f7b69 + checksum: 10/79dd3f6a7284b74f5156cc2265b384d2074ddfb7b38e608be855ec4ad1234aa0e7cdbfc0d7ef899e34113781381a6ee18b820dbe3dbee67364c72ac240144522 languageName: node linkType: hard -"@react-types/slider@npm:^3.7.12": - version: 3.7.12 - resolution: "@react-types/slider@npm:3.7.12" +"@react-types/menu@npm:^3.10.5": + version: 3.10.5 + resolution: "@react-types/menu@npm:3.10.5" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/overlays": "npm:^3.9.2" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/38b8a556f87bb64c7f47af482a1a3ce688345a3d4b7a2c71e99522bdcb9668f8ed8e3ea0797b32d5ac1a95d6557c5f9e8eadab51e8eb780f9e66efa89ba50fa0 + checksum: 10/0466f5b7602ccfc8cb8fec3cd2482d587acbfd1701d427c7d79a121eb3f2b137feca70e62fd401aea95022fd616460575c4d5dd541cf3d69d8644ca54a2446c8 languageName: node linkType: hard -"@react-types/switch@npm:^3.5.12": - version: 3.5.12 - resolution: "@react-types/switch@npm:3.5.12" +"@react-types/meter@npm:^3.4.13": + version: 3.4.13 + resolution: "@react-types/meter@npm:3.4.13" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/progress": "npm:^3.5.16" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/6552f113b0c3abf52f590b8cedf17f5901e7fa2d0ed94b30408fd2fbda907ee17e7792af6d86985ca742a3cb5b667bcbf6cec725e66265ccdfd201b77e7f524b + checksum: 10/28b519a4640c72732719c056903fcf4037582984d235c388095319b5005eb9d5d2698306d9f79d1ad61d594b8ceda115acae27c22e95cb771d0e07da30305708 languageName: node linkType: hard -"@react-types/table@npm:^3.13.1": - version: 3.13.1 - resolution: "@react-types/table@npm:3.13.1" +"@react-types/numberfield@npm:^3.8.15": + version: 3.8.15 + resolution: "@react-types/numberfield@npm:3.8.15" dependencies: - "@react-types/grid": "npm:^3.3.3" - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/be1bac716d13148b47016f2156ee0769c044d301b538df934f6b8aa5466265a750391e462f9fcdebff7dbb93cf9e373e2117f91eab528b3f5cef062174e547ee + checksum: 10/242584ab3ece90a5e26ebee9788c25fd44b85d6be405c5f31e08bda9d58ad8d7fcf199744a2fcd816275da13ae546ca0239175403e68788a43563f2a070c0574 languageName: node linkType: hard -"@react-types/tabs@npm:^3.3.16": - version: 3.3.16 - resolution: "@react-types/tabs@npm:3.3.16" +"@react-types/overlays@npm:^3.9.2": + version: 3.9.2 + resolution: "@react-types/overlays@npm:3.9.2" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/fae8d98776408b0e9776d0217a545a1ed6035ac976321e413e4f442b525375c56854a328c33e77564efe525e66bc7b79dc89e38ff02373788b996c4b46bb6c5d + checksum: 10/6cab7f2cbb813f710696095db1169f902cfe7e4a9aeef496848343ff5116be3782bfea68dffbeaf3f984a0475c2fb6c4a26ad9fb563172c4ec3e47110ca1e672 languageName: node linkType: hard -"@react-types/textfield@npm:^3.12.3": - version: 3.12.3 - resolution: "@react-types/textfield@npm:3.12.3" +"@react-types/progress@npm:^3.5.16": + version: 3.5.16 + resolution: "@react-types/progress@npm:3.5.16" dependencies: - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/d8bf58fd569b30fa13f98de834a025c9ef71d6de8c669912aa7083c83f88f7261852e0b1b30953e903d377b5b63cc849b848fd549a1466c82d6a74cb6c540cf5 + checksum: 10/315b34314dc135a6c9319f4ffd83570fac8c0da377b00d56f17c6eb3d416904682738b522b05d6d8cbb89d3ef92c5118bf8e58eca10fac121da6dcaa40563b8d languageName: node linkType: hard -"@react-types/tooltip@npm:^3.4.18": - version: 3.4.18 - resolution: "@react-types/tooltip@npm:3.4.18" +"@react-types/radio@npm:^3.9.2": + version: 3.9.2 + resolution: "@react-types/radio@npm:3.9.2" dependencies: - "@react-types/overlays": "npm:^3.8.16" - "@react-types/shared": "npm:^3.30.0" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/5eed69c83727496a6d06796617da86740ab2629b3bd6a106c6ddfb384aaa74725aed3c3eed44f329dcebe7cf87a261ce33e8aa8a5899549446321c1a86d27b87 + checksum: 10/3375d13bbeed28a1b959077e727b43324f4282cf43ec985edbaaa5b3e50b46199c083550882e2a9e4788c74555bfd25f5cc2b0351bf48a768f81a4ba6bf73222 + languageName: node + linkType: hard + +"@react-types/searchfield@npm:^3.6.6": + version: 3.6.6 + resolution: "@react-types/searchfield@npm:3.6.6" + dependencies: + "@react-types/shared": "npm:^3.32.1" + "@react-types/textfield": "npm:^3.12.6" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/942cb80234be5d61cae410c144873d75a243dec0bbf8bb0c696f13d66fd729dabb188bb6214d4bfadeb0d54e14eed3bb7e86c6721206bcb395658b613f22b53f + languageName: node + linkType: hard + +"@react-types/select@npm:^3.11.0": + version: 3.11.0 + resolution: "@react-types/select@npm:3.11.0" + dependencies: + "@react-types/shared": "npm:^3.32.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/6c431daa847a034ce06625fe75f220f301e8bdb50961c74e915f36919641f7907aa0d16d15127b9889853d197d66d964fd3726bd6c446b8aecf0e756e30e3925 + languageName: node + linkType: hard + +"@react-types/shared@npm:^3.32.1": + version: 3.32.1 + resolution: "@react-types/shared@npm:3.32.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/33c39d1e23fd73a18519679742ba548c128097831710af4803bec244ae96800271f88dcc4eab958734fc501bb65c17e590028596733761610fb0103c5dea6e36 + languageName: node + linkType: hard + +"@react-types/slider@npm:^3.8.2": + version: 3.8.2 + resolution: "@react-types/slider@npm:3.8.2" + dependencies: + "@react-types/shared": "npm:^3.32.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/cb9600a1842ace218be1a8bdb7b6785113c7165fde0cc76682b82cf7809927d2f45f95facb2570e7abb683f28f0a2ed0590c8ec8e948ed8dadffadb8905918d9 + languageName: node + linkType: hard + +"@react-types/switch@npm:^3.5.15": + version: 3.5.15 + resolution: "@react-types/switch@npm:3.5.15" + dependencies: + "@react-types/shared": "npm:^3.32.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/f35c075188b93aa07b6ab367a6d5bcc4316bcd5481d47e1b0319944411e3a12b15455c443079159280b6d168da36271f3df8bc55808a7d8249b239f5886f0253 + languageName: node + linkType: hard + +"@react-types/table@npm:^3.13.4": + version: 3.13.4 + resolution: "@react-types/table@npm:3.13.4" + dependencies: + "@react-types/grid": "npm:^3.3.6" + "@react-types/shared": "npm:^3.32.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/2f8c1878c8b9a6515a62c7592a335e9688c95a07e0445a891dd6069cbe26921573db6f7d6d2e0c22a8818ec5ef3f48f242ae24d955a1b18e7868f306fadfe7f5 + languageName: node + linkType: hard + +"@react-types/tabs@npm:^3.3.19": + version: 3.3.19 + resolution: "@react-types/tabs@npm:3.3.19" + dependencies: + "@react-types/shared": "npm:^3.32.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/cdc3217251502c6f89621ab366a4d23e32a334dc3ca2f5366cd980fb828bb413be1262a76f4c4794a0908bfd02c3237a3608e283b02ef472707fb7c22b80b44b + languageName: node + linkType: hard + +"@react-types/textfield@npm:^3.12.6": + version: 3.12.6 + resolution: "@react-types/textfield@npm:3.12.6" + dependencies: + "@react-types/shared": "npm:^3.32.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/e223531d29bbaad566f142b44a0f2e42b4ce08eab5661962ad3451391311a604077c49181f89a407aecf8697d59d887f5524f6eff8e9fe7416afda6b1f3ac7b3 + languageName: node + linkType: hard + +"@react-types/tooltip@npm:^3.4.21": + version: 3.4.21 + resolution: "@react-types/tooltip@npm:3.4.21" + dependencies: + "@react-types/overlays": "npm:^3.9.2" + "@react-types/shared": "npm:^3.32.1" + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + checksum: 10/50d1beea407a7e58ef8e3638c2517d8c90f6b15777d396b4adf7cffbd80d38dfb7d68d6a38127ed130bfe7b0c3116c5d499de3f7b6353f54d022a22739e0141d languageName: node linkType: hard @@ -42168,95 +42166,96 @@ __metadata: languageName: node linkType: hard -"react-aria-components@npm:^1.10.1": - version: 1.10.1 - resolution: "react-aria-components@npm:1.10.1" +"react-aria-components@npm:^1.13.0": + version: 1.13.0 + resolution: "react-aria-components@npm:1.13.0" dependencies: - "@internationalized/date": "npm:^3.8.2" + "@internationalized/date": "npm:^3.10.0" "@internationalized/string": "npm:^3.2.7" - "@react-aria/autocomplete": "npm:3.0.0-beta.5" - "@react-aria/collections": "npm:3.0.0-rc.3" - "@react-aria/dnd": "npm:^3.10.1" - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/live-announcer": "npm:^3.4.3" - "@react-aria/overlays": "npm:^3.27.3" - "@react-aria/ssr": "npm:^3.9.9" - "@react-aria/toolbar": "npm:3.0.0-beta.18" - "@react-aria/utils": "npm:^3.29.1" - "@react-aria/virtualizer": "npm:^4.1.7" - "@react-stately/autocomplete": "npm:3.0.0-beta.2" - "@react-stately/layout": "npm:^4.3.1" - "@react-stately/selection": "npm:^3.20.3" - "@react-stately/table": "npm:^3.14.3" - "@react-stately/utils": "npm:^3.10.7" - "@react-stately/virtualizer": "npm:^4.4.1" - "@react-types/form": "npm:^3.7.13" - "@react-types/grid": "npm:^3.3.3" - "@react-types/shared": "npm:^3.30.0" - "@react-types/table": "npm:^3.13.1" + "@react-aria/autocomplete": "npm:3.0.0-rc.3" + "@react-aria/collections": "npm:^3.0.0" + "@react-aria/dnd": "npm:^3.11.3" + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/live-announcer": "npm:^3.4.4" + "@react-aria/overlays": "npm:^3.30.0" + "@react-aria/ssr": "npm:^3.9.10" + "@react-aria/textfield": "npm:^3.18.2" + "@react-aria/toolbar": "npm:3.0.0-beta.21" + "@react-aria/utils": "npm:^3.31.0" + "@react-aria/virtualizer": "npm:^4.1.10" + "@react-stately/autocomplete": "npm:3.0.0-beta.3" + "@react-stately/layout": "npm:^4.5.1" + "@react-stately/selection": "npm:^3.20.6" + "@react-stately/table": "npm:^3.15.1" + "@react-stately/utils": "npm:^3.10.8" + "@react-stately/virtualizer": "npm:^4.4.4" + "@react-types/form": "npm:^3.7.16" + "@react-types/grid": "npm:^3.3.6" + "@react-types/shared": "npm:^3.32.1" + "@react-types/table": "npm:^3.13.4" "@swc/helpers": "npm:^0.5.0" client-only: "npm:^0.0.1" - react-aria: "npm:^3.41.1" - react-stately: "npm:^3.39.0" + react-aria: "npm:^3.44.0" + react-stately: "npm:^3.42.0" use-sync-external-store: "npm:^1.4.0" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/6fcc35404bdd8718bbfb05263bd0c67157d2ba665e0446c47f42f78262ef92231bb0512fc7734c2114bb20c28fff8eb13694c9719c741d2c7a59181fd8fdf115 + checksum: 10/8bff1890ef342b0c32d6a50329ce4657bce2fcc91f2a2f903351f375354b186b47f265e7718caaff0ed9a5f630037f17649d85d00bc20a4928a6417204d75ff2 languageName: node linkType: hard -"react-aria@npm:^3.41.1": - version: 3.41.1 - resolution: "react-aria@npm:3.41.1" +"react-aria@npm:^3.44.0": + version: 3.44.0 + resolution: "react-aria@npm:3.44.0" dependencies: "@internationalized/string": "npm:^3.2.7" - "@react-aria/breadcrumbs": "npm:^3.5.26" - "@react-aria/button": "npm:^3.13.3" - "@react-aria/calendar": "npm:^3.8.3" - "@react-aria/checkbox": "npm:^3.15.7" - "@react-aria/color": "npm:^3.0.9" - "@react-aria/combobox": "npm:^3.12.5" - "@react-aria/datepicker": "npm:^3.14.5" - "@react-aria/dialog": "npm:^3.5.27" - "@react-aria/disclosure": "npm:^3.0.6" - "@react-aria/dnd": "npm:^3.10.1" - "@react-aria/focus": "npm:^3.20.5" - "@react-aria/gridlist": "npm:^3.13.2" - "@react-aria/i18n": "npm:^3.12.10" - "@react-aria/interactions": "npm:^3.25.3" - "@react-aria/label": "npm:^3.7.19" - "@react-aria/landmark": "npm:^3.0.4" - "@react-aria/link": "npm:^3.8.3" - "@react-aria/listbox": "npm:^3.14.6" - "@react-aria/menu": "npm:^3.18.5" - "@react-aria/meter": "npm:^3.4.24" - "@react-aria/numberfield": "npm:^3.11.16" - "@react-aria/overlays": "npm:^3.27.3" - "@react-aria/progress": "npm:^3.4.24" - "@react-aria/radio": "npm:^3.11.5" - "@react-aria/searchfield": "npm:^3.8.6" - "@react-aria/select": "npm:^3.15.7" - "@react-aria/selection": "npm:^3.24.3" - "@react-aria/separator": "npm:^3.4.10" - "@react-aria/slider": "npm:^3.7.21" - "@react-aria/ssr": "npm:^3.9.9" - "@react-aria/switch": "npm:^3.7.5" - "@react-aria/table": "npm:^3.17.5" - "@react-aria/tabs": "npm:^3.10.5" - "@react-aria/tag": "npm:^3.6.2" - "@react-aria/textfield": "npm:^3.17.5" - "@react-aria/toast": "npm:^3.0.5" - "@react-aria/tooltip": "npm:^3.8.5" - "@react-aria/tree": "npm:^3.1.1" - "@react-aria/utils": "npm:^3.29.1" - "@react-aria/visually-hidden": "npm:^3.8.25" - "@react-types/shared": "npm:^3.30.0" + "@react-aria/breadcrumbs": "npm:^3.5.29" + "@react-aria/button": "npm:^3.14.2" + "@react-aria/calendar": "npm:^3.9.2" + "@react-aria/checkbox": "npm:^3.16.2" + "@react-aria/color": "npm:^3.1.2" + "@react-aria/combobox": "npm:^3.14.0" + "@react-aria/datepicker": "npm:^3.15.2" + "@react-aria/dialog": "npm:^3.5.31" + "@react-aria/disclosure": "npm:^3.1.0" + "@react-aria/dnd": "npm:^3.11.3" + "@react-aria/focus": "npm:^3.21.2" + "@react-aria/gridlist": "npm:^3.14.1" + "@react-aria/i18n": "npm:^3.12.13" + "@react-aria/interactions": "npm:^3.25.6" + "@react-aria/label": "npm:^3.7.22" + "@react-aria/landmark": "npm:^3.0.7" + "@react-aria/link": "npm:^3.8.6" + "@react-aria/listbox": "npm:^3.15.0" + "@react-aria/menu": "npm:^3.19.3" + "@react-aria/meter": "npm:^3.4.27" + "@react-aria/numberfield": "npm:^3.12.2" + "@react-aria/overlays": "npm:^3.30.0" + "@react-aria/progress": "npm:^3.4.27" + "@react-aria/radio": "npm:^3.12.2" + "@react-aria/searchfield": "npm:^3.8.9" + "@react-aria/select": "npm:^3.17.0" + "@react-aria/selection": "npm:^3.26.0" + "@react-aria/separator": "npm:^3.4.13" + "@react-aria/slider": "npm:^3.8.2" + "@react-aria/ssr": "npm:^3.9.10" + "@react-aria/switch": "npm:^3.7.8" + "@react-aria/table": "npm:^3.17.8" + "@react-aria/tabs": "npm:^3.10.8" + "@react-aria/tag": "npm:^3.7.2" + "@react-aria/textfield": "npm:^3.18.2" + "@react-aria/toast": "npm:^3.0.8" + "@react-aria/tooltip": "npm:^3.8.8" + "@react-aria/tree": "npm:^3.1.4" + "@react-aria/utils": "npm:^3.31.0" + "@react-aria/visually-hidden": "npm:^3.8.28" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/6ec619bc9b26800516e22054a428ea29ebc7bcfabf762918893a5a1a73d1576dd4b1c99d85aae02ae69eb16a49d1a765ab34cb840a500134a76e145a4e995f42 + checksum: 10/46b428af3f68703c03d7836a79f288dae1e945cb34164220a61f57d77df0a5adfc6c4a4c993282f9dbf57f159c9d249e1d644b57b61caca3dec8af1285404ec1 languageName: node linkType: hard @@ -42866,39 +42865,39 @@ __metadata: languageName: node linkType: hard -"react-stately@npm:^3.39.0": - version: 3.39.0 - resolution: "react-stately@npm:3.39.0" +"react-stately@npm:^3.42.0": + version: 3.42.0 + resolution: "react-stately@npm:3.42.0" dependencies: - "@react-stately/calendar": "npm:^3.8.2" - "@react-stately/checkbox": "npm:^3.6.15" - "@react-stately/collections": "npm:^3.12.5" - "@react-stately/color": "npm:^3.8.6" - "@react-stately/combobox": "npm:^3.10.6" - "@react-stately/data": "npm:^3.13.1" - "@react-stately/datepicker": "npm:^3.14.2" - "@react-stately/disclosure": "npm:^3.0.5" - "@react-stately/dnd": "npm:^3.6.0" - "@react-stately/form": "npm:^3.1.5" - "@react-stately/list": "npm:^3.12.3" - "@react-stately/menu": "npm:^3.9.5" - "@react-stately/numberfield": "npm:^3.9.13" - "@react-stately/overlays": "npm:^3.6.17" - "@react-stately/radio": "npm:^3.10.14" - "@react-stately/searchfield": "npm:^3.5.13" - "@react-stately/select": "npm:^3.6.14" - "@react-stately/selection": "npm:^3.20.3" - "@react-stately/slider": "npm:^3.6.5" - "@react-stately/table": "npm:^3.14.3" - "@react-stately/tabs": "npm:^3.8.3" - "@react-stately/toast": "npm:^3.1.1" - "@react-stately/toggle": "npm:^3.8.5" - "@react-stately/tooltip": "npm:^3.5.5" - "@react-stately/tree": "npm:^3.9.0" - "@react-types/shared": "npm:^3.30.0" + "@react-stately/calendar": "npm:^3.9.0" + "@react-stately/checkbox": "npm:^3.7.2" + "@react-stately/collections": "npm:^3.12.8" + "@react-stately/color": "npm:^3.9.2" + "@react-stately/combobox": "npm:^3.12.0" + "@react-stately/data": "npm:^3.14.1" + "@react-stately/datepicker": "npm:^3.15.2" + "@react-stately/disclosure": "npm:^3.0.8" + "@react-stately/dnd": "npm:^3.7.1" + "@react-stately/form": "npm:^3.2.2" + "@react-stately/list": "npm:^3.13.1" + "@react-stately/menu": "npm:^3.9.8" + "@react-stately/numberfield": "npm:^3.10.2" + "@react-stately/overlays": "npm:^3.6.20" + "@react-stately/radio": "npm:^3.11.2" + "@react-stately/searchfield": "npm:^3.5.16" + "@react-stately/select": "npm:^3.8.0" + "@react-stately/selection": "npm:^3.20.6" + "@react-stately/slider": "npm:^3.7.2" + "@react-stately/table": "npm:^3.15.1" + "@react-stately/tabs": "npm:^3.8.6" + "@react-stately/toast": "npm:^3.1.2" + "@react-stately/toggle": "npm:^3.9.2" + "@react-stately/tooltip": "npm:^3.5.8" + "@react-stately/tree": "npm:^3.9.3" + "@react-types/shared": "npm:^3.32.1" peerDependencies: react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 - checksum: 10/f59f86aca0797e389698fc20a7e88a26748e00e56e011dd6d9f7a4fa1ba7fda32083bc8e5f2af000957d20ad9f4c74dd151cb667b958dcac8f3959d860905fd4 + checksum: 10/4913f8ae9beb909d07669b97c0960dadad72c3c9e572051158a64acac3eadc73ff495b3c145b3673c15494751506e5b8a666a59f65364900fa66917412971d32 languageName: node linkType: hard From df7d2cfca92898db7ecf8db5b61379fb000b3f58 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 8 Oct 2025 21:19:11 +0100 Subject: [PATCH 119/244] Create grumpy-items-peel.md Signed-off-by: Charles de Dreuille --- .changeset/grumpy-items-peel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/grumpy-items-peel.md diff --git a/.changeset/grumpy-items-peel.md b/.changeset/grumpy-items-peel.md new file mode 100644 index 0000000000..bace05e42e --- /dev/null +++ b/.changeset/grumpy-items-peel.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Update react-aria-components to version 1.13.0 From 5e0b5299d3b5026ab53b6a18c8be67cee2483e52 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 9 Oct 2025 11:18:48 +0200 Subject: [PATCH 120/244] Adjust stale issue and PR settings in workflow Signed-off-by: Patrik Oldsberg --- .github/workflows/automate_stale.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/automate_stale.yml b/.github/workflows/automate_stale.yml index d6c86b9afb..5b92c6211b 100644 --- a/.github/workflows/automate_stale.yml +++ b/.github/workflows/automate_stale.yml @@ -27,7 +27,7 @@ jobs: recent activity. It will be closed if no further activity occurs. Thank you for your contributions. days-before-issue-stale: 60 - days-before-issue-close: 7 + days-before-issue-close: 14 exempt-issue-labels: after vacations,no stale stale-issue-label: stale stale-pr-message: > @@ -35,8 +35,8 @@ jobs: recent activity from the author. It will be closed if no further activity occurs. If the PR was closed and you want it re-opened, let us know and we'll re-open the PR so that you can continue the contribution! - days-before-pr-stale: 14 - days-before-pr-close: 7 + days-before-pr-stale: 30 + days-before-pr-close: 14 exempt-pr-labels: after vacations,no stale stale-pr-label: stale operations-per-run: 100 From 796d866a1673dca70cae8109e27f065572f73afb Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 9 Oct 2025 11:33:31 +0200 Subject: [PATCH 121/244] workflows/e2e-techdocs: add explicit node setup Signed-off-by: Patrik Oldsberg --- .github/workflows/verify_e2e-techdocs.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/verify_e2e-techdocs.yml b/.github/workflows/verify_e2e-techdocs.yml index 64ce9e7b12..e933efe3f8 100644 --- a/.github/workflows/verify_e2e-techdocs.yml +++ b/.github/workflows/verify_e2e-techdocs.yml @@ -41,6 +41,10 @@ jobs: with: python-version: '3.9' + - name: use node.js ${{ matrix.node-version }} + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: ${{ matrix.node-version }} - name: yarn install uses: backstage/actions/yarn-install@b3c1841fd69e1658ac631afafd0fb140a2309024 # v0.6.17 with: From e979fe207683c52cb359646d56eddbf1ba7e723e Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 9 Oct 2025 10:36:38 +0100 Subject: [PATCH 122/244] Update warm-dancers-call.md Signed-off-by: Charles de Dreuille --- .changeset/warm-dancers-call.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/warm-dancers-call.md b/.changeset/warm-dancers-call.md index 62cdfb9baf..aa69005663 100644 --- a/.changeset/warm-dancers-call.md +++ b/.changeset/warm-dancers-call.md @@ -2,4 +2,4 @@ '@backstage/theme': minor --- -**BREAKING**: Removed noCssBaseline prop in UnifiedThemeProvider. +**BREAKING**: Removed noCssBaseline prop in UnifiedThemeProvider. If your Backstage instance looks broken after this update, there's a high chance that you forgot to add our new Backstage UI global CSS. To do that, please add @backstage/ui/css/styles.css at the root of your application. From f81b00fa7550495006335021e3c9fc1d712c902e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 9 Oct 2025 11:46:13 +0200 Subject: [PATCH 123/244] add dialog component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../src/components/Dialog/Dialog.stories.tsx | 96 ++++++++++++++ .../src/components/Dialog/Dialog.styles.css | 108 +++++++++++++++ packages/ui/src/components/Dialog/Dialog.tsx | 124 ++++++++++++++++++ packages/ui/src/components/Dialog/index.ts | 17 +++ packages/ui/src/components/Dialog/types.ts | 64 +++++++++ packages/ui/src/index.ts | 1 + 6 files changed, 410 insertions(+) create mode 100644 packages/ui/src/components/Dialog/Dialog.stories.tsx create mode 100644 packages/ui/src/components/Dialog/Dialog.styles.css create mode 100644 packages/ui/src/components/Dialog/Dialog.tsx create mode 100644 packages/ui/src/components/Dialog/index.ts create mode 100644 packages/ui/src/components/Dialog/types.ts diff --git a/packages/ui/src/components/Dialog/Dialog.stories.tsx b/packages/ui/src/components/Dialog/Dialog.stories.tsx new file mode 100644 index 0000000000..47b62330f7 --- /dev/null +++ b/packages/ui/src/components/Dialog/Dialog.stories.tsx @@ -0,0 +1,96 @@ +/* + * 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 { Meta, StoryObj } from '@storybook/react-vite'; +import { + Dialog, + DialogTrigger, + DialogHeader, + DialogBody, + DialogFooter, + DialogClose, +} from './Dialog'; +import { Button, Flex, Text } from '@backstage/ui'; + +const meta = { + title: 'Components/Dialog', + component: Dialog, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: ( + <> + Hello + + Hello world + + + + Close + console.log('Save')}> + Save + + + + + ), + }, + render: args => ( + + + + + ), +}; + +export const CustomBodyMaxHeight: Story = { + args: { + children: ( + <> + Hello + + {Array.from({ length: 40 }).map((_, index) => ( + + Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, + quos. + + ))} + + + + Close + console.log('Save')}> + Save + + + + + ), + }, + render: args => ( + + + + + ), +}; diff --git a/packages/ui/src/components/Dialog/Dialog.styles.css b/packages/ui/src/components/Dialog/Dialog.styles.css new file mode 100644 index 0000000000..8e445a42a8 --- /dev/null +++ b/packages/ui/src/components/Dialog/Dialog.styles.css @@ -0,0 +1,108 @@ +/* Backdrop */ +.bui-Dialog { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; +} + +.bui-Dialog[data-entering] { + animation: fade-in 200ms ease-out forwards; +} + +.bui-Dialog[data-exiting] { + animation: fade-out 150ms ease-out forwards; +} + +.bui-DialogContent { + background: var(--bui-bg-surface-1); + border-radius: 0.5rem; + border: 1px solid var(--bui-border); + color: var(--bui-fg-primary); + position: relative; + width: 24rem; + max-width: calc(100vw - 3rem); + display: flex; + flex-direction: column; +} + +/* Dialog entering animation */ +.bui-Dialog[data-entering] .bui-DialogContent { + animation: dialog-enter 150ms ease-out forwards; +} + +/* Dialog exiting animation */ +.bui-Dialog[data-exiting] .bui-DialogContent { + animation: dialog-exit 150ms ease-out forwards; +} + +.bui-DialogHeader { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--bui-space-3); + border-bottom: 1px solid var(--bui-border); +} + +.bui-Dialog [slot="title"] { + font-size: var(--bui-font-size-3); +} + +.bui-DialogFooter { + display: flex; + align-items: center; + justify-content: end; + gap: var(--bui-space-2); + padding: var(--bui-space-3); + border-top: 1px solid var(--bui-border); +} + +.bui-DialogBody { + padding: var(--bui-space-3); +} + +/* Keyframe animations */ +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fade-out { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@keyframes dialog-enter { + from { + opacity: 0.5; + transform: scale(0.8); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes dialog-exit { + from { + opacity: 1; + transform: scale(1); + } + to { + opacity: 0; + transform: scale(0.95); + } +} \ No newline at end of file diff --git a/packages/ui/src/components/Dialog/Dialog.tsx b/packages/ui/src/components/Dialog/Dialog.tsx new file mode 100644 index 0000000000..2f8bd27c27 --- /dev/null +++ b/packages/ui/src/components/Dialog/Dialog.tsx @@ -0,0 +1,124 @@ +/* + * 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 { forwardRef } from 'react'; +import { + Dialog as RADialog, + DialogTrigger as RADialogTrigger, + Modal, + Heading, +} from 'react-aria-components'; +import clsx from 'clsx'; +import type { + DialogTriggerProps, + DialogHeaderProps, + DialogProps, + DialogBodyProps, + DialogCloseProps, +} from './types'; +import './Dialog.styles.css'; +import { RiCloseLine } from '@remixicon/react'; +import { ScrollArea } from '../ScrollArea'; +import { Button } from '../Button'; + +/** @public */ +export const DialogTrigger = (props: DialogTriggerProps) => { + return ; +}; + +/** @public */ +export const DialogHeader = forwardRef< + React.ElementRef<'div'>, + DialogHeaderProps +>(({ className, children, ...props }, ref) => ( +
+ + {children} + + +
+)); +DialogHeader.displayName = 'DialogHeader'; + +/** @public */ +export const DialogBody = forwardRef, DialogBodyProps>( + ({ className, children, height, ...props }, ref) => ( + + {children} + + + + + ), +); +DialogBody.displayName = 'DialogBody'; + +/** @public */ +export const DialogFooter = forwardRef< + React.ElementRef<'div'>, + React.ComponentPropsWithoutRef<'div'> +>(({ className, children, ...props }, ref) => ( +
+ {children} +
+)); +DialogFooter.displayName = 'DialogFooter'; + +/** @public */ +export const DialogClose = forwardRef< + React.ElementRef, + DialogCloseProps +>(({ className, variant = 'secondary', children, ...props }, ref) => ( + +)); +DialogClose.displayName = 'DialogClose'; + +/** @public */ +export const Dialog = forwardRef, DialogProps>( + ({ className, children, ...props }, ref) => ( + + {children} + + ), +); +Dialog.displayName = 'Dialog'; diff --git a/packages/ui/src/components/Dialog/index.ts b/packages/ui/src/components/Dialog/index.ts new file mode 100644 index 0000000000..8db1b29ff8 --- /dev/null +++ b/packages/ui/src/components/Dialog/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 * from './Dialog'; +export * from './types'; diff --git a/packages/ui/src/components/Dialog/types.ts b/packages/ui/src/components/Dialog/types.ts new file mode 100644 index 0000000000..b13f496d58 --- /dev/null +++ b/packages/ui/src/components/Dialog/types.ts @@ -0,0 +1,64 @@ +/* + * 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 { + DialogTriggerProps as RADialogTriggerProps, + ModalOverlayProps as RAModalProps, + HeadingProps as RAHeadingProps, +} from 'react-aria-components'; +import type { ButtonProps } from '../Button'; + +/** + * Props for the DialogTrigger component. + * @public + */ +export interface DialogTriggerProps extends RADialogTriggerProps {} + +/** + * Props for the DialogHeader component. + * @public + */ +export interface DialogHeaderProps extends RAHeadingProps { + children?: React.ReactNode; + className?: string; +} + +/** + * Props for the DialogBody component. + * @public + */ +export interface DialogBodyProps { + children?: React.ReactNode; + className?: string; + height?: number | string; +} + +/** + * Props for the DialogClose component. + * @public + */ +export interface DialogCloseProps extends Omit { + variant?: 'primary' | 'secondary' | 'tertiary'; +} + +/** + * Props for the Dialog component. + * @public + */ +export interface DialogProps extends RAModalProps { + className?: string; + children?: React.ReactNode; +} diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index f5d9230d4d..efad69605b 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -34,6 +34,7 @@ export * from './components/Avatar'; export * from './components/Button'; export * from './components/Card'; export * from './components/Collapsible'; +export * from './components/Dialog'; export * from './components/FieldLabel'; export * from './components/Header'; export * from './components/HeaderPage'; From 2591b423665489e6d2393e95da7e32b39217f47f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 9 Oct 2025 11:47:58 +0200 Subject: [PATCH 124/244] add changeset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .changeset/better-women-turn.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/better-women-turn.md diff --git a/.changeset/better-women-turn.md b/.changeset/better-women-turn.md new file mode 100644 index 0000000000..b2001a87c5 --- /dev/null +++ b/.changeset/better-women-turn.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Adding a Dialog component From 66eb76aea3a896629f11eb43317d92e889d9427d Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 9 Oct 2025 10:57:48 +0100 Subject: [PATCH 125/244] Update warm-dancers-call.md Signed-off-by: Charles de Dreuille --- .changeset/warm-dancers-call.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.changeset/warm-dancers-call.md b/.changeset/warm-dancers-call.md index aa69005663..404fa16a68 100644 --- a/.changeset/warm-dancers-call.md +++ b/.changeset/warm-dancers-call.md @@ -2,4 +2,10 @@ '@backstage/theme': minor --- -**BREAKING**: Removed noCssBaseline prop in UnifiedThemeProvider. If your Backstage instance looks broken after this update, there's a high chance that you forgot to add our new Backstage UI global CSS. To do that, please add @backstage/ui/css/styles.css at the root of your application. +**BREAKING**: Removed the built-in `CssBaseline` from `UnifiedThemeProvider`. If your Backstage instance looks broken after this update, you likely forgot to add our new Backstage UI global CSS. To do that, please import `@backstage/ui/css/styles.css` in `packages/app/src/index.tsx`: + +```tsx +import '@backstage/ui/css/styles.css'; +``` + +This change also removes the `noCssBaseline` prop, which became redundant. From ad739a5f2534cd05a9abbe1f7b79c114a030bfda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 9 Oct 2025 12:13:19 +0200 Subject: [PATCH 126/244] chore: prettier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- .../src/components/Dialog/Dialog.styles.css | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/ui/src/components/Dialog/Dialog.styles.css b/packages/ui/src/components/Dialog/Dialog.styles.css index 8e445a42a8..6186f5dc89 100644 --- a/packages/ui/src/components/Dialog/Dialog.styles.css +++ b/packages/ui/src/components/Dialog/Dialog.styles.css @@ -49,7 +49,7 @@ border-bottom: 1px solid var(--bui-border); } -.bui-Dialog [slot="title"] { +.bui-Dialog [slot='title'] { font-size: var(--bui-font-size-3); } @@ -68,20 +68,20 @@ /* Keyframe animations */ @keyframes fade-in { - from { - opacity: 0; + from { + opacity: 0; } - to { - opacity: 1; + to { + opacity: 1; } } @keyframes fade-out { - from { - opacity: 1; + from { + opacity: 1; } - to { - opacity: 0; + to { + opacity: 0; } } @@ -105,4 +105,4 @@ opacity: 0; transform: scale(0.95); } -} \ No newline at end of file +} From 02299cddc6570750a5c6270ab3aaf9081aec412f Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 8 Oct 2025 14:16:28 +0100 Subject: [PATCH 127/244] Add new layers to global CSS Signed-off-by: Charles de Dreuille --- packages/ui/css/styles.css | 2 +- packages/ui/src/css/components.css | 48 - packages/ui/src/css/styles.css | 83 +- packages/ui/src/css/tokens.css | 186 ++ packages/ui/src/css/utilities.css | 54 - packages/ui/src/css/utilities/display.css | 196 +- packages/ui/src/css/utilities/flex.css | 522 ++--- packages/ui/src/css/utilities/gap.css | 716 +++--- packages/ui/src/css/utilities/grid.css | 2324 ++++++++++---------- packages/ui/src/css/utilities/height.css | 158 +- packages/ui/src/css/utilities/m.css | 716 +++--- packages/ui/src/css/utilities/mb.css | 716 +++--- packages/ui/src/css/utilities/ml.css | 716 +++--- packages/ui/src/css/utilities/mr.css | 716 +++--- packages/ui/src/css/utilities/mt.css | 716 +++--- packages/ui/src/css/utilities/mx.css | 888 ++++---- packages/ui/src/css/utilities/my.css | 888 ++++---- packages/ui/src/css/utilities/p.css | 716 +++--- packages/ui/src/css/utilities/pb.css | 716 +++--- packages/ui/src/css/utilities/pl.css | 716 +++--- packages/ui/src/css/utilities/position.css | 234 +- packages/ui/src/css/utilities/pr.css | 716 +++--- packages/ui/src/css/utilities/pt.css | 716 +++--- packages/ui/src/css/utilities/px.css | 888 ++++---- packages/ui/src/css/utilities/py.css | 888 ++++---- packages/ui/src/css/utilities/sm.css | 2 +- packages/ui/src/css/utilities/width.css | 158 +- packages/ui/src/css/utilities/xs.css | 2 +- 28 files changed, 7970 insertions(+), 7427 deletions(-) delete mode 100644 packages/ui/src/css/components.css create mode 100644 packages/ui/src/css/tokens.css delete mode 100644 packages/ui/src/css/utilities.css diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index 61051fdf07..6ca70c9c43 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -11069,4 +11069,4 @@ body { transition: all .2s; display: block; } -} +} \ No newline at end of file diff --git a/packages/ui/src/css/components.css b/packages/ui/src/css/components.css deleted file mode 100644 index 9696425431..0000000000 --- a/packages/ui/src/css/components.css +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 '../components/Avatar/Avatar.styles.css'; -@import '../components/Box/styles.css'; -@import '../components/Button/styles.css'; -@import '../components/ButtonIcon/styles.css'; -@import '../components/Card/Card.styles.css'; -@import '../components/Checkbox/styles.css'; -@import '../components/Collapsible/Collapsible.styles.css'; -@import '../components/Container/styles.css'; -@import '../components/FieldError/FieldError.styles.css'; -@import '../components/FieldLabel/FieldLabel.styles.css'; -@import '../components/Flex/styles.css'; -@import '../components/Grid/styles.css'; -@import '../components/Header/Header.styles.css'; -@import '../components/HeaderPage/HeaderPage.styles.css'; -@import '../components/Icon/styles.css'; -@import '../components/Link/styles.css'; -@import '../components/Menu/Menu.styles.css'; -@import '../components/Popover/Popover.styles.css'; -@import '../components/RadioGroup/RadioGroup.styles.css'; -@import '../components/Table/Table.styles.css'; -@import '../components/TablePagination/TablePagination.styles.css'; -@import '../components/Tabs/Tabs.styles.css'; -@import '../components/TagGroup/TagGroup.styles.css'; -@import '../components/Text/styles.css'; -@import '../components/TextField/TextField.styles.css'; -@import '../components/PasswordField/PasswordField.styles.css'; -@import '../components/SearchField/SearchField.styles.css'; -@import '../components/Skeleton/Skeleton.styles.css'; -@import '../components/Tooltip/Tooltip.styles.css'; -@import '../components/ScrollArea/ScrollArea.styles.css'; -@import '../components/Select/Select.styles.css'; -@import '../components/Switch/Switch.styles.css'; diff --git a/packages/ui/src/css/styles.css b/packages/ui/src/css/styles.css index f5d623389f..4f5aa31744 100644 --- a/packages/ui/src/css/styles.css +++ b/packages/ui/src/css/styles.css @@ -14,5 +14,86 @@ * limitations under the License. */ +@layer tokens, base, components, utilities, legacy; + +/* Tokens */ +@import './tokens.css'; + +/* Base */ +@import './normalize.css'; @import './core.css'; -@import './components.css'; + +/* Components */ +@import '../components/Avatar/Avatar.styles.css'; +@import '../components/Box/styles.css'; +@import '../components/Button/styles.css'; +@import '../components/ButtonIcon/styles.css'; +@import '../components/Card/Card.styles.css'; +@import '../components/Checkbox/styles.css'; +@import '../components/Collapsible/Collapsible.styles.css'; +@import '../components/Container/styles.css'; +@import '../components/FieldError/FieldError.styles.css'; +@import '../components/FieldLabel/FieldLabel.styles.css'; +@import '../components/Flex/styles.css'; +@import '../components/Grid/styles.css'; +@import '../components/Header/Header.styles.css'; +@import '../components/HeaderPage/HeaderPage.styles.css'; +@import '../components/Icon/styles.css'; +@import '../components/Link/styles.css'; +@import '../components/Menu/Menu.styles.css'; +@import '../components/Popover/Popover.styles.css'; +@import '../components/RadioGroup/RadioGroup.styles.css'; +@import '../components/Table/Table.styles.css'; +@import '../components/TablePagination/TablePagination.styles.css'; +@import '../components/Tabs/Tabs.styles.css'; +@import '../components/TagGroup/TagGroup.styles.css'; +@import '../components/Text/styles.css'; +@import '../components/TextField/TextField.styles.css'; +@import '../components/PasswordField/PasswordField.styles.css'; +@import '../components/SearchField/SearchField.styles.css'; +@import '../components/Skeleton/Skeleton.styles.css'; +@import '../components/Tooltip/Tooltip.styles.css'; +@import '../components/ScrollArea/ScrollArea.styles.css'; +@import '../components/Select/Select.styles.css'; +@import '../components/Switch/Switch.styles.css'; + +/* Utilities */ + +/* Padding */ +@import './utilities/p.css'; +@import './utilities/pl.css'; +@import './utilities/pr.css'; +@import './utilities/pt.css'; +@import './utilities/pb.css'; +@import './utilities/py.css'; +@import './utilities/px.css'; + +/* Margin */ +@import './utilities/m.css'; +@import './utilities/ml.css'; +@import './utilities/mr.css'; +@import './utilities/mt.css'; +@import './utilities/mb.css'; +@import './utilities/my.css'; +@import './utilities/mx.css'; + +/* Display */ +@import './utilities/display.css'; + +/* Width */ +@import './utilities/width.css'; + +/* Height */ +@import './utilities/height.css'; + +/* Position */ +@import './utilities/position.css'; + +/* Grid */ +@import './utilities/grid.css'; + +/* Gap */ +@import './utilities/gap.css'; + +/* Flex */ +@import './utilities/flex.css'; diff --git a/packages/ui/src/css/tokens.css b/packages/ui/src/css/tokens.css new file mode 100644 index 0000000000..028c60311d --- /dev/null +++ b/packages/ui/src/css/tokens.css @@ -0,0 +1,186 @@ +/* + * 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. + */ + +@layer tokens { + /* Light theme tokens */ + :root { + /* Font families */ + --bui-font-regular: system-ui; + --bui-font-monospace: ui-monospace, 'Menlo', 'Monaco', 'Consolas', + 'Liberation Mono', 'Courier New', monospace; + + /* Font weights */ + --bui-font-weight-regular: 400; + --bui-font-weight-bold: 600; + + /* Font sizes */ + --bui-font-size-1: 0.625rem; /* 10px */ + --bui-font-size-2: 0.75rem; /* 12px */ + --bui-font-size-3: 0.875rem; /* 14px */ + --bui-font-size-4: 1rem; /* 16px */ + --bui-font-size-5: 1.25rem; /* 20px */ + --bui-font-size-6: 1.5rem; /* 24px */ + --bui-font-size-7: 2rem; /* 32px */ + --bui-font-size-8: 3rem; /* 48px */ + --bui-font-size-9: 4rem; /* 64px */ + --bui-font-size-10: 5.75rem; /* 92px */ + + /* Spacing */ + --bui-space: 0.25rem; /* This is the spacing multiplier */ + --bui-space-0_5: calc(var(--bui-space) * 0.5); /* 2px */ + --bui-space-1: var(--bui-space); /* 4px */ + --bui-space-1_5: calc(var(--bui-space) * 1.5); /* 6px */ + --bui-space-2: calc(var(--bui-space) * 2); /* 8px */ + --bui-space-3: calc(var(--bui-space) * 3); /* 12px */ + --bui-space-4: calc(var(--bui-space) * 4); /* 16px */ + --bui-space-5: calc(var(--bui-space) * 5); /* 20px */ + --bui-space-6: calc(var(--bui-space) * 6); /* 24px */ + --bui-space-7: calc(var(--bui-space) * 7); /* 28px */ + --bui-space-8: calc(var(--bui-space) * 8); /* 32px */ + --bui-space-9: calc(var(--bui-space) * 9); /* 36px */ + --bui-space-10: calc(var(--bui-space) * 10); /* 40px */ + --bui-space-11: calc(var(--bui-space) * 11); /* 44px */ + --bui-space-12: calc(var(--bui-space) * 12); /* 48px */ + --bui-space-13: calc(var(--bui-space) * 13); /* 52px */ + --bui-space-14: calc(var(--bui-space) * 14); /* 56px */ + + /* Radius */ + --bui-radius-1: calc(0.125rem); + --bui-radius-2: calc(0.25rem); + --bui-radius-3: calc(0.5rem); + --bui-radius-4: calc(0.75rem); + --bui-radius-5: calc(1rem); + --bui-radius-6: calc(1.25rem); + --bui-radius-full: 9999px; + + /* Base Colors */ + --bui-black: #000000; + --bui-white: #ffffff; + + /* Gray scale */ + --bui-gray-1: #f8f8f8; + --bui-gray-2: #ececec; + --bui-gray-3: #d9d9d9; + --bui-gray-4: #c1c1c1; + --bui-gray-5: #9e9e9e; + --bui-gray-6: #8c8c8c; + --bui-gray-7: #757575; + --bui-gray-8: #595959; + + /* Background Colors */ + --bui-bg: var(--bui-gray-1); + --bui-bg-surface-1: var(--bui-white); + --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-solid: #1f5493; + --bui-bg-solid-hover: #163a66; + --bui-bg-solid-pressed: #0f2b4e; + --bui-bg-solid-disabled: #ebebeb; + --bui-bg-tint: transparent; + --bui-bg-tint-hover: rgba(31, 84, 147, 0.4); + --bui-bg-tint-pressed: rgba(31, 84, 147, 0.6); + --bui-bg-tint-disabled: #ebebeb; + --bui-bg-danger: #feebe7; + --bui-bg-warning: #fff2b2; + --bui-bg-success: #e6f6eb; + + /* Foreground Colors */ + --bui-fg-primary: var(--bui-black); + --bui-fg-secondary: var(--bui-gray-7); + --bui-fg-link: #1f5493; + --bui-fg-link-hover: #1f2d5c; + --bui-fg-disabled: #9e9e9e; + --bui-fg-solid: var(--bui-white); + --bui-fg-solid-disabled: #9c9c9c; + --bui-fg-tint: #1f5493; + --bui-fg-tint-disabled: var(--bui-gray-5); + --bui-fg-danger: #e22b2b; + --bui-fg-warning: #e36d05; + --bui-fg-success: #1db954; + + /* Border Colors */ + --bui-border: rgba(0, 0, 0, 0.1); + --bui-border-hover: rgba(0, 0, 0, 0.2); + --bui-border-pressed: rgba(0, 0, 0, 0.4); + --bui-border-disabled: rgba(0, 0, 0, 0.1); + --bui-border-danger: #f87a7a; + --bui-border-warning: #e36d05; + --bui-border-success: #53db83; + + /* Special Colors */ + --bui-ring: #1f5493; + --bui-scrollbar: #a0a0a03b; + --bui-scrollbar-thumb: #a0a0a0; + + --bui-animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; + } + + /* Dark theme tokens */ + [data-theme-mode='dark'] { + /* Gray scale */ + --bui-gray-1: #191919; + --bui-gray-2: #242424; + --bui-gray-3: #373737; + --bui-gray-4: #464646; + --bui-gray-5: #575757; + --bui-gray-6: #7b7b7b; + --bui-gray-7: #9e9e9e; + --bui-gray-8: #b4b4b4; + + /* Background Colors */ + --bui-bg: #333333; + --bui-bg-surface-1: #424242; + --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-solid: #9cc9ff; + --bui-bg-solid-hover: #83b9fd; + --bui-bg-solid-pressed: #83b9fd; + --bui-bg-solid-disabled: #222222; + --bui-bg-tint: transparent; + --bui-bg-tint-hover: rgba(156, 201, 255, 0.12); + --bui-bg-tint-pressed: rgba(156, 201, 255, 0.16); + --bui-bg-tint-disabled: transparent; + --bui-bg-danger: #3b1219; + --bui-bg-warning: #302008; + --bui-bg-success: #132d21; + + /* Foreground Colors */ + --bui-fg-primary: var(--bui-white); + --bui-fg-secondary: var(--bui-gray-7); + --bui-fg-link: #9cc9ff; + --bui-fg-link-hover: #7eb5f7; + --bui-fg-disabled: var(--bui-gray-7); + --bui-fg-solid: #101821; + --bui-fg-solid-disabled: var(--bui-gray-5); + --bui-fg-tint: #9cc9ff; + --bui-fg-tint-disabled: var(--bui-gray-5); + --bui-fg-danger: #e22b2b; + --bui-fg-warning: #e36d05; + --bui-fg-success: #1db954; + + /* Border Colors */ + --bui-border: rgba(255, 255, 255, 0.12); + --bui-border-hover: rgba(255, 255, 255, 0.4); + --bui-border-pressed: rgba(255, 255, 255, 0.5); + --bui-border-disabled: rgba(255, 255, 255, 0.2); + --bui-border-danger: #f87a7a; + --bui-border-warning: #e36d05; + --bui-border-success: #53db83; + + /* Special Colors */ + --bui-ring: #1f5493; + --bui-scrollbar: #3636363a; + --bui-scrollbar-thumb: #575757; + } +} diff --git a/packages/ui/src/css/utilities.css b/packages/ui/src/css/utilities.css deleted file mode 100644 index 226e30722b..0000000000 --- a/packages/ui/src/css/utilities.css +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2024 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* Padding */ -@import './utilities/p.css'; -@import './utilities/pl.css'; -@import './utilities/pr.css'; -@import './utilities/pt.css'; -@import './utilities/pb.css'; -@import './utilities/py.css'; -@import './utilities/px.css'; - -/* Margin */ -@import './utilities/m.css'; -@import './utilities/ml.css'; -@import './utilities/mr.css'; -@import './utilities/mt.css'; -@import './utilities/mb.css'; -@import './utilities/my.css'; -@import './utilities/mx.css'; - -/* Display */ -@import './utilities/display.css'; - -/* Width */ -@import './utilities/width.css'; - -/* Height */ -@import './utilities/height.css'; - -/* Position */ -@import './utilities/position.css'; - -/* Grid */ -@import './utilities/grid.css'; - -/* Gap */ -@import './utilities/gap.css'; - -/* Flex */ -@import './utilities/flex.css'; diff --git a/packages/ui/src/css/utilities/display.css b/packages/ui/src/css/utilities/display.css index 179d80f860..437fb26993 100644 --- a/packages/ui/src/css/utilities/display.css +++ b/packages/ui/src/css/utilities/display.css @@ -1,110 +1,128 @@ -.bui-display-none { - display: none; -} +/* + * 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. + */ -.bui-display-inline { - display: inline; -} - -.bui-display-inline-block { - display: inline-block; -} - -.bui-display-block { - display: block; -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-display-none { +@layer utilities { + .bui-display-none { display: none; } - .xs\:bui-display-inline { + .bui-display-inline { display: inline; } - .xs\:bui-display-inline-block { + .bui-display-inline-block { display: inline-block; } - .xs\:bui-display-block { + .bui-display-block { display: block; } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-display-none { - display: none; + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-display-none { + display: none; + } + + .xs\:bui-display-inline { + display: inline; + } + + .xs\:bui-display-inline-block { + display: inline-block; + } + + .xs\:bui-display-block { + display: block; + } } - .sm\:bui-display-inline { - display: inline; + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-display-none { + display: none; + } + + .sm\:bui-display-inline { + display: inline; + } + + .sm\:bui-display-inline-block { + display: inline-block; + } + + .sm\:bui-display-block { + display: block; + } } - .sm\:bui-display-inline-block { - display: inline-block; + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-display-none { + display: none; + } + + .md\:bui-display-inline { + display: inline; + } + + .md\:bui-display-inline-block { + display: inline-block; + } + + .md\:bui-display-block { + display: block; + } } - .sm\:bui-display-block { - display: block; - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-display-none { - display: none; - } - - .md\:bui-display-inline { - display: inline; - } - - .md\:bui-display-inline-block { - display: inline-block; - } - - .md\:bui-display-block { - display: block; - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-display-none { - display: none; - } - - .lg\:bui-display-inline { - display: inline; - } - - .lg\:bui-display-inline-block { - display: inline-block; - } - - .lg\:bui-display-block { - display: block; - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-display-none { - display: none; - } - - .xl\:bui-display-inline { - display: inline; - } - - .xl\:bui-display-inline-block { - display: inline-block; - } - - .xl\:bui-display-block { - display: block; + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-display-none { + display: none; + } + + .lg\:bui-display-inline { + display: inline; + } + + .lg\:bui-display-inline-block { + display: inline-block; + } + + .lg\:bui-display-block { + display: block; + } + } + + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-display-none { + display: none; + } + + .xl\:bui-display-inline { + display: inline; + } + + .xl\:bui-display-inline-block { + display: inline-block; + } + + .xl\:bui-display-block { + display: block; + } } } diff --git a/packages/ui/src/css/utilities/flex.css b/packages/ui/src/css/utilities/flex.css index fa2b7b5ff2..2248addfee 100644 --- a/packages/ui/src/css/utilities/flex.css +++ b/packages/ui/src/css/utilities/flex.css @@ -1,306 +1,324 @@ -.bui-align-start { - align-items: start; -} +/* + * 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. + */ -.bui-align-center { - align-items: center; -} - -.bui-align-end { - align-items: end; -} - -.bui-align-baseline { - align-items: baseline; -} - -.bui-align-stretch { - align-items: stretch; -} - -.bui-jc-start { - justify-content: start; -} - -.bui-jc-center { - justify-content: center; -} - -.bui-jc-end { - justify-content: end; -} - -.bui-jc-between { - justify-content: space-between; -} - -.bui-fd-row { - flex-direction: row; -} - -.bui-fd-column { - flex-direction: column; -} - -.bui-fd-row-reverse { - flex-direction: row-reverse; -} - -.bui-fd-column-reverse { - flex-direction: column-reverse; -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-align-start { +@layer utilities { + .bui-align-start { align-items: start; } - .xs\:bui-align-center { + .bui-align-center { align-items: center; } - .xs\:bui-align-end { + .bui-align-end { align-items: end; } - .xs\:bui-align-stretch { + .bui-align-baseline { + align-items: baseline; + } + + .bui-align-stretch { align-items: stretch; } - .xs\:bui-jc-start { + .bui-jc-start { justify-content: start; } - .xs\:bui-jc-center { + .bui-jc-center { justify-content: center; } - .xs\:bui-jc-end { + .bui-jc-end { justify-content: end; } - .xs\:bui-jc-between { + .bui-jc-between { justify-content: space-between; } - .xs\:bui-fd-row { + .bui-fd-row { flex-direction: row; } - .xs\:bui-fd-column { + .bui-fd-column { flex-direction: column; } - .xs\:bui-fd-row-reverse { + .bui-fd-row-reverse { flex-direction: row-reverse; } - .xs\:bui-fd-column-reverse { + .bui-fd-column-reverse { flex-direction: column-reverse; } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-align-start { - align-items: start; + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-align-start { + align-items: start; + } + + .xs\:bui-align-center { + align-items: center; + } + + .xs\:bui-align-end { + align-items: end; + } + + .xs\:bui-align-stretch { + align-items: stretch; + } + + .xs\:bui-jc-start { + justify-content: start; + } + + .xs\:bui-jc-center { + justify-content: center; + } + + .xs\:bui-jc-end { + justify-content: end; + } + + .xs\:bui-jc-between { + justify-content: space-between; + } + + .xs\:bui-fd-row { + flex-direction: row; + } + + .xs\:bui-fd-column { + flex-direction: column; + } + + .xs\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .xs\:bui-fd-column-reverse { + flex-direction: column-reverse; + } } - .sm\:bui-align-center { - align-items: center; + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-align-start { + align-items: start; + } + + .sm\:bui-align-center { + align-items: center; + } + + .sm\:bui-align-end { + align-items: end; + } + + .sm\:bui-align-stretch { + align-items: stretch; + } + + .sm\:bui-jc-start { + justify-content: start; + } + + .sm\:bui-jc-center { + justify-content: center; + } + + .sm\:bui-jc-end { + justify-content: end; + } + + .sm\:bui-jc-between { + justify-content: space-between; + } + + .sm\:bui-fd-row { + flex-direction: row; + } + + .sm\:bui-fd-column { + flex-direction: column; + } + + .sm\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .sm\:bui-fd-column-reverse { + flex-direction: column-reverse; + } } - .sm\:bui-align-end { - align-items: end; + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-align-start { + align-items: start; + } + + .md\:bui-align-center { + align-items: center; + } + + .md\:bui-align-end { + align-items: end; + } + + .md\:bui-align-stretch { + align-items: stretch; + } + + .md\:bui-jc-start { + justify-content: start; + } + + .md\:bui-jc-center { + justify-content: center; + } + + .md\:bui-jc-end { + justify-content: end; + } + + .md\:bui-jc-between { + justify-content: space-between; + } + + .md\:bui-fd-row { + flex-direction: row; + } + + .md\:bui-fd-column { + flex-direction: column; + } + + .md\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .md\:bui-fd-column-reverse { + flex-direction: column-reverse; + } } - .sm\:bui-align-stretch { - align-items: stretch; + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-align-start { + align-items: start; + } + + .lg\:bui-align-center { + align-items: center; + } + + .lg\:bui-align-end { + align-items: end; + } + + .lg\:bui-align-stretch { + align-items: stretch; + } + + .lg\:bui-jc-start { + justify-content: start; + } + + .lg\:bui-jc-center { + justify-content: center; + } + + .lg\:bui-jc-end { + justify-content: end; + } + + .lg\:bui-jc-between { + justify-content: space-between; + } + + .lg\:bui-fd-row { + flex-direction: row; + } + + .lg\:bui-fd-column { + flex-direction: column; + } + + .lg\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .lg\:bui-fd-column-reverse { + flex-direction: column-reverse; + } } - .sm\:bui-jc-start { - justify-content: start; - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-align-start { + align-items: start; + } - .sm\:bui-jc-center { - justify-content: center; - } + .xl\:bui-align-center { + align-items: center; + } - .sm\:bui-jc-end { - justify-content: end; - } + .xl\:bui-align-end { + align-items: end; + } - .sm\:bui-jc-between { - justify-content: space-between; - } + .xl\:bui-align-stretch { + align-items: stretch; + } - .sm\:bui-fd-row { - flex-direction: row; - } + .xl\:bui-jc-start { + justify-content: start; + } - .sm\:bui-fd-column { - flex-direction: column; - } + .xl\:bui-jc-center { + justify-content: center; + } - .sm\:bui-fd-row-reverse { - flex-direction: row-reverse; - } + .xl\:bui-jc-end { + justify-content: end; + } - .sm\:bui-fd-column-reverse { - flex-direction: column-reverse; - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-align-start { - align-items: start; - } - - .md\:bui-align-center { - align-items: center; - } - - .md\:bui-align-end { - align-items: end; - } - - .md\:bui-align-stretch { - align-items: stretch; - } - - .md\:bui-jc-start { - justify-content: start; - } - - .md\:bui-jc-center { - justify-content: center; - } - - .md\:bui-jc-end { - justify-content: end; - } - - .md\:bui-jc-between { - justify-content: space-between; - } - - .md\:bui-fd-row { - flex-direction: row; - } - - .md\:bui-fd-column { - flex-direction: column; - } - - .md\:bui-fd-row-reverse { - flex-direction: row-reverse; - } - - .md\:bui-fd-column-reverse { - flex-direction: column-reverse; - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-align-start { - align-items: start; - } - - .lg\:bui-align-center { - align-items: center; - } - - .lg\:bui-align-end { - align-items: end; - } - - .lg\:bui-align-stretch { - align-items: stretch; - } - - .lg\:bui-jc-start { - justify-content: start; - } - - .lg\:bui-jc-center { - justify-content: center; - } - - .lg\:bui-jc-end { - justify-content: end; - } - - .lg\:bui-jc-between { - justify-content: space-between; - } - - .lg\:bui-fd-row { - flex-direction: row; - } - - .lg\:bui-fd-column { - flex-direction: column; - } - - .lg\:bui-fd-row-reverse { - flex-direction: row-reverse; - } - - .lg\:bui-fd-column-reverse { - flex-direction: column-reverse; - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-align-start { - align-items: start; - } - - .xl\:bui-align-center { - align-items: center; - } - - .xl\:bui-align-end { - align-items: end; - } - - .xl\:bui-align-stretch { - align-items: stretch; - } - - .xl\:bui-jc-start { - justify-content: start; - } - - .xl\:bui-jc-center { - justify-content: center; - } - - .xl\:bui-jc-end { - justify-content: end; - } - - .xl\:bui-jc-between { - justify-content: space-between; - } - - .xl\:bui-fd-row { - flex-direction: row; - } - - .xl\:bui-fd-column { - flex-direction: column; - } - - .xl\:bui-fd-row-reverse { - flex-direction: row-reverse; - } - - .xl\:bui-fd-column-reverse { - flex-direction: column-reverse; + .xl\:bui-jc-between { + justify-content: space-between; + } + + .xl\:bui-fd-row { + flex-direction: row; + } + + .xl\:bui-fd-column { + flex-direction: column; + } + + .xl\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .xl\:bui-fd-column-reverse { + flex-direction: column-reverse; + } } } diff --git a/packages/ui/src/css/utilities/gap.css b/packages/ui/src/css/utilities/gap.css index ec4168fa6b..f9ea4f97d9 100644 --- a/packages/ui/src/css/utilities/gap.css +++ b/packages/ui/src/css/utilities/gap.css @@ -1,422 +1,440 @@ -.bui-gap { - gap: var(--gap); -} +/* + * 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. + */ -.bui-gap-0\.5 { - gap: var(--bui-space-0_5); -} - -.bui-gap-1 { - gap: var(--bui-space-1); -} - -.bui-gap-1\.5 { - gap: var(--bui-space-1_5); -} - -.bui-gap-2 { - gap: var(--bui-space-2); -} - -.bui-gap-3 { - gap: var(--bui-space-3); -} - -.bui-gap-4 { - gap: var(--bui-space-4); -} - -.bui-gap-5 { - gap: var(--bui-space-5); -} - -.bui-gap-6 { - gap: var(--bui-space-6); -} - -.bui-gap-7 { - gap: var(--bui-space-7); -} - -.bui-gap-8 { - gap: var(--bui-space-8); -} - -.bui-gap-9 { - gap: var(--bui-space-9); -} - -.bui-gap-10 { - gap: var(--bui-space-10); -} - -.bui-gap-11 { - gap: var(--bui-space-11); -} - -.bui-gap-12 { - gap: var(--bui-space-12); -} - -.bui-gap-13 { - gap: var(--bui-space-13); -} - -.bui-gap-14 { - gap: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-gap { - gap: var(--gap-xs); +@layer utilities { + .bui-gap { + gap: var(--gap); } - .xs\:bui-gap-0\.5 { + .bui-gap-0\.5 { gap: var(--bui-space-0_5); } - .xs\:bui-gap-1 { + .bui-gap-1 { gap: var(--bui-space-1); } - .xs\:bui-gap-1\.5 { + .bui-gap-1\.5 { gap: var(--bui-space-1_5); } - .xs\:bui-gap-2 { + .bui-gap-2 { gap: var(--bui-space-2); } - .xs\:bui-gap-3 { + .bui-gap-3 { gap: var(--bui-space-3); } - .xs\:bui-gap-4 { + .bui-gap-4 { gap: var(--bui-space-4); } - .xs\:bui-gap-5 { + .bui-gap-5 { gap: var(--bui-space-5); } - .xs\:bui-gap-6 { + .bui-gap-6 { gap: var(--bui-space-6); } - .xs\:bui-gap-7 { + .bui-gap-7 { gap: var(--bui-space-7); } - .xs\:bui-gap-8 { + .bui-gap-8 { gap: var(--bui-space-8); } - .xs\:bui-gap-9 { + .bui-gap-9 { gap: var(--bui-space-9); } - .xs\:bui-gap-10 { + .bui-gap-10 { gap: var(--bui-space-10); } - .xs\:bui-gap-11 { + .bui-gap-11 { gap: var(--bui-space-11); } - .xs\:bui-gap-12 { + .bui-gap-12 { gap: var(--bui-space-12); } - .xs\:bui-gap-13 { + .bui-gap-13 { gap: var(--bui-space-13); } - .xs\:bui-gap-14 { + .bui-gap-14 { gap: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-gap { - gap: var(--gap-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-gap { + gap: var(--gap-xs); + } + + .xs\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .xs\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .xs\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .xs\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .xs\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .xs\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .xs\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .xs\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .xs\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .xs\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .xs\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .xs\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .xs\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .xs\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .xs\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .xs\:bui-gap-14 { + gap: var(--bui-space-14); + } } - .sm\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-gap { + gap: var(--gap-sm); + } + + .sm\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .sm\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .sm\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .sm\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .sm\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .sm\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .sm\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .sm\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .sm\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .sm\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .sm\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .sm\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .sm\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .sm\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .sm\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .sm\:bui-gap-14 { + gap: var(--bui-space-14); + } } - .sm\:bui-gap-1 { - gap: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-gap { + gap: var(--gap-md); + } + + .md\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .md\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .md\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .md\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .md\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .md\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .md\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .md\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .md\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .md\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .md\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .md\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .md\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .md\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .md\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .md\:bui-gap-14 { + gap: var(--bui-space-14); + } } - .sm\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-gap { + gap: var(--gap-lg); + } + + .lg\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .lg\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .lg\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .lg\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .lg\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .lg\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .lg\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .lg\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .lg\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .lg\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .lg\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .lg\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .lg\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .lg\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .lg\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .lg\:bui-gap-14 { + gap: var(--bui-space-14); + } } - .sm\:bui-gap-2 { - gap: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-gap { + gap: var(--gap-xl); + } - .sm\:bui-gap-3 { - gap: var(--bui-space-3); - } + .xl\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } - .sm\:bui-gap-4 { - gap: var(--bui-space-4); - } + .xl\:bui-gap-1 { + gap: var(--bui-space-1); + } - .sm\:bui-gap-5 { - gap: var(--bui-space-5); - } + .xl\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } - .sm\:bui-gap-6 { - gap: var(--bui-space-6); - } + .xl\:bui-gap-2 { + gap: var(--bui-space-2); + } - .sm\:bui-gap-7 { - gap: var(--bui-space-7); - } + .xl\:bui-gap-3 { + gap: var(--bui-space-3); + } - .sm\:bui-gap-8 { - gap: var(--bui-space-8); - } + .xl\:bui-gap-4 { + gap: var(--bui-space-4); + } - .sm\:bui-gap-9 { - gap: var(--bui-space-9); - } + .xl\:bui-gap-5 { + gap: var(--bui-space-5); + } - .sm\:bui-gap-10 { - gap: var(--bui-space-10); - } + .xl\:bui-gap-6 { + gap: var(--bui-space-6); + } - .sm\:bui-gap-11 { - gap: var(--bui-space-11); - } + .xl\:bui-gap-7 { + gap: var(--bui-space-7); + } - .sm\:bui-gap-12 { - gap: var(--bui-space-12); - } + .xl\:bui-gap-8 { + gap: var(--bui-space-8); + } - .sm\:bui-gap-13 { - gap: var(--bui-space-13); - } + .xl\:bui-gap-9 { + gap: var(--bui-space-9); + } - .sm\:bui-gap-14 { - gap: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-gap { - gap: var(--gap-md); - } - - .md\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); - } - - .md\:bui-gap-1 { - gap: var(--bui-space-1); - } - - .md\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); - } - - .md\:bui-gap-2 { - gap: var(--bui-space-2); - } - - .md\:bui-gap-3 { - gap: var(--bui-space-3); - } - - .md\:bui-gap-4 { - gap: var(--bui-space-4); - } - - .md\:bui-gap-5 { - gap: var(--bui-space-5); - } - - .md\:bui-gap-6 { - gap: var(--bui-space-6); - } - - .md\:bui-gap-7 { - gap: var(--bui-space-7); - } - - .md\:bui-gap-8 { - gap: var(--bui-space-8); - } - - .md\:bui-gap-9 { - gap: var(--bui-space-9); - } - - .md\:bui-gap-10 { - gap: var(--bui-space-10); - } - - .md\:bui-gap-11 { - gap: var(--bui-space-11); - } - - .md\:bui-gap-12 { - gap: var(--bui-space-12); - } - - .md\:bui-gap-13 { - gap: var(--bui-space-13); - } - - .md\:bui-gap-14 { - gap: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-gap { - gap: var(--gap-lg); - } - - .lg\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); - } - - .lg\:bui-gap-1 { - gap: var(--bui-space-1); - } - - .lg\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); - } - - .lg\:bui-gap-2 { - gap: var(--bui-space-2); - } - - .lg\:bui-gap-3 { - gap: var(--bui-space-3); - } - - .lg\:bui-gap-4 { - gap: var(--bui-space-4); - } - - .lg\:bui-gap-5 { - gap: var(--bui-space-5); - } - - .lg\:bui-gap-6 { - gap: var(--bui-space-6); - } - - .lg\:bui-gap-7 { - gap: var(--bui-space-7); - } - - .lg\:bui-gap-8 { - gap: var(--bui-space-8); - } - - .lg\:bui-gap-9 { - gap: var(--bui-space-9); - } - - .lg\:bui-gap-10 { - gap: var(--bui-space-10); - } - - .lg\:bui-gap-11 { - gap: var(--bui-space-11); - } - - .lg\:bui-gap-12 { - gap: var(--bui-space-12); - } - - .lg\:bui-gap-13 { - gap: var(--bui-space-13); - } - - .lg\:bui-gap-14 { - gap: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-gap { - gap: var(--gap-xl); - } - - .xl\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); - } - - .xl\:bui-gap-1 { - gap: var(--bui-space-1); - } - - .xl\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); - } - - .xl\:bui-gap-2 { - gap: var(--bui-space-2); - } - - .xl\:bui-gap-3 { - gap: var(--bui-space-3); - } - - .xl\:bui-gap-4 { - gap: var(--bui-space-4); - } - - .xl\:bui-gap-5 { - gap: var(--bui-space-5); - } - - .xl\:bui-gap-6 { - gap: var(--bui-space-6); - } - - .xl\:bui-gap-7 { - gap: var(--bui-space-7); - } - - .xl\:bui-gap-8 { - gap: var(--bui-space-8); - } - - .xl\:bui-gap-9 { - gap: var(--bui-space-9); - } - - .xl\:bui-gap-10 { - gap: var(--bui-space-10); - } - - .xl\:bui-gap-11 { - gap: var(--bui-space-11); - } - - .xl\:bui-gap-12 { - gap: var(--bui-space-12); - } - - .xl\:bui-gap-13 { - gap: var(--bui-space-13); - } - - .xl\:bui-gap-14 { - gap: var(--bui-space-14); + .xl\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .xl\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .xl\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .xl\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .xl\:bui-gap-14 { + gap: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/grid.css b/packages/ui/src/css/utilities/grid.css index 11de40bd7f..989a7fd88a 100644 --- a/packages/ui/src/css/utilities/grid.css +++ b/packages/ui/src/css/utilities/grid.css @@ -1,1292 +1,1310 @@ -.bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); -} - -.bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); -} - -.bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); -} - -.bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); -} - -.bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); -} - -.bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); -} - -.bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); -} - -.bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); -} - -.bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); -} - -.bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); -} - -.bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); -} - -.bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); -} - -.bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); -} - -.bui-col-span-1 { - grid-column: span 1 / span 1; -} - -.bui-col-span-2 { - grid-column: span 2 / span 2; -} - -.bui-col-span-3 { - grid-column: span 3 / span 3; -} - -.bui-col-span-4 { - grid-column: span 4 / span 4; -} - -.bui-col-span-5 { - grid-column: span 5 / span 5; -} - -.bui-col-span-6 { - grid-column: span 6 / span 6; -} - -.bui-col-span-7 { - grid-column: span 7 / span 7; -} - -.bui-col-span-8 { - grid-column: span 8 / span 8; -} - -.bui-col-span-9 { - grid-column: span 9 / span 9; -} - -.bui-col-span-10 { - grid-column: span 10 / span 10; -} - -.bui-col-span-11 { - grid-column: span 11 / span 11; -} - -.bui-col-span-12 { - grid-column: span 12 / span 12; -} - -.bui-col-span-auto { - grid-column: span auto / span auto; -} - -.bui-col-start-1 { - grid-column-start: 1; -} - -.bui-col-start-2 { - grid-column-start: 2; -} - -.bui-col-start-3 { - grid-column-start: 3; -} - -.bui-col-start-4 { - grid-column-start: 4; -} - -.bui-col-start-5 { - grid-column-start: 5; -} - -.bui-col-start-6 { - grid-column-start: 6; -} - -.bui-col-start-7 { - grid-column-start: 7; -} - -.bui-col-start-8 { - grid-column-start: 8; -} - -.bui-col-start-9 { - grid-column-start: 9; -} - -.bui-col-start-10 { - grid-column-start: 10; -} - -.bui-col-start-11 { - grid-column-start: 11; -} - -.bui-col-start-12 { - grid-column-start: 12; -} - -.bui-col-start-13 { - grid-column-start: 13; -} - -.bui-col-start-auto { - grid-column-start: auto; -} - -.bui-col-end-1 { - grid-column-end: 1; -} - -.bui-col-end-2 { - grid-column-end: 2; -} - -.bui-col-end-3 { - grid-column-end: 3; -} - -.bui-col-end-4 { - grid-column-end: 4; -} - -.bui-col-end-5 { - grid-column-end: 5; -} - -.bui-col-end-6 { - grid-column-end: 6; -} - -.bui-col-end-7 { - grid-column-end: 7; -} - -.bui-col-end-8 { - grid-column-end: 8; -} - -.bui-col-end-9 { - grid-column-end: 9; -} - -.bui-col-end-10 { - grid-column-end: 10; -} - -.bui-col-end-11 { - grid-column-end: 11; -} - -.bui-col-end-12 { - grid-column-end: 12; -} - -.bui-col-end-13 { - grid-column-end: 13; -} - -.bui-col-end-auto { - grid-column-end: auto; -} - -.bui-row-span-1 { - grid-row: span 1 / span 1; -} - -.bui-row-span-2 { - grid-row: span 2 / span 2; -} - -.bui-row-span-3 { - grid-row: span 3 / span 3; -} - -.bui-row-span-4 { - grid-row: span 4 / span 4; -} - -.bui-row-span-5 { - grid-row: span 5 / span 5; -} - -.bui-row-span-6 { - grid-row: span 6 / span 6; -} - -.bui-row-span-7 { - grid-row: span 7 / span 7; -} - -.bui-row-span-8 { - grid-row: span 8 / span 8; -} - -.bui-row-span-9 { - grid-row: span 9 / span 9; -} - -.bui-row-span-10 { - grid-row: span 10 / span 10; -} - -.bui-row-span-11 { - grid-row: span 11 / span 11; -} - -.bui-row-span-12 { - grid-row: span 12 / span 12; -} - -.bui-row-span-auto { - grid-row: span auto / span auto; -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-columns-1 { +/* + * 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. + */ + +@layer utilities { + .bui-columns-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); } - .xs\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - .xs\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - .xs\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - .xs\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - .xs\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - .xs\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - .xs\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - .xs\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - .xs\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - .xs\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - .xs\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - .xs\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - .xs\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - .xs\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - .xs\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - .xs\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - .xs\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - .xs\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - .xs\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - .xs\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - .xs\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - .xs\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - .xs\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - .xs\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - .xs\:bui-col-span-auto { - grid-column: span auto / span auto; - } - .xs\:bui-col-start-1 { - grid-column-start: 1; - } - .xs\:bui-col-start-2 { - grid-column-start: 2; - } - .xs\:bui-col-start-3 { - grid-column-start: 3; - } - .xs\:bui-col-start-4 { - grid-column-start: 4; - } - .xs\:bui-col-start-5 { - grid-column-start: 5; - } - .xs\:bui-col-start-6 { - grid-column-start: 6; - } - .xs\:bui-col-start-7 { - grid-column-start: 7; - } - .xs\:bui-col-start-8 { - grid-column-start: 8; - } - .xs\:bui-col-start-9 { - grid-column-start: 9; - } - .xs\:bui-col-start-10 { - grid-column-start: 10; - } - .xs\:bui-col-start-11 { - grid-column-start: 11; - } - .xs\:bui-col-start-12 { - grid-column-start: 12; - } - .xs\:bui-col-start-13 { - grid-column-start: 13; - } - .xs\:bui-col-start-auto { - grid-column-start: auto; - } - .xs\:bui-col-end-1 { - grid-column-end: 1; - } - .xs\:bui-col-end-2 { - grid-column-end: 2; - } - .xs\:bui-col-end-3 { - grid-column-end: 3; - } - .xs\:bui-col-end-4 { - grid-column-end: 4; - } - .xs\:bui-col-end-5 { - grid-column-end: 5; - } - .xs\:bui-col-end-6 { - grid-column-end: 6; - } - .xs\:bui-col-end-7 { - grid-column-end: 7; - } - .xs\:bui-col-end-8 { - grid-column-end: 8; - } - .xs\:bui-col-end-9 { - grid-column-end: 9; - } - .xs\:bui-col-end-10 { - grid-column-end: 10; - } - .xs\:bui-col-end-11 { - grid-column-end: 11; - } - .xs\:bui-col-end-12 { - grid-column-end: 12; - } - .xs\:bui-col-end-13 { - grid-column-end: 13; - } - .xs\:bui-col-end-auto { - grid-column-end: auto; - } - .xs\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - .xs\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - .xs\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - .xs\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - .xs\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - .xs\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - .xs\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - .xs\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - .xs\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - .xs\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - .xs\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - .xs\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - .xs\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - .sm\:bui-columns-2 { + .bui-columns-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } - .sm\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - .sm\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - .sm\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - .sm\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - .sm\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - .sm\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - .sm\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - .sm\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - .sm\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - .sm\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - .sm\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - .sm\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - .sm\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - .sm\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - .sm\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - .sm\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - .sm\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - .sm\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - .sm\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - .sm\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - .sm\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - .sm\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - .sm\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - .sm\:bui-col-span-auto { - grid-column: span auto / span auto; - } - .sm\:bui-col-start-1 { - grid-column-start: 1; - } - .sm\:bui-col-start-2 { - grid-column-start: 2; - } - .sm\:bui-col-start-3 { - grid-column-start: 3; - } - .sm\:bui-col-start-4 { - grid-column-start: 4; - } - .sm\:bui-col-start-5 { - grid-column-start: 5; - } - .sm\:bui-col-start-6 { - grid-column-start: 6; - } - .sm\:bui-col-start-7 { - grid-column-start: 7; - } - .sm\:bui-col-start-8 { - grid-column-start: 8; - } - .sm\:bui-col-start-9 { - grid-column-start: 9; - } - .sm\:bui-col-start-10 { - grid-column-start: 10; - } - .sm\:bui-col-start-11 { - grid-column-start: 11; - } - .sm\:bui-col-start-12 { - grid-column-start: 12; - } - .sm\:bui-col-start-13 { - grid-column-start: 13; - } - .sm\:bui-col-start-auto { - grid-column-start: auto; - } - .sm\:bui-col-end-1 { - grid-column-end: 1; - } - .sm\:bui-col-end-2 { - grid-column-end: 2; - } - .sm\:bui-col-end-3 { - grid-column-end: 3; - } - .sm\:bui-col-end-4 { - grid-column-end: 4; - } - .sm\:bui-col-end-5 { - grid-column-end: 5; - } - .sm\:bui-col-end-6 { - grid-column-end: 6; - } - .sm\:bui-col-end-7 { - grid-column-end: 7; - } - .sm\:bui-col-end-8 { - grid-column-end: 8; - } - .sm\:bui-col-end-9 { - grid-column-end: 9; - } - .sm\:bui-col-end-10 { - grid-column-end: 10; - } - .sm\:bui-col-end-11 { - grid-column-end: 11; - } - .sm\:bui-col-end-12 { - grid-column-end: 12; - } - .sm\:bui-col-end-13 { - grid-column-end: 13; - } - .sm\:bui-col-end-auto { - grid-column-end: auto; - } - .sm\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - .sm\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - .sm\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - .sm\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - .sm\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - .sm\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - .sm\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - .sm\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - .sm\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - .sm\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - .sm\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - .sm\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - .sm\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - .md\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - .md\:bui-columns-3 { + .bui-columns-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } - .md\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - .md\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - .md\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - .md\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - .md\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - .md\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - .md\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - .md\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - .md\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - .md\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - .md\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - .md\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - .md\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - .md\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - .md\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - .md\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - .md\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - .md\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - .md\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - .md\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - .md\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - .md\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - .md\:bui-col-span-auto { - grid-column: span auto / span auto; - } - .md\:bui-col-start-1 { - grid-column-start: 1; - } - .md\:bui-col-start-2 { - grid-column-start: 2; - } - .md\:bui-col-start-3 { - grid-column-start: 3; - } - .md\:bui-col-start-4 { - grid-column-start: 4; - } - .md\:bui-col-start-5 { - grid-column-start: 5; - } - .md\:bui-col-start-6 { - grid-column-start: 6; - } - .md\:bui-col-start-7 { - grid-column-start: 7; - } - .md\:bui-col-start-8 { - grid-column-start: 8; - } - .md\:bui-col-start-9 { - grid-column-start: 9; - } - .md\:bui-col-start-10 { - grid-column-start: 10; - } - .md\:bui-col-start-11 { - grid-column-start: 11; - } - .md\:bui-col-start-12 { - grid-column-start: 12; - } - .md\:bui-col-start-13 { - grid-column-start: 13; - } - .md\:bui-col-start-auto { - grid-column-start: auto; - } - .md\:bui-col-end-1 { - grid-column-end: 1; - } - .md\:bui-col-end-2 { - grid-column-end: 2; - } - .md\:bui-col-end-3 { - grid-column-end: 3; - } - .md\:bui-col-end-4 { - grid-column-end: 4; - } - .md\:bui-col-end-5 { - grid-column-end: 5; - } - .md\:bui-col-end-6 { - grid-column-end: 6; - } - .md\:bui-col-end-7 { - grid-column-end: 7; - } - .md\:bui-col-end-8 { - grid-column-end: 8; - } - .md\:bui-col-end-9 { - grid-column-end: 9; - } - .md\:bui-col-end-10 { - grid-column-end: 10; - } - .md\:bui-col-end-11 { - grid-column-end: 11; - } - .md\:bui-col-end-12 { - grid-column-end: 12; - } - .md\:bui-col-end-13 { - grid-column-end: 13; - } - .md\:bui-col-end-auto { - grid-column-end: auto; - } - .md\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - .md\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - .md\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - .md\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - .md\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - .md\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - .md\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - .md\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - .md\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - .md\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - .md\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - .md\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - .md\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - .lg\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - .lg\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - .lg\:bui-columns-4 { + .bui-columns-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } - .lg\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - .lg\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - .lg\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - .lg\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - .lg\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - .lg\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - .lg\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - .lg\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - .lg\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - .lg\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - .lg\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - .lg\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - .lg\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - .lg\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - .lg\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - .lg\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - .lg\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - .lg\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - .lg\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - .lg\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - .lg\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - .lg\:bui-col-span-auto { - grid-column: span auto / span auto; - } - .lg\:bui-col-start-1 { - grid-column-start: 1; - } - .lg\:bui-col-start-2 { - grid-column-start: 2; - } - .lg\:bui-col-start-3 { - grid-column-start: 3; - } - .lg\:bui-col-start-4 { - grid-column-start: 4; - } - .lg\:bui-col-start-5 { - grid-column-start: 5; - } - .lg\:bui-col-start-6 { - grid-column-start: 6; - } - .lg\:bui-col-start-7 { - grid-column-start: 7; - } - .lg\:bui-col-start-8 { - grid-column-start: 8; - } - .lg\:bui-col-start-9 { - grid-column-start: 9; - } - .lg\:bui-col-start-10 { - grid-column-start: 10; - } - .lg\:bui-col-start-11 { - grid-column-start: 11; - } - .lg\:bui-col-start-12 { - grid-column-start: 12; - } - .lg\:bui-col-start-13 { - grid-column-start: 13; - } - .lg\:bui-col-start-auto { - grid-column-start: auto; - } - .lg\:bui-col-end-1 { - grid-column-end: 1; - } - .lg\:bui-col-end-2 { - grid-column-end: 2; - } - .lg\:bui-col-end-3 { - grid-column-end: 3; - } - .lg\:bui-col-end-4 { - grid-column-end: 4; - } - .lg\:bui-col-end-5 { - grid-column-end: 5; - } - .lg\:bui-col-end-6 { - grid-column-end: 6; - } - .lg\:bui-col-end-7 { - grid-column-end: 7; - } - .lg\:bui-col-end-8 { - grid-column-end: 8; - } - .lg\:bui-col-end-9 { - grid-column-end: 9; - } - .lg\:bui-col-end-10 { - grid-column-end: 10; - } - .lg\:bui-col-end-11 { - grid-column-end: 11; - } - .lg\:bui-col-end-12 { - grid-column-end: 12; - } - .lg\:bui-col-end-13 { - grid-column-end: 13; - } - .lg\:bui-col-end-auto { - grid-column-end: auto; - } - .lg\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - .lg\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - .lg\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - .lg\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - .lg\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - .lg\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - .lg\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - .lg\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - .lg\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - .lg\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - .lg\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - .lg\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - .lg\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - .xl\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - .xl\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - .xl\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - .xl\:bui-columns-5 { + .bui-columns-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); } - .xl\:bui-columns-6 { + + .bui-columns-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); } - .xl\:bui-columns-7 { + + .bui-columns-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); } - .xl\:bui-columns-8 { + + .bui-columns-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); } - .xl\:bui-columns-9 { + + .bui-columns-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); } - .xl\:bui-columns-10 { + + .bui-columns-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); } - .xl\:bui-columns-11 { + + .bui-columns-11 { grid-template-columns: repeat(11, minmax(0, 1fr)); } - .xl\:bui-columns-12 { + + .bui-columns-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); } - .xl\:bui-columns-auto { + + .bui-columns-auto { grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); } - .xl\:bui-col-span-1 { + + .bui-col-span-1 { grid-column: span 1 / span 1; } - .xl\:bui-col-span-2 { + + .bui-col-span-2 { grid-column: span 2 / span 2; } - .xl\:bui-col-span-3 { + + .bui-col-span-3 { grid-column: span 3 / span 3; } - .xl\:bui-col-span-4 { + + .bui-col-span-4 { grid-column: span 4 / span 4; } - .xl\:bui-col-span-5 { + + .bui-col-span-5 { grid-column: span 5 / span 5; } - .xl\:bui-col-span-6 { + + .bui-col-span-6 { grid-column: span 6 / span 6; } - .xl\:bui-col-span-7 { + + .bui-col-span-7 { grid-column: span 7 / span 7; } - .xl\:bui-col-span-8 { + + .bui-col-span-8 { grid-column: span 8 / span 8; } - .xl\:bui-col-span-9 { + + .bui-col-span-9 { grid-column: span 9 / span 9; } - .xl\:bui-col-span-10 { + + .bui-col-span-10 { grid-column: span 10 / span 10; } - .xl\:bui-col-span-11 { + + .bui-col-span-11 { grid-column: span 11 / span 11; } - .xl\:bui-col-span-12 { + + .bui-col-span-12 { grid-column: span 12 / span 12; } - .xl\:bui-col-span-auto { + + .bui-col-span-auto { grid-column: span auto / span auto; } - .xl\:bui-col-start-1 { + + .bui-col-start-1 { grid-column-start: 1; } - .xl\:bui-col-start-2 { + + .bui-col-start-2 { grid-column-start: 2; } - .xl\:bui-col-start-3 { + + .bui-col-start-3 { grid-column-start: 3; } - .xl\:bui-col-start-4 { + + .bui-col-start-4 { grid-column-start: 4; } - .xl\:bui-col-start-5 { + + .bui-col-start-5 { grid-column-start: 5; } - .xl\:bui-col-start-6 { + + .bui-col-start-6 { grid-column-start: 6; } - .xl\:bui-col-start-7 { + + .bui-col-start-7 { grid-column-start: 7; } - .xl\:bui-col-start-8 { + + .bui-col-start-8 { grid-column-start: 8; } - .xl\:bui-col-start-9 { + + .bui-col-start-9 { grid-column-start: 9; } - .xl\:bui-col-start-10 { + + .bui-col-start-10 { grid-column-start: 10; } - .xl\:bui-col-start-11 { + + .bui-col-start-11 { grid-column-start: 11; } - .xl\:bui-col-start-12 { + + .bui-col-start-12 { grid-column-start: 12; } - .xl\:bui-col-start-13 { + + .bui-col-start-13 { grid-column-start: 13; } - .xl\:bui-col-start-auto { + + .bui-col-start-auto { grid-column-start: auto; } - .xl\:bui-col-end-1 { + + .bui-col-end-1 { grid-column-end: 1; } - .xl\:bui-col-end-2 { + + .bui-col-end-2 { grid-column-end: 2; } - .xl\:bui-col-end-3 { + + .bui-col-end-3 { grid-column-end: 3; } - .xl\:bui-col-end-4 { + + .bui-col-end-4 { grid-column-end: 4; } - .xl\:bui-col-end-5 { + + .bui-col-end-5 { grid-column-end: 5; } - .xl\:bui-col-end-6 { + + .bui-col-end-6 { grid-column-end: 6; } - .xl\:bui-col-end-7 { + + .bui-col-end-7 { grid-column-end: 7; } - .xl\:bui-col-end-8 { + + .bui-col-end-8 { grid-column-end: 8; } - .xl\:bui-col-end-9 { + + .bui-col-end-9 { grid-column-end: 9; } - .xl\:bui-col-end-10 { + + .bui-col-end-10 { grid-column-end: 10; } - .xl\:bui-col-end-11 { + + .bui-col-end-11 { grid-column-end: 11; } - .xl\:bui-col-end-12 { + + .bui-col-end-12 { grid-column-end: 12; } - .xl\:bui-col-end-13 { + + .bui-col-end-13 { grid-column-end: 13; } - .xl\:bui-col-end-auto { + + .bui-col-end-auto { grid-column-end: auto; } - .xl\:bui-row-span-1 { + + .bui-row-span-1 { grid-row: span 1 / span 1; } - .xl\:bui-row-span-2 { + + .bui-row-span-2 { grid-row: span 2 / span 2; } - .xl\:bui-row-span-3 { + + .bui-row-span-3 { grid-row: span 3 / span 3; } - .xl\:bui-row-span-4 { + + .bui-row-span-4 { grid-row: span 4 / span 4; } - .xl\:bui-row-span-5 { + + .bui-row-span-5 { grid-row: span 5 / span 5; } - .xl\:bui-row-span-6 { + + .bui-row-span-6 { grid-row: span 6 / span 6; } - .xl\:bui-row-span-7 { + + .bui-row-span-7 { grid-row: span 7 / span 7; } - .xl\:bui-row-span-8 { + + .bui-row-span-8 { grid-row: span 8 / span 8; } - .xl\:bui-row-span-9 { + + .bui-row-span-9 { grid-row: span 9 / span 9; } - .xl\:bui-row-span-10 { + + .bui-row-span-10 { grid-row: span 10 / span 10; } - .xl\:bui-row-span-11 { + + .bui-row-span-11 { grid-row: span 11 / span 11; } - .xl\:bui-row-span-12 { + + .bui-row-span-12 { grid-row: span 12 / span 12; } - .xl\:bui-row-span-auto { + + .bui-row-span-auto { grid-row: span auto / span auto; } + + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .xs\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .xs\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .xs\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .xs\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + .xs\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + .xs\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + .xs\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + .xs\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + .xs\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + .xs\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + .xs\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + .xs\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + .xs\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + .xs\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + .xs\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + .xs\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + .xs\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + .xs\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + .xs\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + .xs\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + .xs\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + .xs\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + .xs\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + .xs\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + .xs\:bui-col-span-auto { + grid-column: span auto / span auto; + } + .xs\:bui-col-start-1 { + grid-column-start: 1; + } + .xs\:bui-col-start-2 { + grid-column-start: 2; + } + .xs\:bui-col-start-3 { + grid-column-start: 3; + } + .xs\:bui-col-start-4 { + grid-column-start: 4; + } + .xs\:bui-col-start-5 { + grid-column-start: 5; + } + .xs\:bui-col-start-6 { + grid-column-start: 6; + } + .xs\:bui-col-start-7 { + grid-column-start: 7; + } + .xs\:bui-col-start-8 { + grid-column-start: 8; + } + .xs\:bui-col-start-9 { + grid-column-start: 9; + } + .xs\:bui-col-start-10 { + grid-column-start: 10; + } + .xs\:bui-col-start-11 { + grid-column-start: 11; + } + .xs\:bui-col-start-12 { + grid-column-start: 12; + } + .xs\:bui-col-start-13 { + grid-column-start: 13; + } + .xs\:bui-col-start-auto { + grid-column-start: auto; + } + .xs\:bui-col-end-1 { + grid-column-end: 1; + } + .xs\:bui-col-end-2 { + grid-column-end: 2; + } + .xs\:bui-col-end-3 { + grid-column-end: 3; + } + .xs\:bui-col-end-4 { + grid-column-end: 4; + } + .xs\:bui-col-end-5 { + grid-column-end: 5; + } + .xs\:bui-col-end-6 { + grid-column-end: 6; + } + .xs\:bui-col-end-7 { + grid-column-end: 7; + } + .xs\:bui-col-end-8 { + grid-column-end: 8; + } + .xs\:bui-col-end-9 { + grid-column-end: 9; + } + .xs\:bui-col-end-10 { + grid-column-end: 10; + } + .xs\:bui-col-end-11 { + grid-column-end: 11; + } + .xs\:bui-col-end-12 { + grid-column-end: 12; + } + .xs\:bui-col-end-13 { + grid-column-end: 13; + } + .xs\:bui-col-end-auto { + grid-column-end: auto; + } + .xs\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + .xs\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + .xs\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + .xs\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + .xs\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + .xs\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + .xs\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + .xs\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + .xs\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + .xs\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + .xs\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + .xs\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + .xs\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .sm\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .sm\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .sm\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .sm\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + .sm\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + .sm\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + .sm\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + .sm\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + .sm\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + .sm\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + .sm\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + .sm\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + .sm\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + .sm\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + .sm\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + .sm\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + .sm\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + .sm\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + .sm\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + .sm\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + .sm\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + .sm\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + .sm\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + .sm\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + .sm\:bui-col-span-auto { + grid-column: span auto / span auto; + } + .sm\:bui-col-start-1 { + grid-column-start: 1; + } + .sm\:bui-col-start-2 { + grid-column-start: 2; + } + .sm\:bui-col-start-3 { + grid-column-start: 3; + } + .sm\:bui-col-start-4 { + grid-column-start: 4; + } + .sm\:bui-col-start-5 { + grid-column-start: 5; + } + .sm\:bui-col-start-6 { + grid-column-start: 6; + } + .sm\:bui-col-start-7 { + grid-column-start: 7; + } + .sm\:bui-col-start-8 { + grid-column-start: 8; + } + .sm\:bui-col-start-9 { + grid-column-start: 9; + } + .sm\:bui-col-start-10 { + grid-column-start: 10; + } + .sm\:bui-col-start-11 { + grid-column-start: 11; + } + .sm\:bui-col-start-12 { + grid-column-start: 12; + } + .sm\:bui-col-start-13 { + grid-column-start: 13; + } + .sm\:bui-col-start-auto { + grid-column-start: auto; + } + .sm\:bui-col-end-1 { + grid-column-end: 1; + } + .sm\:bui-col-end-2 { + grid-column-end: 2; + } + .sm\:bui-col-end-3 { + grid-column-end: 3; + } + .sm\:bui-col-end-4 { + grid-column-end: 4; + } + .sm\:bui-col-end-5 { + grid-column-end: 5; + } + .sm\:bui-col-end-6 { + grid-column-end: 6; + } + .sm\:bui-col-end-7 { + grid-column-end: 7; + } + .sm\:bui-col-end-8 { + grid-column-end: 8; + } + .sm\:bui-col-end-9 { + grid-column-end: 9; + } + .sm\:bui-col-end-10 { + grid-column-end: 10; + } + .sm\:bui-col-end-11 { + grid-column-end: 11; + } + .sm\:bui-col-end-12 { + grid-column-end: 12; + } + .sm\:bui-col-end-13 { + grid-column-end: 13; + } + .sm\:bui-col-end-auto { + grid-column-end: auto; + } + .sm\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + .sm\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + .sm\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + .sm\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + .sm\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + .sm\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + .sm\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + .sm\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + .sm\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + .sm\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + .sm\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + .sm\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + .sm\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .md\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .md\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .md\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .md\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + .md\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + .md\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + .md\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + .md\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + .md\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + .md\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + .md\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + .md\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + .md\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + .md\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + .md\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + .md\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + .md\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + .md\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + .md\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + .md\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + .md\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + .md\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + .md\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + .md\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + .md\:bui-col-span-auto { + grid-column: span auto / span auto; + } + .md\:bui-col-start-1 { + grid-column-start: 1; + } + .md\:bui-col-start-2 { + grid-column-start: 2; + } + .md\:bui-col-start-3 { + grid-column-start: 3; + } + .md\:bui-col-start-4 { + grid-column-start: 4; + } + .md\:bui-col-start-5 { + grid-column-start: 5; + } + .md\:bui-col-start-6 { + grid-column-start: 6; + } + .md\:bui-col-start-7 { + grid-column-start: 7; + } + .md\:bui-col-start-8 { + grid-column-start: 8; + } + .md\:bui-col-start-9 { + grid-column-start: 9; + } + .md\:bui-col-start-10 { + grid-column-start: 10; + } + .md\:bui-col-start-11 { + grid-column-start: 11; + } + .md\:bui-col-start-12 { + grid-column-start: 12; + } + .md\:bui-col-start-13 { + grid-column-start: 13; + } + .md\:bui-col-start-auto { + grid-column-start: auto; + } + .md\:bui-col-end-1 { + grid-column-end: 1; + } + .md\:bui-col-end-2 { + grid-column-end: 2; + } + .md\:bui-col-end-3 { + grid-column-end: 3; + } + .md\:bui-col-end-4 { + grid-column-end: 4; + } + .md\:bui-col-end-5 { + grid-column-end: 5; + } + .md\:bui-col-end-6 { + grid-column-end: 6; + } + .md\:bui-col-end-7 { + grid-column-end: 7; + } + .md\:bui-col-end-8 { + grid-column-end: 8; + } + .md\:bui-col-end-9 { + grid-column-end: 9; + } + .md\:bui-col-end-10 { + grid-column-end: 10; + } + .md\:bui-col-end-11 { + grid-column-end: 11; + } + .md\:bui-col-end-12 { + grid-column-end: 12; + } + .md\:bui-col-end-13 { + grid-column-end: 13; + } + .md\:bui-col-end-auto { + grid-column-end: auto; + } + .md\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + .md\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + .md\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + .md\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + .md\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + .md\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + .md\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + .md\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + .md\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + .md\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + .md\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + .md\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + .md\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .lg\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .lg\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .lg\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .lg\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + .lg\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + .lg\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + .lg\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + .lg\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + .lg\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + .lg\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + .lg\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + .lg\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + .lg\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + .lg\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + .lg\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + .lg\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + .lg\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + .lg\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + .lg\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + .lg\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + .lg\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + .lg\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + .lg\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + .lg\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + .lg\:bui-col-span-auto { + grid-column: span auto / span auto; + } + .lg\:bui-col-start-1 { + grid-column-start: 1; + } + .lg\:bui-col-start-2 { + grid-column-start: 2; + } + .lg\:bui-col-start-3 { + grid-column-start: 3; + } + .lg\:bui-col-start-4 { + grid-column-start: 4; + } + .lg\:bui-col-start-5 { + grid-column-start: 5; + } + .lg\:bui-col-start-6 { + grid-column-start: 6; + } + .lg\:bui-col-start-7 { + grid-column-start: 7; + } + .lg\:bui-col-start-8 { + grid-column-start: 8; + } + .lg\:bui-col-start-9 { + grid-column-start: 9; + } + .lg\:bui-col-start-10 { + grid-column-start: 10; + } + .lg\:bui-col-start-11 { + grid-column-start: 11; + } + .lg\:bui-col-start-12 { + grid-column-start: 12; + } + .lg\:bui-col-start-13 { + grid-column-start: 13; + } + .lg\:bui-col-start-auto { + grid-column-start: auto; + } + .lg\:bui-col-end-1 { + grid-column-end: 1; + } + .lg\:bui-col-end-2 { + grid-column-end: 2; + } + .lg\:bui-col-end-3 { + grid-column-end: 3; + } + .lg\:bui-col-end-4 { + grid-column-end: 4; + } + .lg\:bui-col-end-5 { + grid-column-end: 5; + } + .lg\:bui-col-end-6 { + grid-column-end: 6; + } + .lg\:bui-col-end-7 { + grid-column-end: 7; + } + .lg\:bui-col-end-8 { + grid-column-end: 8; + } + .lg\:bui-col-end-9 { + grid-column-end: 9; + } + .lg\:bui-col-end-10 { + grid-column-end: 10; + } + .lg\:bui-col-end-11 { + grid-column-end: 11; + } + .lg\:bui-col-end-12 { + grid-column-end: 12; + } + .lg\:bui-col-end-13 { + grid-column-end: 13; + } + .lg\:bui-col-end-auto { + grid-column-end: auto; + } + .lg\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + .lg\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + .lg\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + .lg\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + .lg\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + .lg\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + .lg\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + .lg\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + .lg\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + .lg\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + .lg\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + .lg\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + .lg\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .xl\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .xl\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .xl\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + .xl\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + .xl\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + .xl\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + .xl\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + .xl\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + .xl\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + .xl\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + .xl\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + .xl\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + .xl\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + .xl\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + .xl\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + .xl\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + .xl\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + .xl\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + .xl\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + .xl\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + .xl\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + .xl\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + .xl\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + .xl\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + .xl\:bui-col-span-auto { + grid-column: span auto / span auto; + } + .xl\:bui-col-start-1 { + grid-column-start: 1; + } + .xl\:bui-col-start-2 { + grid-column-start: 2; + } + .xl\:bui-col-start-3 { + grid-column-start: 3; + } + .xl\:bui-col-start-4 { + grid-column-start: 4; + } + .xl\:bui-col-start-5 { + grid-column-start: 5; + } + .xl\:bui-col-start-6 { + grid-column-start: 6; + } + .xl\:bui-col-start-7 { + grid-column-start: 7; + } + .xl\:bui-col-start-8 { + grid-column-start: 8; + } + .xl\:bui-col-start-9 { + grid-column-start: 9; + } + .xl\:bui-col-start-10 { + grid-column-start: 10; + } + .xl\:bui-col-start-11 { + grid-column-start: 11; + } + .xl\:bui-col-start-12 { + grid-column-start: 12; + } + .xl\:bui-col-start-13 { + grid-column-start: 13; + } + .xl\:bui-col-start-auto { + grid-column-start: auto; + } + .xl\:bui-col-end-1 { + grid-column-end: 1; + } + .xl\:bui-col-end-2 { + grid-column-end: 2; + } + .xl\:bui-col-end-3 { + grid-column-end: 3; + } + .xl\:bui-col-end-4 { + grid-column-end: 4; + } + .xl\:bui-col-end-5 { + grid-column-end: 5; + } + .xl\:bui-col-end-6 { + grid-column-end: 6; + } + .xl\:bui-col-end-7 { + grid-column-end: 7; + } + .xl\:bui-col-end-8 { + grid-column-end: 8; + } + .xl\:bui-col-end-9 { + grid-column-end: 9; + } + .xl\:bui-col-end-10 { + grid-column-end: 10; + } + .xl\:bui-col-end-11 { + grid-column-end: 11; + } + .xl\:bui-col-end-12 { + grid-column-end: 12; + } + .xl\:bui-col-end-13 { + grid-column-end: 13; + } + .xl\:bui-col-end-auto { + grid-column-end: auto; + } + .xl\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + .xl\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + .xl\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + .xl\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + .xl\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + .xl\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + .xl\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + .xl\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + .xl\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + .xl\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + .xl\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + .xl\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + .xl\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } } diff --git a/packages/ui/src/css/utilities/height.css b/packages/ui/src/css/utilities/height.css index 5c245cbfb9..2028ed1510 100644 --- a/packages/ui/src/css/utilities/height.css +++ b/packages/ui/src/css/utilities/height.css @@ -1,86 +1,104 @@ -.bui-h { - height: var(--height); -} +/* + * 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. + */ -.bui-min-h { - min-height: var(--min-height); -} - -.bui-max-h { - max-height: var(--max-height); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-h { +@layer utilities { + .bui-h { height: var(--height); } - .xs\:bui-min-h { + .bui-min-h { min-height: var(--min-height); } - .xs\:bui-max-h { + .bui-max-h { max-height: var(--max-height); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-h { - height: var(--height); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-h { + height: var(--height); + } + + .xs\:bui-min-h { + min-height: var(--min-height); + } + + .xs\:bui-max-h { + max-height: var(--max-height); + } } - .sm\:bui-min-h { - min-height: var(--min-height); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-h { + height: var(--height); + } + + .sm\:bui-min-h { + min-height: var(--min-height); + } + + .sm\:bui-max-h { + max-height: var(--max-height); + } } - .sm\:bui-max-h { - max-height: var(--max-height); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-h { - height: var(--height); - } - - .md\:bui-min-h { - min-height: var(--min-height); - } - - .md\:bui-max-h { - max-height: var(--max-height); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-h { - height: var(--height); - } - - .lg\:bui-min-h { - min-height: var(--min-height); - } - - .lg\:bui-max-h { - max-height: var(--max-height); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-h { - height: var(--height); - } - - .xl\:bui-min-h { - min-height: var(--min-height); - } - - .xl\:bui-max-h { - max-height: var(--max-height); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-h { + height: var(--height); + } + + .md\:bui-min-h { + min-height: var(--min-height); + } + + .md\:bui-max-h { + max-height: var(--max-height); + } + } + + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-h { + height: var(--height); + } + + .lg\:bui-min-h { + min-height: var(--min-height); + } + + .lg\:bui-max-h { + max-height: var(--max-height); + } + } + + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-h { + height: var(--height); + } + + .xl\:bui-min-h { + min-height: var(--min-height); + } + + .xl\:bui-max-h { + max-height: var(--max-height); + } } } diff --git a/packages/ui/src/css/utilities/m.css b/packages/ui/src/css/utilities/m.css index b2c1099d9b..75d150acfb 100644 --- a/packages/ui/src/css/utilities/m.css +++ b/packages/ui/src/css/utilities/m.css @@ -1,422 +1,440 @@ -.bui-m { - margin: var(--m); -} +/* + * 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. + */ -.bui-m-0\.5 { - margin: var(--bui-space-0_5); -} - -.bui-m-1 { - margin: var(--bui-space-1); -} - -.bui-m-1\.5 { - margin: var(--bui-space-1_5); -} - -.bui-m-2 { - margin: var(--bui-space-2); -} - -.bui-m-3 { - margin: var(--bui-space-3); -} - -.bui-m-4 { - margin: var(--bui-space-4); -} - -.bui-m-5 { - margin: var(--bui-space-5); -} - -.bui-m-6 { - margin: var(--bui-space-6); -} - -.bui-m-7 { - margin: var(--bui-space-7); -} - -.bui-m-8 { - margin: var(--bui-space-8); -} - -.bui-m-9 { - margin: var(--bui-space-9); -} - -.bui-m-10 { - margin: var(--bui-space-10); -} - -.bui-m-11 { - margin: var(--bui-space-11); -} - -.bui-m-12 { - margin: var(--bui-space-12); -} - -.bui-m-13 { - margin: var(--bui-space-13); -} - -.bui-m-14 { - margin: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-m { - margin: var(--p-xs); +@layer utilities { + .bui-m { + margin: var(--m); } - .xs\:bui-m-0\.5 { + .bui-m-0\.5 { margin: var(--bui-space-0_5); } - .xs\:bui-m-1 { + .bui-m-1 { margin: var(--bui-space-1); } - .xs\:bui-m-1\.5 { + .bui-m-1\.5 { margin: var(--bui-space-1_5); } - .xs\:bui-m-2 { + .bui-m-2 { margin: var(--bui-space-2); } - .xs\:bui-m-3 { + .bui-m-3 { margin: var(--bui-space-3); } - .xs\:bui-m-4 { + .bui-m-4 { margin: var(--bui-space-4); } - .xs\:bui-m-5 { + .bui-m-5 { margin: var(--bui-space-5); } - .xs\:bui-m-6 { + .bui-m-6 { margin: var(--bui-space-6); } - .xs\:bui-m-7 { + .bui-m-7 { margin: var(--bui-space-7); } - .xs\:bui-m-8 { + .bui-m-8 { margin: var(--bui-space-8); } - .xs\:bui-m-9 { + .bui-m-9 { margin: var(--bui-space-9); } - .xs\:bui-m-10 { + .bui-m-10 { margin: var(--bui-space-10); } - .xs\:bui-m-11 { + .bui-m-11 { margin: var(--bui-space-11); } - .xs\:bui-m-12 { + .bui-m-12 { margin: var(--bui-space-12); } - .xs\:bui-m-13 { + .bui-m-13 { margin: var(--bui-space-13); } - .xs\:bui-m-14 { + .bui-m-14 { margin: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-m { - margin: var(--p-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-m { + margin: var(--p-xs); + } + + .xs\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .xs\:bui-m-1 { + margin: var(--bui-space-1); + } + + .xs\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .xs\:bui-m-2 { + margin: var(--bui-space-2); + } + + .xs\:bui-m-3 { + margin: var(--bui-space-3); + } + + .xs\:bui-m-4 { + margin: var(--bui-space-4); + } + + .xs\:bui-m-5 { + margin: var(--bui-space-5); + } + + .xs\:bui-m-6 { + margin: var(--bui-space-6); + } + + .xs\:bui-m-7 { + margin: var(--bui-space-7); + } + + .xs\:bui-m-8 { + margin: var(--bui-space-8); + } + + .xs\:bui-m-9 { + margin: var(--bui-space-9); + } + + .xs\:bui-m-10 { + margin: var(--bui-space-10); + } + + .xs\:bui-m-11 { + margin: var(--bui-space-11); + } + + .xs\:bui-m-12 { + margin: var(--bui-space-12); + } + + .xs\:bui-m-13 { + margin: var(--bui-space-13); + } + + .xs\:bui-m-14 { + margin: var(--bui-space-14); + } } - .sm\:bui-m-0\.5 { - margin: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-m { + margin: var(--p-sm); + } + + .sm\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .sm\:bui-m-1 { + margin: var(--bui-space-1); + } + + .sm\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .sm\:bui-m-2 { + margin: var(--bui-space-2); + } + + .sm\:bui-m-3 { + margin: var(--bui-space-3); + } + + .sm\:bui-m-4 { + margin: var(--bui-space-4); + } + + .sm\:bui-m-5 { + margin: var(--bui-space-5); + } + + .sm\:bui-m-6 { + margin: var(--bui-space-6); + } + + .sm\:bui-m-7 { + margin: var(--bui-space-7); + } + + .sm\:bui-m-8 { + margin: var(--bui-space-8); + } + + .sm\:bui-m-9 { + margin: var(--bui-space-9); + } + + .sm\:bui-m-10 { + margin: var(--bui-space-10); + } + + .sm\:bui-m-11 { + margin: var(--bui-space-11); + } + + .sm\:bui-m-12 { + margin: var(--bui-space-12); + } + + .sm\:bui-m-13 { + margin: var(--bui-space-13); + } + + .sm\:bui-m-14 { + margin: var(--bui-space-14); + } } - .sm\:bui-m-1 { - margin: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-m { + margin: var(--p-md); + } + + .md\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .md\:bui-m-1 { + margin: var(--bui-space-1); + } + + .md\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .md\:bui-m-2 { + margin: var(--bui-space-2); + } + + .md\:bui-m-3 { + margin: var(--bui-space-3); + } + + .md\:bui-m-4 { + margin: var(--bui-space-4); + } + + .md\:bui-m-5 { + margin: var(--bui-space-5); + } + + .md\:bui-m-6 { + margin: var(--bui-space-6); + } + + .md\:bui-m-7 { + margin: var(--bui-space-7); + } + + .md\:bui-m-8 { + margin: var(--bui-space-8); + } + + .md\:bui-m-9 { + margin: var(--bui-space-9); + } + + .md\:bui-m-10 { + margin: var(--bui-space-10); + } + + .md\:bui-m-11 { + margin: var(--bui-space-11); + } + + .md\:bui-m-12 { + margin: var(--bui-space-12); + } + + .md\:bui-m-13 { + margin: var(--bui-space-13); + } + + .md\:bui-m-14 { + margin: var(--bui-space-14); + } } - .sm\:bui-m-1\.5 { - margin: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-m { + margin: var(--p-lg); + } + + .lg\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .lg\:bui-m-1 { + margin: var(--bui-space-1); + } + + .lg\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .lg\:bui-m-2 { + margin: var(--bui-space-2); + } + + .lg\:bui-m-3 { + margin: var(--bui-space-3); + } + + .lg\:bui-m-4 { + margin: var(--bui-space-4); + } + + .lg\:bui-m-5 { + margin: var(--bui-space-5); + } + + .lg\:bui-m-6 { + margin: var(--bui-space-6); + } + + .lg\:bui-m-7 { + margin: var(--bui-space-7); + } + + .lg\:bui-m-8 { + margin: var(--bui-space-8); + } + + .lg\:bui-m-9 { + margin: var(--bui-space-9); + } + + .lg\:bui-m-10 { + margin: var(--bui-space-10); + } + + .lg\:bui-m-11 { + margin: var(--bui-space-11); + } + + .lg\:bui-m-12 { + margin: var(--bui-space-12); + } + + .lg\:bui-m-13 { + margin: var(--bui-space-13); + } + + .lg\:bui-m-14 { + margin: var(--bui-space-14); + } } - .sm\:bui-m-2 { - margin: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-m { + margin: var(--p-xl); + } - .sm\:bui-m-3 { - margin: var(--bui-space-3); - } + .xl\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } - .sm\:bui-m-4 { - margin: var(--bui-space-4); - } + .xl\:bui-m-1 { + margin: var(--bui-space-1); + } - .sm\:bui-m-5 { - margin: var(--bui-space-5); - } + .xl\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } - .sm\:bui-m-6 { - margin: var(--bui-space-6); - } + .xl\:bui-m-2 { + margin: var(--bui-space-2); + } - .sm\:bui-m-7 { - margin: var(--bui-space-7); - } + .xl\:bui-m-3 { + margin: var(--bui-space-3); + } - .sm\:bui-m-8 { - margin: var(--bui-space-8); - } + .xl\:bui-m-4 { + margin: var(--bui-space-4); + } - .sm\:bui-m-9 { - margin: var(--bui-space-9); - } + .xl\:bui-m-5 { + margin: var(--bui-space-5); + } - .sm\:bui-m-10 { - margin: var(--bui-space-10); - } + .xl\:bui-m-6 { + margin: var(--bui-space-6); + } - .sm\:bui-m-11 { - margin: var(--bui-space-11); - } + .xl\:bui-m-7 { + margin: var(--bui-space-7); + } - .sm\:bui-m-12 { - margin: var(--bui-space-12); - } + .xl\:bui-m-8 { + margin: var(--bui-space-8); + } - .sm\:bui-m-13 { - margin: var(--bui-space-13); - } + .xl\:bui-m-9 { + margin: var(--bui-space-9); + } - .sm\:bui-m-14 { - margin: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-m { - margin: var(--p-md); - } - - .md\:bui-m-0\.5 { - margin: var(--bui-space-0_5); - } - - .md\:bui-m-1 { - margin: var(--bui-space-1); - } - - .md\:bui-m-1\.5 { - margin: var(--bui-space-1_5); - } - - .md\:bui-m-2 { - margin: var(--bui-space-2); - } - - .md\:bui-m-3 { - margin: var(--bui-space-3); - } - - .md\:bui-m-4 { - margin: var(--bui-space-4); - } - - .md\:bui-m-5 { - margin: var(--bui-space-5); - } - - .md\:bui-m-6 { - margin: var(--bui-space-6); - } - - .md\:bui-m-7 { - margin: var(--bui-space-7); - } - - .md\:bui-m-8 { - margin: var(--bui-space-8); - } - - .md\:bui-m-9 { - margin: var(--bui-space-9); - } - - .md\:bui-m-10 { - margin: var(--bui-space-10); - } - - .md\:bui-m-11 { - margin: var(--bui-space-11); - } - - .md\:bui-m-12 { - margin: var(--bui-space-12); - } - - .md\:bui-m-13 { - margin: var(--bui-space-13); - } - - .md\:bui-m-14 { - margin: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-m { - margin: var(--p-lg); - } - - .lg\:bui-m-0\.5 { - margin: var(--bui-space-0_5); - } - - .lg\:bui-m-1 { - margin: var(--bui-space-1); - } - - .lg\:bui-m-1\.5 { - margin: var(--bui-space-1_5); - } - - .lg\:bui-m-2 { - margin: var(--bui-space-2); - } - - .lg\:bui-m-3 { - margin: var(--bui-space-3); - } - - .lg\:bui-m-4 { - margin: var(--bui-space-4); - } - - .lg\:bui-m-5 { - margin: var(--bui-space-5); - } - - .lg\:bui-m-6 { - margin: var(--bui-space-6); - } - - .lg\:bui-m-7 { - margin: var(--bui-space-7); - } - - .lg\:bui-m-8 { - margin: var(--bui-space-8); - } - - .lg\:bui-m-9 { - margin: var(--bui-space-9); - } - - .lg\:bui-m-10 { - margin: var(--bui-space-10); - } - - .lg\:bui-m-11 { - margin: var(--bui-space-11); - } - - .lg\:bui-m-12 { - margin: var(--bui-space-12); - } - - .lg\:bui-m-13 { - margin: var(--bui-space-13); - } - - .lg\:bui-m-14 { - margin: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-m { - margin: var(--p-xl); - } - - .xl\:bui-m-0\.5 { - margin: var(--bui-space-0_5); - } - - .xl\:bui-m-1 { - margin: var(--bui-space-1); - } - - .xl\:bui-m-1\.5 { - margin: var(--bui-space-1_5); - } - - .xl\:bui-m-2 { - margin: var(--bui-space-2); - } - - .xl\:bui-m-3 { - margin: var(--bui-space-3); - } - - .xl\:bui-m-4 { - margin: var(--bui-space-4); - } - - .xl\:bui-m-5 { - margin: var(--bui-space-5); - } - - .xl\:bui-m-6 { - margin: var(--bui-space-6); - } - - .xl\:bui-m-7 { - margin: var(--bui-space-7); - } - - .xl\:bui-m-8 { - margin: var(--bui-space-8); - } - - .xl\:bui-m-9 { - margin: var(--bui-space-9); - } - - .xl\:bui-m-10 { - margin: var(--bui-space-10); - } - - .xl\:bui-m-11 { - margin: var(--bui-space-11); - } - - .xl\:bui-m-12 { - margin: var(--bui-space-12); - } - - .xl\:bui-m-13 { - margin: var(--bui-space-13); - } - - .xl\:bui-m-14 { - margin: var(--bui-space-14); + .xl\:bui-m-10 { + margin: var(--bui-space-10); + } + + .xl\:bui-m-11 { + margin: var(--bui-space-11); + } + + .xl\:bui-m-12 { + margin: var(--bui-space-12); + } + + .xl\:bui-m-13 { + margin: var(--bui-space-13); + } + + .xl\:bui-m-14 { + margin: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/mb.css b/packages/ui/src/css/utilities/mb.css index 576d4d488e..6394937af4 100644 --- a/packages/ui/src/css/utilities/mb.css +++ b/packages/ui/src/css/utilities/mb.css @@ -1,422 +1,440 @@ -.bui-mb { - margin-bottom: var(--mb); -} +/* + * 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. + */ -.bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); -} - -.bui-mb-1 { - margin-bottom: var(--bui-space-1); -} - -.bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); -} - -.bui-mb-2 { - margin-bottom: var(--bui-space-2); -} - -.bui-mb-3 { - margin-bottom: var(--bui-space-3); -} - -.bui-mb-4 { - margin-bottom: var(--bui-space-4); -} - -.bui-mb-5 { - margin-bottom: var(--bui-space-5); -} - -.bui-mb-6 { - margin-bottom: var(--bui-space-6); -} - -.bui-mb-7 { - margin-bottom: var(--bui-space-7); -} - -.bui-mb-8 { - margin-bottom: var(--bui-space-8); -} - -.bui-mb-9 { - margin-bottom: var(--bui-space-9); -} - -.bui-mb-10 { - margin-bottom: var(--bui-space-10); -} - -.bui-mb-11 { - margin-bottom: var(--bui-space-11); -} - -.bui-mb-12 { - margin-bottom: var(--bui-space-12); -} - -.bui-mb-13 { - margin-bottom: var(--bui-space-13); -} - -.bui-mb-14 { - margin-bottom: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-mb { - margin-bottom: var(--pb-xs); +@layer utilities { + .bui-mb { + margin-bottom: var(--mb); } - .xs\:bui-mb-0\.5 { + .bui-mb-0\.5 { margin-bottom: var(--bui-space-0_5); } - .xs\:bui-mb-1 { + .bui-mb-1 { margin-bottom: var(--bui-space-1); } - .xs\:bui-mb-1\.5 { + .bui-mb-1\.5 { margin-bottom: var(--bui-space-1_5); } - .xs\:bui-mb-2 { + .bui-mb-2 { margin-bottom: var(--bui-space-2); } - .xs\:bui-mb-3 { + .bui-mb-3 { margin-bottom: var(--bui-space-3); } - .xs\:bui-mb-4 { + .bui-mb-4 { margin-bottom: var(--bui-space-4); } - .xs\:bui-mb-5 { + .bui-mb-5 { margin-bottom: var(--bui-space-5); } - .xs\:bui-mb-6 { + .bui-mb-6 { margin-bottom: var(--bui-space-6); } - .xs\:bui-mb-7 { + .bui-mb-7 { margin-bottom: var(--bui-space-7); } - .xs\:bui-mb-8 { + .bui-mb-8 { margin-bottom: var(--bui-space-8); } - .xs\:bui-mb-9 { + .bui-mb-9 { margin-bottom: var(--bui-space-9); } - .xs\:bui-mb-10 { + .bui-mb-10 { margin-bottom: var(--bui-space-10); } - .xs\:bui-mb-11 { + .bui-mb-11 { margin-bottom: var(--bui-space-11); } - .xs\:bui-mb-12 { + .bui-mb-12 { margin-bottom: var(--bui-space-12); } - .xs\:bui-mb-13 { + .bui-mb-13 { margin-bottom: var(--bui-space-13); } - .xs\:bui-mb-14 { + .bui-mb-14 { margin-bottom: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-mb { - margin-bottom: var(--pb-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-mb { + margin-bottom: var(--pb-xs); + } + + .xs\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .xs\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .xs\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .xs\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .xs\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .xs\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .xs\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .xs\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .xs\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .xs\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .xs\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .xs\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .xs\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .xs\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .xs\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .xs\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } } - .sm\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-mb { + margin-bottom: var(--pb-sm); + } + + .sm\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .sm\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .sm\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .sm\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .sm\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .sm\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .sm\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .sm\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .sm\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .sm\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .sm\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .sm\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .sm\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .sm\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .sm\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .sm\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } } - .sm\:bui-mb-1 { - margin-bottom: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-mb { + margin-bottom: var(--pb-md); + } + + .md\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .md\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .md\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .md\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .md\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .md\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .md\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .md\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .md\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .md\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .md\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .md\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .md\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .md\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .md\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .md\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } } - .sm\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-mb { + margin-bottom: var(--pb-lg); + } + + .lg\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .lg\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .lg\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .lg\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .lg\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .lg\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .lg\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .lg\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .lg\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .lg\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .lg\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .lg\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .lg\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .lg\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .lg\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .lg\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } } - .sm\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-mb { + margin-bottom: var(--pb-xl); + } - .sm\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } + .xl\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } - .sm\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } + .xl\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } - .sm\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } + .xl\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } - .sm\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } + .xl\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } - .sm\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } + .xl\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } - .sm\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } + .xl\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } - .sm\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } + .xl\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } - .sm\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } + .xl\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } - .sm\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } + .xl\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } - .sm\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } + .xl\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } - .sm\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } + .xl\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } - .sm\:bui-mb-14 { - margin-bottom: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-mb { - margin-bottom: var(--pb-md); - } - - .md\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); - } - - .md\:bui-mb-1 { - margin-bottom: var(--bui-space-1); - } - - .md\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); - } - - .md\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } - - .md\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } - - .md\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } - - .md\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } - - .md\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } - - .md\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } - - .md\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } - - .md\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } - - .md\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } - - .md\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } - - .md\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } - - .md\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } - - .md\:bui-mb-14 { - margin-bottom: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-mb { - margin-bottom: var(--pb-lg); - } - - .lg\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); - } - - .lg\:bui-mb-1 { - margin-bottom: var(--bui-space-1); - } - - .lg\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); - } - - .lg\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } - - .lg\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } - - .lg\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } - - .lg\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } - - .lg\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } - - .lg\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } - - .lg\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } - - .lg\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } - - .lg\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } - - .lg\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } - - .lg\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } - - .lg\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } - - .lg\:bui-mb-14 { - margin-bottom: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-mb { - margin-bottom: var(--pb-xl); - } - - .xl\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); - } - - .xl\:bui-mb-1 { - margin-bottom: var(--bui-space-1); - } - - .xl\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); - } - - .xl\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } - - .xl\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } - - .xl\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } - - .xl\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } - - .xl\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } - - .xl\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } - - .xl\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } - - .xl\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } - - .xl\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } - - .xl\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } - - .xl\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } - - .xl\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } - - .xl\:bui-mb-14 { - margin-bottom: var(--bui-space-14); + .xl\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .xl\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .xl\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .xl\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .xl\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/ml.css b/packages/ui/src/css/utilities/ml.css index b11fe779fb..7b82b73ab8 100644 --- a/packages/ui/src/css/utilities/ml.css +++ b/packages/ui/src/css/utilities/ml.css @@ -1,422 +1,440 @@ -.bui-ml { - margin-left: var(--ml); -} +/* + * 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. + */ -.bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); -} - -.bui-ml-1 { - margin-left: var(--bui-space-1); -} - -.bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); -} - -.bui-ml-2 { - margin-left: var(--bui-space-2); -} - -.bui-ml-3 { - margin-left: var(--bui-space-3); -} - -.bui-ml-4 { - margin-left: var(--bui-space-4); -} - -.bui-ml-5 { - margin-left: var(--bui-space-5); -} - -.bui-ml-6 { - margin-left: var(--bui-space-6); -} - -.bui-ml-7 { - margin-left: var(--bui-space-7); -} - -.bui-ml-8 { - margin-left: var(--bui-space-8); -} - -.bui-ml-9 { - margin-left: var(--bui-space-9); -} - -.bui-ml-10 { - margin-left: var(--bui-space-10); -} - -.bui-ml-11 { - margin-left: var(--bui-space-11); -} - -.bui-ml-12 { - margin-left: var(--bui-space-12); -} - -.bui-ml-13 { - margin-left: var(--bui-space-13); -} - -.bui-ml-14 { - margin-left: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-ml { - margin-left: var(--pl-xs); +@layer utilities { + .bui-ml { + margin-left: var(--ml); } - .xs\:bui-ml-0\.5 { + .bui-ml-0\.5 { margin-left: var(--bui-space-0_5); } - .xs\:bui-ml-1 { + .bui-ml-1 { margin-left: var(--bui-space-1); } - .xs\:bui-ml-1\.5 { + .bui-ml-1\.5 { margin-left: var(--bui-space-1_5); } - .xs\:bui-ml-2 { + .bui-ml-2 { margin-left: var(--bui-space-2); } - .xs\:bui-ml-3 { + .bui-ml-3 { margin-left: var(--bui-space-3); } - .xs\:bui-ml-4 { + .bui-ml-4 { margin-left: var(--bui-space-4); } - .xs\:bui-ml-5 { + .bui-ml-5 { margin-left: var(--bui-space-5); } - .xs\:bui-ml-6 { + .bui-ml-6 { margin-left: var(--bui-space-6); } - .xs\:bui-ml-7 { + .bui-ml-7 { margin-left: var(--bui-space-7); } - .xs\:bui-ml-8 { + .bui-ml-8 { margin-left: var(--bui-space-8); } - .xs\:bui-ml-9 { + .bui-ml-9 { margin-left: var(--bui-space-9); } - .xs\:bui-ml-10 { + .bui-ml-10 { margin-left: var(--bui-space-10); } - .xs\:bui-ml-11 { + .bui-ml-11 { margin-left: var(--bui-space-11); } - .xs\:bui-ml-12 { + .bui-ml-12 { margin-left: var(--bui-space-12); } - .xs\:bui-ml-13 { + .bui-ml-13 { margin-left: var(--bui-space-13); } - .xs\:bui-ml-14 { + .bui-ml-14 { margin-left: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-ml { - margin-left: var(--pl-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-ml { + margin-left: var(--pl-xs); + } + + .xs\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .xs\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .xs\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .xs\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .xs\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .xs\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .xs\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .xs\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .xs\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .xs\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .xs\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .xs\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .xs\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .xs\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .xs\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .xs\:bui-ml-14 { + margin-left: var(--bui-space-14); + } } - .sm\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-ml { + margin-left: var(--pl-sm); + } + + .sm\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .sm\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .sm\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .sm\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .sm\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .sm\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .sm\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .sm\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .sm\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .sm\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .sm\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .sm\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .sm\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .sm\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .sm\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .sm\:bui-ml-14 { + margin-left: var(--bui-space-14); + } } - .sm\:bui-ml-1 { - margin-left: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-ml { + margin-left: var(--pl-md); + } + + .md\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .md\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .md\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .md\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .md\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .md\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .md\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .md\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .md\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .md\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .md\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .md\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .md\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .md\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .md\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .md\:bui-ml-14 { + margin-left: var(--bui-space-14); + } } - .sm\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-ml { + margin-left: var(--pl-lg); + } + + .lg\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .lg\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .lg\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .lg\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .lg\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .lg\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .lg\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .lg\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .lg\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .lg\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .lg\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .lg\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .lg\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .lg\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .lg\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .lg\:bui-ml-14 { + margin-left: var(--bui-space-14); + } } - .sm\:bui-ml-2 { - margin-left: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-ml { + margin-left: var(--pl-xl); + } - .sm\:bui-ml-3 { - margin-left: var(--bui-space-3); - } + .xl\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } - .sm\:bui-ml-4 { - margin-left: var(--bui-space-4); - } + .xl\:bui-ml-1 { + margin-left: var(--bui-space-1); + } - .sm\:bui-ml-5 { - margin-left: var(--bui-space-5); - } + .xl\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } - .sm\:bui-ml-6 { - margin-left: var(--bui-space-6); - } + .xl\:bui-ml-2 { + margin-left: var(--bui-space-2); + } - .sm\:bui-ml-7 { - margin-left: var(--bui-space-7); - } + .xl\:bui-ml-3 { + margin-left: var(--bui-space-3); + } - .sm\:bui-ml-8 { - margin-left: var(--bui-space-8); - } + .xl\:bui-ml-4 { + margin-left: var(--bui-space-4); + } - .sm\:bui-ml-9 { - margin-left: var(--bui-space-9); - } + .xl\:bui-ml-5 { + margin-left: var(--bui-space-5); + } - .sm\:bui-ml-10 { - margin-left: var(--bui-space-10); - } + .xl\:bui-ml-6 { + margin-left: var(--bui-space-6); + } - .sm\:bui-ml-11 { - margin-left: var(--bui-space-11); - } + .xl\:bui-ml-7 { + margin-left: var(--bui-space-7); + } - .sm\:bui-ml-12 { - margin-left: var(--bui-space-12); - } + .xl\:bui-ml-8 { + margin-left: var(--bui-space-8); + } - .sm\:bui-ml-13 { - margin-left: var(--bui-space-13); - } + .xl\:bui-ml-9 { + margin-left: var(--bui-space-9); + } - .sm\:bui-ml-14 { - margin-left: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-ml { - margin-left: var(--pl-md); - } - - .md\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); - } - - .md\:bui-ml-1 { - margin-left: var(--bui-space-1); - } - - .md\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); - } - - .md\:bui-ml-2 { - margin-left: var(--bui-space-2); - } - - .md\:bui-ml-3 { - margin-left: var(--bui-space-3); - } - - .md\:bui-ml-4 { - margin-left: var(--bui-space-4); - } - - .md\:bui-ml-5 { - margin-left: var(--bui-space-5); - } - - .md\:bui-ml-6 { - margin-left: var(--bui-space-6); - } - - .md\:bui-ml-7 { - margin-left: var(--bui-space-7); - } - - .md\:bui-ml-8 { - margin-left: var(--bui-space-8); - } - - .md\:bui-ml-9 { - margin-left: var(--bui-space-9); - } - - .md\:bui-ml-10 { - margin-left: var(--bui-space-10); - } - - .md\:bui-ml-11 { - margin-left: var(--bui-space-11); - } - - .md\:bui-ml-12 { - margin-left: var(--bui-space-12); - } - - .md\:bui-ml-13 { - margin-left: var(--bui-space-13); - } - - .md\:bui-ml-14 { - margin-left: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-ml { - margin-left: var(--pl-lg); - } - - .lg\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); - } - - .lg\:bui-ml-1 { - margin-left: var(--bui-space-1); - } - - .lg\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); - } - - .lg\:bui-ml-2 { - margin-left: var(--bui-space-2); - } - - .lg\:bui-ml-3 { - margin-left: var(--bui-space-3); - } - - .lg\:bui-ml-4 { - margin-left: var(--bui-space-4); - } - - .lg\:bui-ml-5 { - margin-left: var(--bui-space-5); - } - - .lg\:bui-ml-6 { - margin-left: var(--bui-space-6); - } - - .lg\:bui-ml-7 { - margin-left: var(--bui-space-7); - } - - .lg\:bui-ml-8 { - margin-left: var(--bui-space-8); - } - - .lg\:bui-ml-9 { - margin-left: var(--bui-space-9); - } - - .lg\:bui-ml-10 { - margin-left: var(--bui-space-10); - } - - .lg\:bui-ml-11 { - margin-left: var(--bui-space-11); - } - - .lg\:bui-ml-12 { - margin-left: var(--bui-space-12); - } - - .lg\:bui-ml-13 { - margin-left: var(--bui-space-13); - } - - .lg\:bui-ml-14 { - margin-left: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-ml { - margin-left: var(--pl-xl); - } - - .xl\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); - } - - .xl\:bui-ml-1 { - margin-left: var(--bui-space-1); - } - - .xl\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); - } - - .xl\:bui-ml-2 { - margin-left: var(--bui-space-2); - } - - .xl\:bui-ml-3 { - margin-left: var(--bui-space-3); - } - - .xl\:bui-ml-4 { - margin-left: var(--bui-space-4); - } - - .xl\:bui-ml-5 { - margin-left: var(--bui-space-5); - } - - .xl\:bui-ml-6 { - margin-left: var(--bui-space-6); - } - - .xl\:bui-ml-7 { - margin-left: var(--bui-space-7); - } - - .xl\:bui-ml-8 { - margin-left: var(--bui-space-8); - } - - .xl\:bui-ml-9 { - margin-left: var(--bui-space-9); - } - - .xl\:bui-ml-10 { - margin-left: var(--bui-space-10); - } - - .xl\:bui-ml-11 { - margin-left: var(--bui-space-11); - } - - .xl\:bui-ml-12 { - margin-left: var(--bui-space-12); - } - - .xl\:bui-ml-13 { - margin-left: var(--bui-space-13); - } - - .xl\:bui-ml-14 { - margin-left: var(--bui-space-14); + .xl\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .xl\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .xl\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .xl\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .xl\:bui-ml-14 { + margin-left: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/mr.css b/packages/ui/src/css/utilities/mr.css index 215a9dc88d..bac16b3ed3 100644 --- a/packages/ui/src/css/utilities/mr.css +++ b/packages/ui/src/css/utilities/mr.css @@ -1,422 +1,440 @@ -.bui-mr { - margin-right: var(--mr); -} +/* + * 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. + */ -.bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); -} - -.bui-mr-1 { - margin-right: var(--bui-space-1); -} - -.bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); -} - -.bui-mr-2 { - margin-right: var(--bui-space-2); -} - -.bui-mr-3 { - margin-right: var(--bui-space-3); -} - -.bui-mr-4 { - margin-right: var(--bui-space-4); -} - -.bui-mr-5 { - margin-right: var(--bui-space-5); -} - -.bui-mr-6 { - margin-right: var(--bui-space-6); -} - -.bui-mr-7 { - margin-right: var(--bui-space-7); -} - -.bui-mr-8 { - margin-right: var(--bui-space-8); -} - -.bui-mr-9 { - margin-right: var(--bui-space-9); -} - -.bui-mr-10 { - margin-right: var(--bui-space-10); -} - -.bui-mr-11 { - margin-right: var(--bui-space-11); -} - -.bui-mr-12 { - margin-right: var(--bui-space-12); -} - -.bui-mr-13 { - margin-right: var(--bui-space-13); -} - -.bui-mr-14 { - margin-right: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-mr { - margin-right: var(--pr-xs); +@layer utilities { + .bui-mr { + margin-right: var(--mr); } - .xs\:bui-mr-0\.5 { + .bui-mr-0\.5 { margin-right: var(--bui-space-0_5); } - .xs\:bui-mr-1 { + .bui-mr-1 { margin-right: var(--bui-space-1); } - .xs\:bui-mr-1\.5 { + .bui-mr-1\.5 { margin-right: var(--bui-space-1_5); } - .xs\:bui-mr-2 { + .bui-mr-2 { margin-right: var(--bui-space-2); } - .xs\:bui-mr-3 { + .bui-mr-3 { margin-right: var(--bui-space-3); } - .xs\:bui-mr-4 { + .bui-mr-4 { margin-right: var(--bui-space-4); } - .xs\:bui-mr-5 { + .bui-mr-5 { margin-right: var(--bui-space-5); } - .xs\:bui-mr-6 { + .bui-mr-6 { margin-right: var(--bui-space-6); } - .xs\:bui-mr-7 { + .bui-mr-7 { margin-right: var(--bui-space-7); } - .xs\:bui-mr-8 { + .bui-mr-8 { margin-right: var(--bui-space-8); } - .xs\:bui-mr-9 { + .bui-mr-9 { margin-right: var(--bui-space-9); } - .xs\:bui-mr-10 { + .bui-mr-10 { margin-right: var(--bui-space-10); } - .xs\:bui-mr-11 { + .bui-mr-11 { margin-right: var(--bui-space-11); } - .xs\:bui-mr-12 { + .bui-mr-12 { margin-right: var(--bui-space-12); } - .xs\:bui-mr-13 { + .bui-mr-13 { margin-right: var(--bui-space-13); } - .xs\:bui-mr-14 { + .bui-mr-14 { margin-right: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-mr { - margin-right: var(--pr-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-mr { + margin-right: var(--pr-xs); + } + + .xs\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .xs\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .xs\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .xs\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .xs\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .xs\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .xs\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .xs\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .xs\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .xs\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .xs\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .xs\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .xs\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .xs\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .xs\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .xs\:bui-mr-14 { + margin-right: var(--bui-space-14); + } } - .sm\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-mr { + margin-right: var(--pr-sm); + } + + .sm\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .sm\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .sm\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .sm\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .sm\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .sm\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .sm\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .sm\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .sm\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .sm\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .sm\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .sm\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .sm\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .sm\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .sm\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .sm\:bui-mr-14 { + margin-right: var(--bui-space-14); + } } - .sm\:bui-mr-1 { - margin-right: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-mr { + margin-right: var(--pr-md); + } + + .md\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .md\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .md\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .md\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .md\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .md\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .md\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .md\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .md\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .md\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .md\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .md\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .md\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .md\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .md\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .md\:bui-mr-14 { + margin-right: var(--bui-space-14); + } } - .sm\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-mr { + margin-right: var(--pr-lg); + } + + .lg\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .lg\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .lg\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .lg\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .lg\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .lg\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .lg\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .lg\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .lg\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .lg\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .lg\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .lg\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .lg\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .lg\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .lg\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .lg\:bui-mr-14 { + margin-right: var(--bui-space-14); + } } - .sm\:bui-mr-2 { - margin-right: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-mr { + margin-right: var(--pr-xl); + } - .sm\:bui-mr-3 { - margin-right: var(--bui-space-3); - } + .xl\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } - .sm\:bui-mr-4 { - margin-right: var(--bui-space-4); - } + .xl\:bui-mr-1 { + margin-right: var(--bui-space-1); + } - .sm\:bui-mr-5 { - margin-right: var(--bui-space-5); - } + .xl\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } - .sm\:bui-mr-6 { - margin-right: var(--bui-space-6); - } + .xl\:bui-mr-2 { + margin-right: var(--bui-space-2); + } - .sm\:bui-mr-7 { - margin-right: var(--bui-space-7); - } + .xl\:bui-mr-3 { + margin-right: var(--bui-space-3); + } - .sm\:bui-mr-8 { - margin-right: var(--bui-space-8); - } + .xl\:bui-mr-4 { + margin-right: var(--bui-space-4); + } - .sm\:bui-mr-9 { - margin-right: var(--bui-space-9); - } + .xl\:bui-mr-5 { + margin-right: var(--bui-space-5); + } - .sm\:bui-mr-10 { - margin-right: var(--bui-space-10); - } + .xl\:bui-mr-6 { + margin-right: var(--bui-space-6); + } - .sm\:bui-mr-11 { - margin-right: var(--bui-space-11); - } + .xl\:bui-mr-7 { + margin-right: var(--bui-space-7); + } - .sm\:bui-mr-12 { - margin-right: var(--bui-space-12); - } + .xl\:bui-mr-8 { + margin-right: var(--bui-space-8); + } - .sm\:bui-mr-13 { - margin-right: var(--bui-space-13); - } + .xl\:bui-mr-9 { + margin-right: var(--bui-space-9); + } - .sm\:bui-mr-14 { - margin-right: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-mr { - margin-right: var(--pr-md); - } - - .md\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); - } - - .md\:bui-mr-1 { - margin-right: var(--bui-space-1); - } - - .md\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); - } - - .md\:bui-mr-2 { - margin-right: var(--bui-space-2); - } - - .md\:bui-mr-3 { - margin-right: var(--bui-space-3); - } - - .md\:bui-mr-4 { - margin-right: var(--bui-space-4); - } - - .md\:bui-mr-5 { - margin-right: var(--bui-space-5); - } - - .md\:bui-mr-6 { - margin-right: var(--bui-space-6); - } - - .md\:bui-mr-7 { - margin-right: var(--bui-space-7); - } - - .md\:bui-mr-8 { - margin-right: var(--bui-space-8); - } - - .md\:bui-mr-9 { - margin-right: var(--bui-space-9); - } - - .md\:bui-mr-10 { - margin-right: var(--bui-space-10); - } - - .md\:bui-mr-11 { - margin-right: var(--bui-space-11); - } - - .md\:bui-mr-12 { - margin-right: var(--bui-space-12); - } - - .md\:bui-mr-13 { - margin-right: var(--bui-space-13); - } - - .md\:bui-mr-14 { - margin-right: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-mr { - margin-right: var(--pr-lg); - } - - .lg\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); - } - - .lg\:bui-mr-1 { - margin-right: var(--bui-space-1); - } - - .lg\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); - } - - .lg\:bui-mr-2 { - margin-right: var(--bui-space-2); - } - - .lg\:bui-mr-3 { - margin-right: var(--bui-space-3); - } - - .lg\:bui-mr-4 { - margin-right: var(--bui-space-4); - } - - .lg\:bui-mr-5 { - margin-right: var(--bui-space-5); - } - - .lg\:bui-mr-6 { - margin-right: var(--bui-space-6); - } - - .lg\:bui-mr-7 { - margin-right: var(--bui-space-7); - } - - .lg\:bui-mr-8 { - margin-right: var(--bui-space-8); - } - - .lg\:bui-mr-9 { - margin-right: var(--bui-space-9); - } - - .lg\:bui-mr-10 { - margin-right: var(--bui-space-10); - } - - .lg\:bui-mr-11 { - margin-right: var(--bui-space-11); - } - - .lg\:bui-mr-12 { - margin-right: var(--bui-space-12); - } - - .lg\:bui-mr-13 { - margin-right: var(--bui-space-13); - } - - .lg\:bui-mr-14 { - margin-right: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-mr { - margin-right: var(--pr-xl); - } - - .xl\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); - } - - .xl\:bui-mr-1 { - margin-right: var(--bui-space-1); - } - - .xl\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); - } - - .xl\:bui-mr-2 { - margin-right: var(--bui-space-2); - } - - .xl\:bui-mr-3 { - margin-right: var(--bui-space-3); - } - - .xl\:bui-mr-4 { - margin-right: var(--bui-space-4); - } - - .xl\:bui-mr-5 { - margin-right: var(--bui-space-5); - } - - .xl\:bui-mr-6 { - margin-right: var(--bui-space-6); - } - - .xl\:bui-mr-7 { - margin-right: var(--bui-space-7); - } - - .xl\:bui-mr-8 { - margin-right: var(--bui-space-8); - } - - .xl\:bui-mr-9 { - margin-right: var(--bui-space-9); - } - - .xl\:bui-mr-10 { - margin-right: var(--bui-space-10); - } - - .xl\:bui-mr-11 { - margin-right: var(--bui-space-11); - } - - .xl\:bui-mr-12 { - margin-right: var(--bui-space-12); - } - - .xl\:bui-mr-13 { - margin-right: var(--bui-space-13); - } - - .xl\:bui-mr-14 { - margin-right: var(--bui-space-14); + .xl\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .xl\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .xl\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .xl\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .xl\:bui-mr-14 { + margin-right: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/mt.css b/packages/ui/src/css/utilities/mt.css index 30035bf8bd..2f6ecc4aa8 100644 --- a/packages/ui/src/css/utilities/mt.css +++ b/packages/ui/src/css/utilities/mt.css @@ -1,422 +1,440 @@ -.bui-mt { - margin-top: var(--mt); -} +/* + * 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. + */ -.bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); -} - -.bui-mt-1 { - margin-top: var(--bui-space-1); -} - -.bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); -} - -.bui-mt-2 { - margin-top: var(--bui-space-2); -} - -.bui-mt-3 { - margin-top: var(--bui-space-3); -} - -.bui-mt-4 { - margin-top: var(--bui-space-4); -} - -.bui-mt-5 { - margin-top: var(--bui-space-5); -} - -.bui-mt-6 { - margin-top: var(--bui-space-6); -} - -.bui-mt-7 { - margin-top: var(--bui-space-7); -} - -.bui-mt-8 { - margin-top: var(--bui-space-8); -} - -.bui-mt-9 { - margin-top: var(--bui-space-9); -} - -.bui-mt-10 { - margin-top: var(--bui-space-10); -} - -.bui-mt-11 { - margin-top: var(--bui-space-11); -} - -.bui-mt-12 { - margin-top: var(--bui-space-12); -} - -.bui-mt-13 { - margin-top: var(--bui-space-13); -} - -.bui-mt-14 { - margin-top: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-mt { - margin-top: var(--pt-xs); +@layer utilities { + .bui-mt { + margin-top: var(--mt); } - .xs\:bui-mt-0\.5 { + .bui-mt-0\.5 { margin-top: var(--bui-space-0_5); } - .xs\:bui-mt-1 { + .bui-mt-1 { margin-top: var(--bui-space-1); } - .xs\:bui-mt-1\.5 { + .bui-mt-1\.5 { margin-top: var(--bui-space-1_5); } - .xs\:bui-mt-2 { + .bui-mt-2 { margin-top: var(--bui-space-2); } - .xs\:bui-mt-3 { + .bui-mt-3 { margin-top: var(--bui-space-3); } - .xs\:bui-mt-4 { + .bui-mt-4 { margin-top: var(--bui-space-4); } - .xs\:bui-mt-5 { + .bui-mt-5 { margin-top: var(--bui-space-5); } - .xs\:bui-mt-6 { + .bui-mt-6 { margin-top: var(--bui-space-6); } - .xs\:bui-mt-7 { + .bui-mt-7 { margin-top: var(--bui-space-7); } - .xs\:bui-mt-8 { + .bui-mt-8 { margin-top: var(--bui-space-8); } - .xs\:bui-mt-9 { + .bui-mt-9 { margin-top: var(--bui-space-9); } - .xs\:bui-mt-10 { + .bui-mt-10 { margin-top: var(--bui-space-10); } - .xs\:bui-mt-11 { + .bui-mt-11 { margin-top: var(--bui-space-11); } - .xs\:bui-mt-12 { + .bui-mt-12 { margin-top: var(--bui-space-12); } - .xs\:bui-mt-13 { + .bui-mt-13 { margin-top: var(--bui-space-13); } - .xs\:bui-mt-14 { + .bui-mt-14 { margin-top: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-mt { - margin-top: var(--pt-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-mt { + margin-top: var(--pt-xs); + } + + .xs\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .xs\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .xs\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .xs\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .xs\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .xs\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .xs\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .xs\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .xs\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .xs\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .xs\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .xs\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .xs\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .xs\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .xs\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .xs\:bui-mt-14 { + margin-top: var(--bui-space-14); + } } - .sm\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-mt { + margin-top: var(--pt-sm); + } + + .sm\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .sm\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .sm\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .sm\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .sm\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .sm\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .sm\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .sm\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .sm\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .sm\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .sm\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .sm\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .sm\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .sm\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .sm\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .sm\:bui-mt-14 { + margin-top: var(--bui-space-14); + } } - .sm\:bui-mt-1 { - margin-top: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-mt { + margin-top: var(--pt-md); + } + + .md\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .md\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .md\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .md\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .md\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .md\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .md\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .md\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .md\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .md\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .md\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .md\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .md\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .md\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .md\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .md\:bui-mt-14 { + margin-top: var(--bui-space-14); + } } - .sm\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-mt { + margin-top: var(--pt-lg); + } + + .lg\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .lg\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .lg\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .lg\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .lg\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .lg\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .lg\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .lg\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .lg\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .lg\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .lg\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .lg\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .lg\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .lg\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .lg\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .lg\:bui-mt-14 { + margin-top: var(--bui-space-14); + } } - .sm\:bui-mt-2 { - margin-top: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-mt { + margin-top: var(--pt-xl); + } - .sm\:bui-mt-3 { - margin-top: var(--bui-space-3); - } + .xl\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } - .sm\:bui-mt-4 { - margin-top: var(--bui-space-4); - } + .xl\:bui-mt-1 { + margin-top: var(--bui-space-1); + } - .sm\:bui-mt-5 { - margin-top: var(--bui-space-5); - } + .xl\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } - .sm\:bui-mt-6 { - margin-top: var(--bui-space-6); - } + .xl\:bui-mt-2 { + margin-top: var(--bui-space-2); + } - .sm\:bui-mt-7 { - margin-top: var(--bui-space-7); - } + .xl\:bui-mt-3 { + margin-top: var(--bui-space-3); + } - .sm\:bui-mt-8 { - margin-top: var(--bui-space-8); - } + .xl\:bui-mt-4 { + margin-top: var(--bui-space-4); + } - .sm\:bui-mt-9 { - margin-top: var(--bui-space-9); - } + .xl\:bui-mt-5 { + margin-top: var(--bui-space-5); + } - .sm\:bui-mt-10 { - margin-top: var(--bui-space-10); - } + .xl\:bui-mt-6 { + margin-top: var(--bui-space-6); + } - .sm\:bui-mt-11 { - margin-top: var(--bui-space-11); - } + .xl\:bui-mt-7 { + margin-top: var(--bui-space-7); + } - .sm\:bui-mt-12 { - margin-top: var(--bui-space-12); - } + .xl\:bui-mt-8 { + margin-top: var(--bui-space-8); + } - .sm\:bui-mt-13 { - margin-top: var(--bui-space-13); - } + .xl\:bui-mt-9 { + margin-top: var(--bui-space-9); + } - .sm\:bui-mt-14 { - margin-top: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-mt { - margin-top: var(--pt-md); - } - - .md\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); - } - - .md\:bui-mt-1 { - margin-top: var(--bui-space-1); - } - - .md\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); - } - - .md\:bui-mt-2 { - margin-top: var(--bui-space-2); - } - - .md\:bui-mt-3 { - margin-top: var(--bui-space-3); - } - - .md\:bui-mt-4 { - margin-top: var(--bui-space-4); - } - - .md\:bui-mt-5 { - margin-top: var(--bui-space-5); - } - - .md\:bui-mt-6 { - margin-top: var(--bui-space-6); - } - - .md\:bui-mt-7 { - margin-top: var(--bui-space-7); - } - - .md\:bui-mt-8 { - margin-top: var(--bui-space-8); - } - - .md\:bui-mt-9 { - margin-top: var(--bui-space-9); - } - - .md\:bui-mt-10 { - margin-top: var(--bui-space-10); - } - - .md\:bui-mt-11 { - margin-top: var(--bui-space-11); - } - - .md\:bui-mt-12 { - margin-top: var(--bui-space-12); - } - - .md\:bui-mt-13 { - margin-top: var(--bui-space-13); - } - - .md\:bui-mt-14 { - margin-top: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-mt { - margin-top: var(--pt-lg); - } - - .lg\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); - } - - .lg\:bui-mt-1 { - margin-top: var(--bui-space-1); - } - - .lg\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); - } - - .lg\:bui-mt-2 { - margin-top: var(--bui-space-2); - } - - .lg\:bui-mt-3 { - margin-top: var(--bui-space-3); - } - - .lg\:bui-mt-4 { - margin-top: var(--bui-space-4); - } - - .lg\:bui-mt-5 { - margin-top: var(--bui-space-5); - } - - .lg\:bui-mt-6 { - margin-top: var(--bui-space-6); - } - - .lg\:bui-mt-7 { - margin-top: var(--bui-space-7); - } - - .lg\:bui-mt-8 { - margin-top: var(--bui-space-8); - } - - .lg\:bui-mt-9 { - margin-top: var(--bui-space-9); - } - - .lg\:bui-mt-10 { - margin-top: var(--bui-space-10); - } - - .lg\:bui-mt-11 { - margin-top: var(--bui-space-11); - } - - .lg\:bui-mt-12 { - margin-top: var(--bui-space-12); - } - - .lg\:bui-mt-13 { - margin-top: var(--bui-space-13); - } - - .lg\:bui-mt-14 { - margin-top: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-mt { - margin-top: var(--pt-xl); - } - - .xl\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); - } - - .xl\:bui-mt-1 { - margin-top: var(--bui-space-1); - } - - .xl\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); - } - - .xl\:bui-mt-2 { - margin-top: var(--bui-space-2); - } - - .xl\:bui-mt-3 { - margin-top: var(--bui-space-3); - } - - .xl\:bui-mt-4 { - margin-top: var(--bui-space-4); - } - - .xl\:bui-mt-5 { - margin-top: var(--bui-space-5); - } - - .xl\:bui-mt-6 { - margin-top: var(--bui-space-6); - } - - .xl\:bui-mt-7 { - margin-top: var(--bui-space-7); - } - - .xl\:bui-mt-8 { - margin-top: var(--bui-space-8); - } - - .xl\:bui-mt-9 { - margin-top: var(--bui-space-9); - } - - .xl\:bui-mt-10 { - margin-top: var(--bui-space-10); - } - - .xl\:bui-mt-11 { - margin-top: var(--bui-space-11); - } - - .xl\:bui-mt-12 { - margin-top: var(--bui-space-12); - } - - .xl\:bui-mt-13 { - margin-top: var(--bui-space-13); - } - - .xl\:bui-mt-14 { - margin-top: var(--bui-space-14); + .xl\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .xl\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .xl\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .xl\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .xl\:bui-mt-14 { + margin-top: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/mx.css b/packages/ui/src/css/utilities/mx.css index 36bdf32796..4898fc2352 100644 --- a/packages/ui/src/css/utilities/mx.css +++ b/packages/ui/src/css/utilities/mx.css @@ -1,524 +1,542 @@ -.bui-mx { - margin-left: var(--mx); - margin-right: var(--mx); -} +/* + * 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. + */ -.bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); -} - -.bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); -} - -.bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); -} - -.bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); -} - -.bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); -} - -.bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); -} - -.bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); -} - -.bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); -} - -.bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); -} - -.bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); -} - -.bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); -} - -.bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); -} - -.bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); -} - -.bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); -} - -.bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); -} - -.bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-mx { - margin-left: var(--px-xs); - margin-right: var(--px-xs); +@layer utilities { + .bui-mx { + margin-left: var(--mx); + margin-right: var(--mx); } - .xs\:bui-mx-0\.5 { + .bui-mx-0\.5 { margin-left: var(--bui-space-0_5); margin-right: var(--bui-space-0_5); } - .xs\:bui-mx-1 { + .bui-mx-1 { margin-left: var(--bui-space-1); margin-right: var(--bui-space-1); } - .xs\:bui-mx-1\.5 { + .bui-mx-1\.5 { margin-left: var(--bui-space-1_5); margin-right: var(--bui-space-1_5); } - .xs\:bui-mx-2 { + .bui-mx-2 { margin-left: var(--bui-space-2); margin-right: var(--bui-space-2); } - .xs\:bui-mx-3 { + .bui-mx-3 { margin-left: var(--bui-space-3); margin-right: var(--bui-space-3); } - .xs\:bui-mx-4 { + .bui-mx-4 { margin-left: var(--bui-space-4); margin-right: var(--bui-space-4); } - .xs\:bui-mx-5 { + .bui-mx-5 { margin-left: var(--bui-space-5); margin-right: var(--bui-space-5); } - .xs\:bui-mx-6 { + .bui-mx-6 { margin-left: var(--bui-space-6); margin-right: var(--bui-space-6); } - .xs\:bui-mx-7 { + .bui-mx-7 { margin-left: var(--bui-space-7); margin-right: var(--bui-space-7); } - .xs\:bui-mx-8 { + .bui-mx-8 { margin-left: var(--bui-space-8); margin-right: var(--bui-space-8); } - .xs\:bui-mx-9 { + .bui-mx-9 { margin-left: var(--bui-space-9); margin-right: var(--bui-space-9); } - .xs\:bui-mx-10 { + .bui-mx-10 { margin-left: var(--bui-space-10); margin-right: var(--bui-space-10); } - .xs\:bui-mx-11 { + .bui-mx-11 { margin-left: var(--bui-space-11); margin-right: var(--bui-space-11); } - .xs\:bui-mx-12 { + .bui-mx-12 { margin-left: var(--bui-space-12); margin-right: var(--bui-space-12); } - .xs\:bui-mx-13 { + .bui-mx-13 { margin-left: var(--bui-space-13); margin-right: var(--bui-space-13); } - .xs\:bui-mx-14 { + .bui-mx-14 { margin-left: var(--bui-space-14); margin-right: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-mx { - margin-left: var(--px-sm); - margin-right: var(--px-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-mx { + margin-left: var(--px-xs); + margin-right: var(--px-xs); + } + + .xs\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .xs\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .xs\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .xs\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .xs\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .xs\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .xs\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .xs\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .xs\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .xs\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .xs\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .xs\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .xs\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .xs\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .xs\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .xs\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } } - .sm\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-mx { + margin-left: var(--px-sm); + margin-right: var(--px-sm); + } + + .sm\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .sm\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .sm\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .sm\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .sm\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .sm\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .sm\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .sm\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .sm\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .sm\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .sm\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .sm\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .sm\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .sm\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .sm\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .sm\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } } - .sm\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-mx { + margin-left: var(--px-md); + margin-right: var(--px-md); + } + + .md\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .md\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .md\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .md\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .md\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .md\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .md\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .md\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .md\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .md\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .md\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .md\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .md\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .md\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .md\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .md\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } } - .sm\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-mx { + margin-left: var(--px-lg); + margin-right: var(--px-lg); + } + + .lg\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .lg\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .lg\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .lg\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .lg\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .lg\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .lg\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .lg\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .lg\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .lg\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .lg\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .lg\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .lg\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .lg\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .lg\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .lg\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } } - .sm\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-mx { + margin-left: var(--px-xl); + margin-right: var(--px-xl); + } - .sm\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } + .xl\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } - .sm\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } + .xl\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } - .sm\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } + .xl\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } - .sm\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } + .xl\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } - .sm\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } + .xl\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } - .sm\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } + .xl\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } - .sm\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } + .xl\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } - .sm\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } + .xl\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } - .sm\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } + .xl\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } - .sm\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } + .xl\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } - .sm\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } + .xl\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } - .sm\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-mx { - margin-left: var(--px-md); - margin-right: var(--px-md); - } - - .md\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); - } - - .md\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); - } - - .md\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); - } - - .md\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } - - .md\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } - - .md\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } - - .md\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } - - .md\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } - - .md\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } - - .md\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } - - .md\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } - - .md\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } - - .md\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } - - .md\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } - - .md\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } - - .md\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-mx { - margin-left: var(--px-lg); - margin-right: var(--px-lg); - } - - .lg\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); - } - - .lg\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); - } - - .lg\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); - } - - .lg\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } - - .lg\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } - - .lg\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } - - .lg\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } - - .lg\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } - - .lg\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } - - .lg\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } - - .lg\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } - - .lg\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } - - .lg\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } - - .lg\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } - - .lg\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } - - .lg\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-mx { - margin-left: var(--px-xl); - margin-right: var(--px-xl); - } - - .xl\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); - } - - .xl\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); - } - - .xl\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); - } - - .xl\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } - - .xl\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } - - .xl\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } - - .xl\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } - - .xl\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } - - .xl\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } - - .xl\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } - - .xl\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } - - .xl\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } - - .xl\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } - - .xl\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } - - .xl\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } - - .xl\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); + .xl\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .xl\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .xl\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .xl\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .xl\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/my.css b/packages/ui/src/css/utilities/my.css index ab3aadf77e..a165ad478e 100644 --- a/packages/ui/src/css/utilities/my.css +++ b/packages/ui/src/css/utilities/my.css @@ -1,524 +1,542 @@ -.bui-my { - margin-top: var(--my); - margin-bottom: var(--my); -} +/* + * 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. + */ -.bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); -} - -.bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); -} - -.bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); -} - -.bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); -} - -.bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); -} - -.bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); -} - -.bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); -} - -.bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); -} - -.bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); -} - -.bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); -} - -.bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); -} - -.bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); -} - -.bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); -} - -.bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); -} - -.bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); -} - -.bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-my { - margin-top: var(--py-xs); - margin-bottom: var(--py-xs); +@layer utilities { + .bui-my { + margin-top: var(--my); + margin-bottom: var(--my); } - .xs\:bui-my-0\.5 { + .bui-my-0\.5 { margin-top: var(--bui-space-0_5); margin-bottom: var(--bui-space-0_5); } - .xs\:bui-my-1 { + .bui-my-1 { margin-top: var(--bui-space-1); margin-bottom: var(--bui-space-1); } - .xs\:bui-my-1\.5 { + .bui-my-1\.5 { margin-top: var(--bui-space-1_5); margin-bottom: var(--bui-space-1_5); } - .xs\:bui-my-2 { + .bui-my-2 { margin-top: var(--bui-space-2); margin-bottom: var(--bui-space-2); } - .xs\:bui-my-3 { + .bui-my-3 { margin-top: var(--bui-space-3); margin-bottom: var(--bui-space-3); } - .xs\:bui-my-4 { + .bui-my-4 { margin-top: var(--bui-space-4); margin-bottom: var(--bui-space-4); } - .xs\:bui-my-5 { + .bui-my-5 { margin-top: var(--bui-space-5); margin-bottom: var(--bui-space-5); } - .xs\:bui-my-6 { + .bui-my-6 { margin-top: var(--bui-space-6); margin-bottom: var(--bui-space-6); } - .xs\:bui-my-7 { + .bui-my-7 { margin-top: var(--bui-space-7); margin-bottom: var(--bui-space-7); } - .xs\:bui-my-8 { + .bui-my-8 { margin-top: var(--bui-space-8); margin-bottom: var(--bui-space-8); } - .xs\:bui-my-9 { + .bui-my-9 { margin-top: var(--bui-space-9); margin-bottom: var(--bui-space-9); } - .xs\:bui-my-10 { + .bui-my-10 { margin-top: var(--bui-space-10); margin-bottom: var(--bui-space-10); } - .xs\:bui-my-11 { + .bui-my-11 { margin-top: var(--bui-space-11); margin-bottom: var(--bui-space-11); } - .xs\:bui-my-12 { + .bui-my-12 { margin-top: var(--bui-space-12); margin-bottom: var(--bui-space-12); } - .xs\:bui-my-13 { + .bui-my-13 { margin-top: var(--bui-space-13); margin-bottom: var(--bui-space-13); } - .xs\:bui-my-14 { + .bui-my-14 { margin-top: var(--bui-space-14); margin-bottom: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-my { - margin-top: var(--py-sm); - margin-bottom: var(--py-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-my { + margin-top: var(--py-xs); + margin-bottom: var(--py-xs); + } + + .xs\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .xs\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .xs\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .xs\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .xs\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .xs\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .xs\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .xs\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .xs\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .xs\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .xs\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .xs\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .xs\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .xs\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .xs\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .xs\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } } - .sm\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-my { + margin-top: var(--py-sm); + margin-bottom: var(--py-sm); + } + + .sm\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .sm\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .sm\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .sm\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .sm\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .sm\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .sm\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .sm\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .sm\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .sm\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .sm\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .sm\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .sm\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .sm\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .sm\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .sm\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } } - .sm\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-my { + margin-top: var(--py-md); + margin-bottom: var(--py-md); + } + + .md\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .md\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .md\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .md\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .md\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .md\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .md\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .md\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .md\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .md\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .md\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .md\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .md\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .md\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .md\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .md\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } } - .sm\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-my { + margin-top: var(--py-lg); + margin-bottom: var(--py-lg); + } + + .lg\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .lg\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .lg\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .lg\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .lg\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .lg\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .lg\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .lg\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .lg\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .lg\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .lg\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .lg\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .lg\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .lg\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .lg\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .lg\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } } - .sm\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-my { + margin-top: var(--py-xl); + margin-bottom: var(--py-xl); + } - .sm\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } + .xl\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } - .sm\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } + .xl\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } - .sm\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } + .xl\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } - .sm\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } + .xl\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } - .sm\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } + .xl\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } - .sm\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } + .xl\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } - .sm\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } + .xl\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } - .sm\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } + .xl\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } - .sm\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } + .xl\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } - .sm\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } + .xl\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } - .sm\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } + .xl\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } - .sm\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-my { - margin-top: var(--py-md); - margin-bottom: var(--py-md); - } - - .md\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); - } - - .md\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); - } - - .md\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); - } - - .md\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } - - .md\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } - - .md\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } - - .md\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } - - .md\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } - - .md\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } - - .md\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } - - .md\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } - - .md\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } - - .md\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } - - .md\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } - - .md\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } - - .md\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-my { - margin-top: var(--py-lg); - margin-bottom: var(--py-lg); - } - - .lg\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); - } - - .lg\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); - } - - .lg\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); - } - - .lg\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } - - .lg\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } - - .lg\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } - - .lg\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } - - .lg\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } - - .lg\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } - - .lg\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } - - .lg\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } - - .lg\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } - - .lg\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } - - .lg\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } - - .lg\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } - - .lg\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-my { - margin-top: var(--py-xl); - margin-bottom: var(--py-xl); - } - - .xl\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); - } - - .xl\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); - } - - .xl\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); - } - - .xl\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } - - .xl\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } - - .xl\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } - - .xl\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } - - .xl\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } - - .xl\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } - - .xl\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } - - .xl\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } - - .xl\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } - - .xl\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } - - .xl\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } - - .xl\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } - - .xl\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); + .xl\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .xl\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .xl\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .xl\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .xl\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/p.css b/packages/ui/src/css/utilities/p.css index 113f10777e..27713d9662 100644 --- a/packages/ui/src/css/utilities/p.css +++ b/packages/ui/src/css/utilities/p.css @@ -1,422 +1,440 @@ -.bui-p { - padding: var(--p); -} +/* + * 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. + */ -.bui-p-0\.5 { - padding: var(--bui-space-0_5); -} - -.bui-p-1 { - padding: var(--bui-space-1); -} - -.bui-p-1\.5 { - padding: var(--bui-space-1_5); -} - -.bui-p-2 { - padding: var(--bui-space-2); -} - -.bui-p-3 { - padding: var(--bui-space-3); -} - -.bui-p-4 { - padding: var(--bui-space-4); -} - -.bui-p-5 { - padding: var(--bui-space-5); -} - -.bui-p-6 { - padding: var(--bui-space-6); -} - -.bui-p-7 { - padding: var(--bui-space-7); -} - -.bui-p-8 { - padding: var(--bui-space-8); -} - -.bui-p-9 { - padding: var(--bui-space-9); -} - -.bui-p-10 { - padding: var(--bui-space-10); -} - -.bui-p-11 { - padding: var(--bui-space-11); -} - -.bui-p-12 { - padding: var(--bui-space-12); -} - -.bui-p-13 { - padding: var(--bui-space-13); -} - -.bui-p-14 { - padding: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-p { - padding: var(--p-xs); +@layer utilities { + .bui-p { + padding: var(--p); } - .xs\:bui-p-0\.5 { + .bui-p-0\.5 { padding: var(--bui-space-0_5); } - .xs\:bui-p-1 { + .bui-p-1 { padding: var(--bui-space-1); } - .xs\:bui-p-1\.5 { + .bui-p-1\.5 { padding: var(--bui-space-1_5); } - .xs\:bui-p-2 { + .bui-p-2 { padding: var(--bui-space-2); } - .xs\:bui-p-3 { + .bui-p-3 { padding: var(--bui-space-3); } - .xs\:bui-p-4 { + .bui-p-4 { padding: var(--bui-space-4); } - .xs\:bui-p-5 { + .bui-p-5 { padding: var(--bui-space-5); } - .xs\:bui-p-6 { + .bui-p-6 { padding: var(--bui-space-6); } - .xs\:bui-p-7 { + .bui-p-7 { padding: var(--bui-space-7); } - .xs\:bui-p-8 { + .bui-p-8 { padding: var(--bui-space-8); } - .xs\:bui-p-9 { + .bui-p-9 { padding: var(--bui-space-9); } - .xs\:bui-p-10 { + .bui-p-10 { padding: var(--bui-space-10); } - .xs\:bui-p-11 { + .bui-p-11 { padding: var(--bui-space-11); } - .xs\:bui-p-12 { + .bui-p-12 { padding: var(--bui-space-12); } - .xs\:bui-p-13 { + .bui-p-13 { padding: var(--bui-space-13); } - .xs\:bui-p-14 { + .bui-p-14 { padding: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-p { - padding: var(--p-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-p { + padding: var(--p-xs); + } + + .xs\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } + + .xs\:bui-p-1 { + padding: var(--bui-space-1); + } + + .xs\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .xs\:bui-p-2 { + padding: var(--bui-space-2); + } + + .xs\:bui-p-3 { + padding: var(--bui-space-3); + } + + .xs\:bui-p-4 { + padding: var(--bui-space-4); + } + + .xs\:bui-p-5 { + padding: var(--bui-space-5); + } + + .xs\:bui-p-6 { + padding: var(--bui-space-6); + } + + .xs\:bui-p-7 { + padding: var(--bui-space-7); + } + + .xs\:bui-p-8 { + padding: var(--bui-space-8); + } + + .xs\:bui-p-9 { + padding: var(--bui-space-9); + } + + .xs\:bui-p-10 { + padding: var(--bui-space-10); + } + + .xs\:bui-p-11 { + padding: var(--bui-space-11); + } + + .xs\:bui-p-12 { + padding: var(--bui-space-12); + } + + .xs\:bui-p-13 { + padding: var(--bui-space-13); + } + + .xs\:bui-p-14 { + padding: var(--bui-space-14); + } } - .sm\:bui-p-0\.5 { - padding: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-p { + padding: var(--p-sm); + } + + .sm\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } + + .sm\:bui-p-1 { + padding: var(--bui-space-1); + } + + .sm\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .sm\:bui-p-2 { + padding: var(--bui-space-2); + } + + .sm\:bui-p-3 { + padding: var(--bui-space-3); + } + + .sm\:bui-p-4 { + padding: var(--bui-space-4); + } + + .sm\:bui-p-5 { + padding: var(--bui-space-5); + } + + .sm\:bui-p-6 { + padding: var(--bui-space-6); + } + + .sm\:bui-p-7 { + padding: var(--bui-space-7); + } + + .sm\:bui-p-8 { + padding: var(--bui-space-8); + } + + .sm\:bui-p-9 { + padding: var(--bui-space-9); + } + + .sm\:bui-p-10 { + padding: var(--bui-space-10); + } + + .sm\:bui-p-11 { + padding: var(--bui-space-11); + } + + .sm\:bui-p-12 { + padding: var(--bui-space-12); + } + + .sm\:bui-p-13 { + padding: var(--bui-space-13); + } + + .sm\:bui-p-14 { + padding: var(--bui-space-14); + } } - .sm\:bui-p-1 { - padding: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-p { + padding: var(--p-md); + } + + .md\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } + + .md\:bui-p-1 { + padding: var(--bui-space-1); + } + + .md\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .md\:bui-p-2 { + padding: var(--bui-space-2); + } + + .md\:bui-p-3 { + padding: var(--bui-space-3); + } + + .md\:bui-p-4 { + padding: var(--bui-space-4); + } + + .md\:bui-p-5 { + padding: var(--bui-space-5); + } + + .md\:bui-p-6 { + padding: var(--bui-space-6); + } + + .md\:bui-p-7 { + padding: var(--bui-space-7); + } + + .md\:bui-p-8 { + padding: var(--bui-space-8); + } + + .md\:bui-p-9 { + padding: var(--bui-space-9); + } + + .md\:bui-p-10 { + padding: var(--bui-space-10); + } + + .md\:bui-p-11 { + padding: var(--bui-space-11); + } + + .md\:bui-p-12 { + padding: var(--bui-space-12); + } + + .md\:bui-p-13 { + padding: var(--bui-space-13); + } + + .md\:bui-p-14 { + padding: var(--bui-space-14); + } } - .sm\:bui-p-1\.5 { - padding: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-p { + padding: var(--p-lg); + } + + .lg\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } + + .lg\:bui-p-1 { + padding: var(--bui-space-1); + } + + .lg\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .lg\:bui-p-2 { + padding: var(--bui-space-2); + } + + .lg\:bui-p-3 { + padding: var(--bui-space-3); + } + + .lg\:bui-p-4 { + padding: var(--bui-space-4); + } + + .lg\:bui-p-5 { + padding: var(--bui-space-5); + } + + .lg\:bui-p-6 { + padding: var(--bui-space-6); + } + + .lg\:bui-p-7 { + padding: var(--bui-space-7); + } + + .lg\:bui-p-8 { + padding: var(--bui-space-8); + } + + .lg\:bui-p-9 { + padding: var(--bui-space-9); + } + + .lg\:bui-p-10 { + padding: var(--bui-space-10); + } + + .lg\:bui-p-11 { + padding: var(--bui-space-11); + } + + .lg\:bui-p-12 { + padding: var(--bui-space-12); + } + + .lg\:bui-p-13 { + padding: var(--bui-space-13); + } + + .lg\:bui-p-14 { + padding: var(--bui-space-14); + } } - .sm\:bui-p-2 { - padding: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-p { + padding: var(--p-xl); + } - .sm\:bui-p-3 { - padding: var(--bui-space-3); - } + .xl\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } - .sm\:bui-p-4 { - padding: var(--bui-space-4); - } + .xl\:bui-p-1 { + padding: var(--bui-space-1); + } - .sm\:bui-p-5 { - padding: var(--bui-space-5); - } + .xl\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } - .sm\:bui-p-6 { - padding: var(--bui-space-6); - } + .xl\:bui-p-2 { + padding: var(--bui-space-2); + } - .sm\:bui-p-7 { - padding: var(--bui-space-7); - } + .xl\:bui-p-3 { + padding: var(--bui-space-3); + } - .sm\:bui-p-8 { - padding: var(--bui-space-8); - } + .xl\:bui-p-4 { + padding: var(--bui-space-4); + } - .sm\:bui-p-9 { - padding: var(--bui-space-9); - } + .xl\:bui-p-5 { + padding: var(--bui-space-5); + } - .sm\:bui-p-10 { - padding: var(--bui-space-10); - } + .xl\:bui-p-6 { + padding: var(--bui-space-6); + } - .sm\:bui-p-11 { - padding: var(--bui-space-11); - } + .xl\:bui-p-7 { + padding: var(--bui-space-7); + } - .sm\:bui-p-12 { - padding: var(--bui-space-12); - } + .xl\:bui-p-8 { + padding: var(--bui-space-8); + } - .sm\:bui-p-13 { - padding: var(--bui-space-13); - } + .xl\:bui-p-9 { + padding: var(--bui-space-9); + } - .sm\:bui-p-14 { - padding: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-p { - padding: var(--p-md); - } - - .md\:bui-p-0\.5 { - padding: var(--bui-space-0_5); - } - - .md\:bui-p-1 { - padding: var(--bui-space-1); - } - - .md\:bui-p-1\.5 { - padding: var(--bui-space-1_5); - } - - .md\:bui-p-2 { - padding: var(--bui-space-2); - } - - .md\:bui-p-3 { - padding: var(--bui-space-3); - } - - .md\:bui-p-4 { - padding: var(--bui-space-4); - } - - .md\:bui-p-5 { - padding: var(--bui-space-5); - } - - .md\:bui-p-6 { - padding: var(--bui-space-6); - } - - .md\:bui-p-7 { - padding: var(--bui-space-7); - } - - .md\:bui-p-8 { - padding: var(--bui-space-8); - } - - .md\:bui-p-9 { - padding: var(--bui-space-9); - } - - .md\:bui-p-10 { - padding: var(--bui-space-10); - } - - .md\:bui-p-11 { - padding: var(--bui-space-11); - } - - .md\:bui-p-12 { - padding: var(--bui-space-12); - } - - .md\:bui-p-13 { - padding: var(--bui-space-13); - } - - .md\:bui-p-14 { - padding: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-p { - padding: var(--p-lg); - } - - .lg\:bui-p-0\.5 { - padding: var(--bui-space-0_5); - } - - .lg\:bui-p-1 { - padding: var(--bui-space-1); - } - - .lg\:bui-p-1\.5 { - padding: var(--bui-space-1_5); - } - - .lg\:bui-p-2 { - padding: var(--bui-space-2); - } - - .lg\:bui-p-3 { - padding: var(--bui-space-3); - } - - .lg\:bui-p-4 { - padding: var(--bui-space-4); - } - - .lg\:bui-p-5 { - padding: var(--bui-space-5); - } - - .lg\:bui-p-6 { - padding: var(--bui-space-6); - } - - .lg\:bui-p-7 { - padding: var(--bui-space-7); - } - - .lg\:bui-p-8 { - padding: var(--bui-space-8); - } - - .lg\:bui-p-9 { - padding: var(--bui-space-9); - } - - .lg\:bui-p-10 { - padding: var(--bui-space-10); - } - - .lg\:bui-p-11 { - padding: var(--bui-space-11); - } - - .lg\:bui-p-12 { - padding: var(--bui-space-12); - } - - .lg\:bui-p-13 { - padding: var(--bui-space-13); - } - - .lg\:bui-p-14 { - padding: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-p { - padding: var(--p-xl); - } - - .xl\:bui-p-0\.5 { - padding: var(--bui-space-0_5); - } - - .xl\:bui-p-1 { - padding: var(--bui-space-1); - } - - .xl\:bui-p-1\.5 { - padding: var(--bui-space-1_5); - } - - .xl\:bui-p-2 { - padding: var(--bui-space-2); - } - - .xl\:bui-p-3 { - padding: var(--bui-space-3); - } - - .xl\:bui-p-4 { - padding: var(--bui-space-4); - } - - .xl\:bui-p-5 { - padding: var(--bui-space-5); - } - - .xl\:bui-p-6 { - padding: var(--bui-space-6); - } - - .xl\:bui-p-7 { - padding: var(--bui-space-7); - } - - .xl\:bui-p-8 { - padding: var(--bui-space-8); - } - - .xl\:bui-p-9 { - padding: var(--bui-space-9); - } - - .xl\:bui-p-10 { - padding: var(--bui-space-10); - } - - .xl\:bui-p-11 { - padding: var(--bui-space-11); - } - - .xl\:bui-p-12 { - padding: var(--bui-space-12); - } - - .xl\:bui-p-13 { - padding: var(--bui-space-13); - } - - .xl\:bui-p-14 { - padding: var(--bui-space-14); + .xl\:bui-p-10 { + padding: var(--bui-space-10); + } + + .xl\:bui-p-11 { + padding: var(--bui-space-11); + } + + .xl\:bui-p-12 { + padding: var(--bui-space-12); + } + + .xl\:bui-p-13 { + padding: var(--bui-space-13); + } + + .xl\:bui-p-14 { + padding: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/pb.css b/packages/ui/src/css/utilities/pb.css index bdd3881f86..f32d284f37 100644 --- a/packages/ui/src/css/utilities/pb.css +++ b/packages/ui/src/css/utilities/pb.css @@ -1,422 +1,440 @@ -.bui-pb { - padding-bottom: var(--pb); -} +/* + * 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. + */ -.bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); -} - -.bui-pb-1 { - padding-bottom: var(--bui-space-1); -} - -.bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); -} - -.bui-pb-2 { - padding-bottom: var(--bui-space-2); -} - -.bui-pb-3 { - padding-bottom: var(--bui-space-3); -} - -.bui-pb-4 { - padding-bottom: var(--bui-space-4); -} - -.bui-pb-5 { - padding-bottom: var(--bui-space-5); -} - -.bui-pb-6 { - padding-bottom: var(--bui-space-6); -} - -.bui-pb-7 { - padding-bottom: var(--bui-space-7); -} - -.bui-pb-8 { - padding-bottom: var(--bui-space-8); -} - -.bui-pb-9 { - padding-bottom: var(--bui-space-9); -} - -.bui-pb-10 { - padding-bottom: var(--bui-space-10); -} - -.bui-pb-11 { - padding-bottom: var(--bui-space-11); -} - -.bui-pb-12 { - padding-bottom: var(--bui-space-12); -} - -.bui-pb-13 { - padding-bottom: var(--bui-space-13); -} - -.bui-pb-14 { - padding-bottom: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-pb { - padding-bottom: var(--pb-xs); +@layer utilities { + .bui-pb { + padding-bottom: var(--pb); } - .xs\:bui-pb-0\.5 { + .bui-pb-0\.5 { padding-bottom: var(--bui-space-0_5); } - .xs\:bui-pb-1 { + .bui-pb-1 { padding-bottom: var(--bui-space-1); } - .xs\:bui-pb-1\.5 { + .bui-pb-1\.5 { padding-bottom: var(--bui-space-1_5); } - .xs\:bui-pb-2 { + .bui-pb-2 { padding-bottom: var(--bui-space-2); } - .xs\:bui-pb-3 { + .bui-pb-3 { padding-bottom: var(--bui-space-3); } - .xs\:bui-pb-4 { + .bui-pb-4 { padding-bottom: var(--bui-space-4); } - .xs\:bui-pb-5 { + .bui-pb-5 { padding-bottom: var(--bui-space-5); } - .xs\:bui-pb-6 { + .bui-pb-6 { padding-bottom: var(--bui-space-6); } - .xs\:bui-pb-7 { + .bui-pb-7 { padding-bottom: var(--bui-space-7); } - .xs\:bui-pb-8 { + .bui-pb-8 { padding-bottom: var(--bui-space-8); } - .xs\:bui-pb-9 { + .bui-pb-9 { padding-bottom: var(--bui-space-9); } - .xs\:bui-pb-10 { + .bui-pb-10 { padding-bottom: var(--bui-space-10); } - .xs\:bui-pb-11 { + .bui-pb-11 { padding-bottom: var(--bui-space-11); } - .xs\:bui-pb-12 { + .bui-pb-12 { padding-bottom: var(--bui-space-12); } - .xs\:bui-pb-13 { + .bui-pb-13 { padding-bottom: var(--bui-space-13); } - .xs\:bui-pb-14 { + .bui-pb-14 { padding-bottom: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-pb { - padding-bottom: var(--pb-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-pb { + padding-bottom: var(--pb-xs); + } + + .xs\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .xs\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .xs\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .xs\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .xs\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .xs\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .xs\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .xs\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .xs\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .xs\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .xs\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .xs\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .xs\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .xs\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .xs\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .xs\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } } - .sm\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-pb { + padding-bottom: var(--pb-sm); + } + + .sm\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .sm\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .sm\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .sm\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .sm\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .sm\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .sm\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .sm\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .sm\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .sm\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .sm\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .sm\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .sm\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .sm\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .sm\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .sm\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } } - .sm\:bui-pb-1 { - padding-bottom: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-pb { + padding-bottom: var(--pb-md); + } + + .md\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .md\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .md\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .md\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .md\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .md\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .md\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .md\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .md\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .md\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .md\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .md\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .md\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .md\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .md\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .md\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } } - .sm\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-pb { + padding-bottom: var(--pb-lg); + } + + .lg\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .lg\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .lg\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .lg\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .lg\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .lg\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .lg\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .lg\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .lg\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .lg\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .lg\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .lg\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .lg\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .lg\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .lg\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .lg\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } } - .sm\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-pb { + padding-bottom: var(--pb-xl); + } - .sm\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } + .xl\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } - .sm\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } + .xl\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } - .sm\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } + .xl\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } - .sm\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } + .xl\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } - .sm\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } + .xl\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } - .sm\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } + .xl\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } - .sm\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } + .xl\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } - .sm\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } + .xl\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } - .sm\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } + .xl\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } - .sm\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } + .xl\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } - .sm\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } + .xl\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } - .sm\:bui-pb-14 { - padding-bottom: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-pb { - padding-bottom: var(--pb-md); - } - - .md\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); - } - - .md\:bui-pb-1 { - padding-bottom: var(--bui-space-1); - } - - .md\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); - } - - .md\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } - - .md\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } - - .md\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } - - .md\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } - - .md\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } - - .md\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } - - .md\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } - - .md\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } - - .md\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } - - .md\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } - - .md\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } - - .md\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } - - .md\:bui-pb-14 { - padding-bottom: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-pb { - padding-bottom: var(--pb-lg); - } - - .lg\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); - } - - .lg\:bui-pb-1 { - padding-bottom: var(--bui-space-1); - } - - .lg\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); - } - - .lg\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } - - .lg\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } - - .lg\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } - - .lg\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } - - .lg\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } - - .lg\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } - - .lg\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } - - .lg\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } - - .lg\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } - - .lg\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } - - .lg\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } - - .lg\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } - - .lg\:bui-pb-14 { - padding-bottom: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-pb { - padding-bottom: var(--pb-xl); - } - - .xl\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); - } - - .xl\:bui-pb-1 { - padding-bottom: var(--bui-space-1); - } - - .xl\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); - } - - .xl\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } - - .xl\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } - - .xl\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } - - .xl\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } - - .xl\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } - - .xl\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } - - .xl\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } - - .xl\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } - - .xl\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } - - .xl\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } - - .xl\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } - - .xl\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } - - .xl\:bui-pb-14 { - padding-bottom: var(--bui-space-14); + .xl\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .xl\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .xl\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .xl\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .xl\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/pl.css b/packages/ui/src/css/utilities/pl.css index 07e064293a..65bbfcf5e8 100644 --- a/packages/ui/src/css/utilities/pl.css +++ b/packages/ui/src/css/utilities/pl.css @@ -1,422 +1,440 @@ -.bui-pl { - padding-left: var(--pl); -} +/* + * 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. + */ -.bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); -} - -.bui-pl-1 { - padding-left: var(--bui-space-1); -} - -.bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); -} - -.bui-pl-2 { - padding-left: var(--bui-space-2); -} - -.bui-pl-3 { - padding-left: var(--bui-space-3); -} - -.bui-pl-4 { - padding-left: var(--bui-space-4); -} - -.bui-pl-5 { - padding-left: var(--bui-space-5); -} - -.bui-pl-6 { - padding-left: var(--bui-space-6); -} - -.bui-pl-7 { - padding-left: var(--bui-space-7); -} - -.bui-pl-8 { - padding-left: var(--bui-space-8); -} - -.bui-pl-9 { - padding-left: var(--bui-space-9); -} - -.bui-pl-10 { - padding-left: var(--bui-space-10); -} - -.bui-pl-11 { - padding-left: var(--bui-space-11); -} - -.bui-pl-12 { - padding-left: var(--bui-space-12); -} - -.bui-pl-13 { - padding-left: var(--bui-space-13); -} - -.bui-pl-14 { - padding-left: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-pl { - padding-left: var(--pl-xs); +@layer utilities { + .bui-pl { + padding-left: var(--pl); } - .xs\:bui-pl-0\.5 { + .bui-pl-0\.5 { padding-left: var(--bui-space-0_5); } - .xs\:bui-pl-1 { + .bui-pl-1 { padding-left: var(--bui-space-1); } - .xs\:bui-pl-1\.5 { + .bui-pl-1\.5 { padding-left: var(--bui-space-1_5); } - .xs\:bui-pl-2 { + .bui-pl-2 { padding-left: var(--bui-space-2); } - .xs\:bui-pl-3 { + .bui-pl-3 { padding-left: var(--bui-space-3); } - .xs\:bui-pl-4 { + .bui-pl-4 { padding-left: var(--bui-space-4); } - .xs\:bui-pl-5 { + .bui-pl-5 { padding-left: var(--bui-space-5); } - .xs\:bui-pl-6 { + .bui-pl-6 { padding-left: var(--bui-space-6); } - .xs\:bui-pl-7 { + .bui-pl-7 { padding-left: var(--bui-space-7); } - .xs\:bui-pl-8 { + .bui-pl-8 { padding-left: var(--bui-space-8); } - .xs\:bui-pl-9 { + .bui-pl-9 { padding-left: var(--bui-space-9); } - .xs\:bui-pl-10 { + .bui-pl-10 { padding-left: var(--bui-space-10); } - .xs\:bui-pl-11 { + .bui-pl-11 { padding-left: var(--bui-space-11); } - .xs\:bui-pl-12 { + .bui-pl-12 { padding-left: var(--bui-space-12); } - .xs\:bui-pl-13 { + .bui-pl-13 { padding-left: var(--bui-space-13); } - .xs\:bui-pl-14 { + .bui-pl-14 { padding-left: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-pl { - padding-left: var(--pl-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-pl { + padding-left: var(--pl-xs); + } + + .xs\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } + + .xs\:bui-pl-1 { + padding-left: var(--bui-space-1); + } + + .xs\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } + + .xs\:bui-pl-2 { + padding-left: var(--bui-space-2); + } + + .xs\:bui-pl-3 { + padding-left: var(--bui-space-3); + } + + .xs\:bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .xs\:bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .xs\:bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .xs\:bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .xs\:bui-pl-8 { + padding-left: var(--bui-space-8); + } + + .xs\:bui-pl-9 { + padding-left: var(--bui-space-9); + } + + .xs\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .xs\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .xs\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .xs\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .xs\:bui-pl-14 { + padding-left: var(--bui-space-14); + } } - .sm\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-pl { + padding-left: var(--pl-sm); + } + + .sm\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } + + .sm\:bui-pl-1 { + padding-left: var(--bui-space-1); + } + + .sm\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } + + .sm\:bui-pl-2 { + padding-left: var(--bui-space-2); + } + + .sm\:bui-pl-3 { + padding-left: var(--bui-space-3); + } + + .sm\:bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .sm\:bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .sm\:bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .sm\:bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .sm\:bui-pl-8 { + padding-left: var(--bui-space-8); + } + + .sm\:bui-pl-9 { + padding-left: var(--bui-space-9); + } + + .sm\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .sm\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .sm\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .sm\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .sm\:bui-pl-14 { + padding-left: var(--bui-space-14); + } } - .sm\:bui-pl-1 { - padding-left: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-pl { + padding-left: var(--pl-md); + } + + .md\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } + + .md\:bui-pl-1 { + padding-left: var(--bui-space-1); + } + + .md\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } + + .md\:bui-pl-2 { + padding-left: var(--bui-space-2); + } + + .md\:bui-pl-3 { + padding-left: var(--bui-space-3); + } + + .md\:bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .md\:bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .md\:bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .md\:bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .md\:bui-pl-8 { + padding-left: var(--bui-space-8); + } + + .md\:bui-pl-9 { + padding-left: var(--bui-space-9); + } + + .md\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .md\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .md\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .md\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .md\:bui-pl-14 { + padding-left: var(--bui-space-14); + } } - .sm\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-pl { + padding-left: var(--pl-lg); + } + + .lg\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } + + .lg\:bui-pl-1 { + padding-left: var(--bui-space-1); + } + + .lg\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } + + .lg\:bui-pl-2 { + padding-left: var(--bui-space-2); + } + + .lg\:bui-pl-3 { + padding-left: var(--bui-space-3); + } + + .lg\:bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .lg\:bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .lg\:bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .lg\:bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .lg\:bui-pl-8 { + padding-left: var(--bui-space-8); + } + + .lg\:bui-pl-9 { + padding-left: var(--bui-space-9); + } + + .lg\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .lg\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .lg\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .lg\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .lg\:bui-pl-14 { + padding-left: var(--bui-space-14); + } } - .sm\:bui-pl-2 { - padding-left: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-pl { + padding-left: var(--pl-xl); + } - .sm\:bui-pl-3 { - padding-left: var(--bui-space-3); - } + .xl\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } - .sm\:bui-pl-4 { - padding-left: var(--bui-space-4); - } + .xl\:bui-pl-1 { + padding-left: var(--bui-space-1); + } - .sm\:bui-pl-5 { - padding-left: var(--bui-space-5); - } + .xl\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } - .sm\:bui-pl-6 { - padding-left: var(--bui-space-6); - } + .xl\:bui-pl-2 { + padding-left: var(--bui-space-2); + } - .sm\:bui-pl-7 { - padding-left: var(--bui-space-7); - } + .xl\:bui-pl-3 { + padding-left: var(--bui-space-3); + } - .sm\:bui-pl-8 { - padding-left: var(--bui-space-8); - } + .xl\:bui-pl-4 { + padding-left: var(--bui-space-4); + } - .sm\:bui-pl-9 { - padding-left: var(--bui-space-9); - } + .xl\:bui-pl-5 { + padding-left: var(--bui-space-5); + } - .sm\:bui-pl-10 { - padding-left: var(--bui-space-10); - } + .xl\:bui-pl-6 { + padding-left: var(--bui-space-6); + } - .sm\:bui-pl-11 { - padding-left: var(--bui-space-11); - } + .xl\:bui-pl-7 { + padding-left: var(--bui-space-7); + } - .sm\:bui-pl-12 { - padding-left: var(--bui-space-12); - } + .xl\:bui-pl-8 { + padding-left: var(--bui-space-8); + } - .sm\:bui-pl-13 { - padding-left: var(--bui-space-13); - } + .xl\:bui-pl-9 { + padding-left: var(--bui-space-9); + } - .sm\:bui-pl-14 { - padding-left: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-pl { - padding-left: var(--pl-md); - } - - .md\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); - } - - .md\:bui-pl-1 { - padding-left: var(--bui-space-1); - } - - .md\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); - } - - .md\:bui-pl-2 { - padding-left: var(--bui-space-2); - } - - .md\:bui-pl-3 { - padding-left: var(--bui-space-3); - } - - .md\:bui-pl-4 { - padding-left: var(--bui-space-4); - } - - .md\:bui-pl-5 { - padding-left: var(--bui-space-5); - } - - .md\:bui-pl-6 { - padding-left: var(--bui-space-6); - } - - .md\:bui-pl-7 { - padding-left: var(--bui-space-7); - } - - .md\:bui-pl-8 { - padding-left: var(--bui-space-8); - } - - .md\:bui-pl-9 { - padding-left: var(--bui-space-9); - } - - .md\:bui-pl-10 { - padding-left: var(--bui-space-10); - } - - .md\:bui-pl-11 { - padding-left: var(--bui-space-11); - } - - .md\:bui-pl-12 { - padding-left: var(--bui-space-12); - } - - .md\:bui-pl-13 { - padding-left: var(--bui-space-13); - } - - .md\:bui-pl-14 { - padding-left: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-pl { - padding-left: var(--pl-lg); - } - - .lg\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); - } - - .lg\:bui-pl-1 { - padding-left: var(--bui-space-1); - } - - .lg\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); - } - - .lg\:bui-pl-2 { - padding-left: var(--bui-space-2); - } - - .lg\:bui-pl-3 { - padding-left: var(--bui-space-3); - } - - .lg\:bui-pl-4 { - padding-left: var(--bui-space-4); - } - - .lg\:bui-pl-5 { - padding-left: var(--bui-space-5); - } - - .lg\:bui-pl-6 { - padding-left: var(--bui-space-6); - } - - .lg\:bui-pl-7 { - padding-left: var(--bui-space-7); - } - - .lg\:bui-pl-8 { - padding-left: var(--bui-space-8); - } - - .lg\:bui-pl-9 { - padding-left: var(--bui-space-9); - } - - .lg\:bui-pl-10 { - padding-left: var(--bui-space-10); - } - - .lg\:bui-pl-11 { - padding-left: var(--bui-space-11); - } - - .lg\:bui-pl-12 { - padding-left: var(--bui-space-12); - } - - .lg\:bui-pl-13 { - padding-left: var(--bui-space-13); - } - - .lg\:bui-pl-14 { - padding-left: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-pl { - padding-left: var(--pl-xl); - } - - .xl\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); - } - - .xl\:bui-pl-1 { - padding-left: var(--bui-space-1); - } - - .xl\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); - } - - .xl\:bui-pl-2 { - padding-left: var(--bui-space-2); - } - - .xl\:bui-pl-3 { - padding-left: var(--bui-space-3); - } - - .xl\:bui-pl-4 { - padding-left: var(--bui-space-4); - } - - .xl\:bui-pl-5 { - padding-left: var(--bui-space-5); - } - - .xl\:bui-pl-6 { - padding-left: var(--bui-space-6); - } - - .xl\:bui-pl-7 { - padding-left: var(--bui-space-7); - } - - .xl\:bui-pl-8 { - padding-left: var(--bui-space-8); - } - - .xl\:bui-pl-9 { - padding-left: var(--bui-space-9); - } - - .xl\:bui-pl-10 { - padding-left: var(--bui-space-10); - } - - .xl\:bui-pl-11 { - padding-left: var(--bui-space-11); - } - - .xl\:bui-pl-12 { - padding-left: var(--bui-space-12); - } - - .xl\:bui-pl-13 { - padding-left: var(--bui-space-13); - } - - .xl\:bui-pl-14 { - padding-left: var(--bui-space-14); + .xl\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .xl\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .xl\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .xl\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .xl\:bui-pl-14 { + padding-left: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/position.css b/packages/ui/src/css/utilities/position.css index 11cc0994b6..307e25cc04 100644 --- a/packages/ui/src/css/utilities/position.css +++ b/packages/ui/src/css/utilities/position.css @@ -1,134 +1,152 @@ -.bui-position-absolute { - position: absolute; -} +/* + * 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. + */ -.bui-position-fixed { - position: fixed; -} - -.bui-position-sticky { - position: sticky; -} - -.bui-position-relative { - position: relative; -} - -.bui-position-static { - position: static; -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-position-absolute { +@layer utilities { + .bui-position-absolute { position: absolute; } - .xs\:bui-position-fixed { + .bui-position-fixed { position: fixed; } - .xs\:bui-position-sticky { + .bui-position-sticky { position: sticky; } - .xs\:bui-position-relative { + .bui-position-relative { position: relative; } - .xs\:bui-position-static { + .bui-position-static { position: static; } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-position-absolute { - position: absolute; + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-position-absolute { + position: absolute; + } + + .xs\:bui-position-fixed { + position: fixed; + } + + .xs\:bui-position-sticky { + position: sticky; + } + + .xs\:bui-position-relative { + position: relative; + } + + .xs\:bui-position-static { + position: static; + } } - .sm\:bui-position-fixed { - position: fixed; + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-position-absolute { + position: absolute; + } + + .sm\:bui-position-fixed { + position: fixed; + } + + .sm\:bui-position-sticky { + position: sticky; + } + + .sm\:bui-position-relative { + position: relative; + } + + .sm\:bui-position-static { + position: static; + } } - .sm\:bui-position-sticky { - position: sticky; + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-position-absolute { + position: absolute; + } + + .md\:bui-position-fixed { + position: fixed; + } + + .md\:bui-position-sticky { + position: sticky; + } + + .md\:bui-position-relative { + position: relative; + } + + .md\:bui-position-static { + position: static; + } } - .sm\:bui-position-relative { - position: relative; + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-position-absolute { + position: absolute; + } + + .lg\:bui-position-fixed { + position: fixed; + } + + .lg\:bui-position-sticky { + position: sticky; + } + + .lg\:bui-position-relative { + position: relative; + } + + .lg\:bui-position-static { + position: static; + } } - .sm\:bui-position-static { - position: static; - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-position-absolute { - position: absolute; - } - - .md\:bui-position-fixed { - position: fixed; - } - - .md\:bui-position-sticky { - position: sticky; - } - - .md\:bui-position-relative { - position: relative; - } - - .md\:bui-position-static { - position: static; - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-position-absolute { - position: absolute; - } - - .lg\:bui-position-fixed { - position: fixed; - } - - .lg\:bui-position-sticky { - position: sticky; - } - - .lg\:bui-position-relative { - position: relative; - } - - .lg\:bui-position-static { - position: static; - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-position-absolute { - position: absolute; - } - - .xl\:bui-position-fixed { - position: fixed; - } - - .xl\:bui-position-sticky { - position: sticky; - } - - .xl\:bui-position-relative { - position: relative; - } - - .xl\:bui-position-static { - position: static; + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-position-absolute { + position: absolute; + } + + .xl\:bui-position-fixed { + position: fixed; + } + + .xl\:bui-position-sticky { + position: sticky; + } + + .xl\:bui-position-relative { + position: relative; + } + + .xl\:bui-position-static { + position: static; + } } } diff --git a/packages/ui/src/css/utilities/pr.css b/packages/ui/src/css/utilities/pr.css index c6fa94a1c5..e228fe1c13 100644 --- a/packages/ui/src/css/utilities/pr.css +++ b/packages/ui/src/css/utilities/pr.css @@ -1,422 +1,440 @@ -.bui-pr { - padding-right: var(--pr); -} +/* + * 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. + */ -.bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); -} - -.bui-pr-1 { - padding-right: var(--bui-space-1); -} - -.bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); -} - -.bui-pr-2 { - padding-right: var(--bui-space-2); -} - -.bui-pr-3 { - padding-right: var(--bui-space-3); -} - -.bui-pr-4 { - padding-right: var(--bui-space-4); -} - -.bui-pr-5 { - padding-right: var(--bui-space-5); -} - -.bui-pr-6 { - padding-right: var(--bui-space-6); -} - -.bui-pr-7 { - padding-right: var(--bui-space-7); -} - -.bui-pr-8 { - padding-right: var(--bui-space-8); -} - -.bui-pr-9 { - padding-right: var(--bui-space-9); -} - -.bui-pr-10 { - padding-right: var(--bui-space-10); -} - -.bui-pr-11 { - padding-right: var(--bui-space-11); -} - -.bui-pr-12 { - padding-right: var(--bui-space-12); -} - -.bui-pr-13 { - padding-right: var(--bui-space-13); -} - -.bui-pr-14 { - padding-right: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-pr { - padding-right: var(--pr-xs); +@layer utilities { + .bui-pr { + padding-right: var(--pr); } - .xs\:bui-pr-0\.5 { + .bui-pr-0\.5 { padding-right: var(--bui-space-0_5); } - .xs\:bui-pr-1 { + .bui-pr-1 { padding-right: var(--bui-space-1); } - .xs\:bui-pr-1\.5 { + .bui-pr-1\.5 { padding-right: var(--bui-space-1_5); } - .xs\:bui-pr-2 { + .bui-pr-2 { padding-right: var(--bui-space-2); } - .xs\:bui-pr-3 { + .bui-pr-3 { padding-right: var(--bui-space-3); } - .xs\:bui-pr-4 { + .bui-pr-4 { padding-right: var(--bui-space-4); } - .xs\:bui-pr-5 { + .bui-pr-5 { padding-right: var(--bui-space-5); } - .xs\:bui-pr-6 { + .bui-pr-6 { padding-right: var(--bui-space-6); } - .xs\:bui-pr-7 { + .bui-pr-7 { padding-right: var(--bui-space-7); } - .xs\:bui-pr-8 { + .bui-pr-8 { padding-right: var(--bui-space-8); } - .xs\:bui-pr-9 { + .bui-pr-9 { padding-right: var(--bui-space-9); } - .xs\:bui-pr-10 { + .bui-pr-10 { padding-right: var(--bui-space-10); } - .xs\:bui-pr-11 { + .bui-pr-11 { padding-right: var(--bui-space-11); } - .xs\:bui-pr-12 { + .bui-pr-12 { padding-right: var(--bui-space-12); } - .xs\:bui-pr-13 { + .bui-pr-13 { padding-right: var(--bui-space-13); } - .xs\:bui-pr-14 { + .bui-pr-14 { padding-right: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-pr { - padding-right: var(--pr-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-pr { + padding-right: var(--pr-xs); + } + + .xs\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } + + .xs\:bui-pr-1 { + padding-right: var(--bui-space-1); + } + + .xs\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } + + .xs\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .xs\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .xs\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .xs\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .xs\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .xs\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .xs\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .xs\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .xs\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .xs\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .xs\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .xs\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .xs\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } - .sm\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-pr { + padding-right: var(--pr-sm); + } + + .sm\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } + + .sm\:bui-pr-1 { + padding-right: var(--bui-space-1); + } + + .sm\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } + + .sm\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .sm\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .sm\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .sm\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .sm\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .sm\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .sm\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .sm\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .sm\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .sm\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .sm\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .sm\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .sm\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } - .sm\:bui-pr-1 { - padding-right: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-pr { + padding-right: var(--pr-md); + } + + .md\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } + + .md\:bui-pr-1 { + padding-right: var(--bui-space-1); + } + + .md\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } + + .md\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .md\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .md\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .md\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .md\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .md\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .md\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .md\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .md\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .md\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .md\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .md\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .md\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } - .sm\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-pr { + padding-right: var(--pr-lg); + } + + .lg\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } + + .lg\:bui-pr-1 { + padding-right: var(--bui-space-1); + } + + .lg\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } + + .lg\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .lg\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .lg\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .lg\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .lg\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .lg\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .lg\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .lg\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .lg\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .lg\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .lg\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .lg\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .lg\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } - .sm\:bui-pr-2 { - padding-right: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-pr { + padding-right: var(--pr-xl); + } - .sm\:bui-pr-3 { - padding-right: var(--bui-space-3); - } + .xl\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } - .sm\:bui-pr-4 { - padding-right: var(--bui-space-4); - } + .xl\:bui-pr-1 { + padding-right: var(--bui-space-1); + } - .sm\:bui-pr-5 { - padding-right: var(--bui-space-5); - } + .xl\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } - .sm\:bui-pr-6 { - padding-right: var(--bui-space-6); - } + .xl\:bui-pr-2 { + padding-right: var(--bui-space-2); + } - .sm\:bui-pr-7 { - padding-right: var(--bui-space-7); - } + .xl\:bui-pr-3 { + padding-right: var(--bui-space-3); + } - .sm\:bui-pr-8 { - padding-right: var(--bui-space-8); - } + .xl\:bui-pr-4 { + padding-right: var(--bui-space-4); + } - .sm\:bui-pr-9 { - padding-right: var(--bui-space-9); - } + .xl\:bui-pr-5 { + padding-right: var(--bui-space-5); + } - .sm\:bui-pr-10 { - padding-right: var(--bui-space-10); - } + .xl\:bui-pr-6 { + padding-right: var(--bui-space-6); + } - .sm\:bui-pr-11 { - padding-right: var(--bui-space-11); - } + .xl\:bui-pr-7 { + padding-right: var(--bui-space-7); + } - .sm\:bui-pr-12 { - padding-right: var(--bui-space-12); - } + .xl\:bui-pr-8 { + padding-right: var(--bui-space-8); + } - .sm\:bui-pr-13 { - padding-right: var(--bui-space-13); - } + .xl\:bui-pr-9 { + padding-right: var(--bui-space-9); + } - .sm\:bui-pr-14 { - padding-right: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-pr { - padding-right: var(--pr-md); - } - - .md\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); - } - - .md\:bui-pr-1 { - padding-right: var(--bui-space-1); - } - - .md\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); - } - - .md\:bui-pr-2 { - padding-right: var(--bui-space-2); - } - - .md\:bui-pr-3 { - padding-right: var(--bui-space-3); - } - - .md\:bui-pr-4 { - padding-right: var(--bui-space-4); - } - - .md\:bui-pr-5 { - padding-right: var(--bui-space-5); - } - - .md\:bui-pr-6 { - padding-right: var(--bui-space-6); - } - - .md\:bui-pr-7 { - padding-right: var(--bui-space-7); - } - - .md\:bui-pr-8 { - padding-right: var(--bui-space-8); - } - - .md\:bui-pr-9 { - padding-right: var(--bui-space-9); - } - - .md\:bui-pr-10 { - padding-right: var(--bui-space-10); - } - - .md\:bui-pr-11 { - padding-right: var(--bui-space-11); - } - - .md\:bui-pr-12 { - padding-right: var(--bui-space-12); - } - - .md\:bui-pr-13 { - padding-right: var(--bui-space-13); - } - - .md\:bui-pr-14 { - padding-right: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-pr { - padding-right: var(--pr-lg); - } - - .lg\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); - } - - .lg\:bui-pr-1 { - padding-right: var(--bui-space-1); - } - - .lg\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); - } - - .lg\:bui-pr-2 { - padding-right: var(--bui-space-2); - } - - .lg\:bui-pr-3 { - padding-right: var(--bui-space-3); - } - - .lg\:bui-pr-4 { - padding-right: var(--bui-space-4); - } - - .lg\:bui-pr-5 { - padding-right: var(--bui-space-5); - } - - .lg\:bui-pr-6 { - padding-right: var(--bui-space-6); - } - - .lg\:bui-pr-7 { - padding-right: var(--bui-space-7); - } - - .lg\:bui-pr-8 { - padding-right: var(--bui-space-8); - } - - .lg\:bui-pr-9 { - padding-right: var(--bui-space-9); - } - - .lg\:bui-pr-10 { - padding-right: var(--bui-space-10); - } - - .lg\:bui-pr-11 { - padding-right: var(--bui-space-11); - } - - .lg\:bui-pr-12 { - padding-right: var(--bui-space-12); - } - - .lg\:bui-pr-13 { - padding-right: var(--bui-space-13); - } - - .lg\:bui-pr-14 { - padding-right: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-pr { - padding-right: var(--pr-xl); - } - - .xl\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); - } - - .xl\:bui-pr-1 { - padding-right: var(--bui-space-1); - } - - .xl\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); - } - - .xl\:bui-pr-2 { - padding-right: var(--bui-space-2); - } - - .xl\:bui-pr-3 { - padding-right: var(--bui-space-3); - } - - .xl\:bui-pr-4 { - padding-right: var(--bui-space-4); - } - - .xl\:bui-pr-5 { - padding-right: var(--bui-space-5); - } - - .xl\:bui-pr-6 { - padding-right: var(--bui-space-6); - } - - .xl\:bui-pr-7 { - padding-right: var(--bui-space-7); - } - - .xl\:bui-pr-8 { - padding-right: var(--bui-space-8); - } - - .xl\:bui-pr-9 { - padding-right: var(--bui-space-9); - } - - .xl\:bui-pr-10 { - padding-right: var(--bui-space-10); - } - - .xl\:bui-pr-11 { - padding-right: var(--bui-space-11); - } - - .xl\:bui-pr-12 { - padding-right: var(--bui-space-12); - } - - .xl\:bui-pr-13 { - padding-right: var(--bui-space-13); - } - - .xl\:bui-pr-14 { - padding-right: var(--bui-space-14); + .xl\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .xl\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .xl\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .xl\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .xl\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/pt.css b/packages/ui/src/css/utilities/pt.css index cf557257e3..f9f17c1afc 100644 --- a/packages/ui/src/css/utilities/pt.css +++ b/packages/ui/src/css/utilities/pt.css @@ -1,422 +1,440 @@ -.bui-pt { - padding-top: var(--pt); -} +/* + * 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. + */ -.bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); -} - -.bui-pt-1 { - padding-top: var(--bui-space-1); -} - -.bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); -} - -.bui-pt-2 { - padding-top: var(--bui-space-2); -} - -.bui-pt-3 { - padding-top: var(--bui-space-3); -} - -.bui-pt-4 { - padding-top: var(--bui-space-4); -} - -.bui-pt-5 { - padding-top: var(--bui-space-5); -} - -.bui-pt-6 { - padding-top: var(--bui-space-6); -} - -.bui-pt-7 { - padding-top: var(--bui-space-7); -} - -.bui-pt-8 { - padding-top: var(--bui-space-8); -} - -.bui-pt-9 { - padding-top: var(--bui-space-9); -} - -.bui-pt-10 { - padding-top: var(--bui-space-10); -} - -.bui-pt-11 { - padding-top: var(--bui-space-11); -} - -.bui-pt-12 { - padding-top: var(--bui-space-12); -} - -.bui-pt-13 { - padding-top: var(--bui-space-13); -} - -.bui-pt-14 { - padding-top: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-pt { - padding-top: var(--pt-xs); +@layer utilities { + .bui-pt { + padding-top: var(--pt); } - .xs\:bui-pt-0\.5 { + .bui-pt-0\.5 { padding-top: var(--bui-space-0_5); } - .xs\:bui-pt-1 { + .bui-pt-1 { padding-top: var(--bui-space-1); } - .xs\:bui-pt-1\.5 { + .bui-pt-1\.5 { padding-top: var(--bui-space-1_5); } - .xs\:bui-pt-2 { + .bui-pt-2 { padding-top: var(--bui-space-2); } - .xs\:bui-pt-3 { + .bui-pt-3 { padding-top: var(--bui-space-3); } - .xs\:bui-pt-4 { + .bui-pt-4 { padding-top: var(--bui-space-4); } - .xs\:bui-pt-5 { + .bui-pt-5 { padding-top: var(--bui-space-5); } - .xs\:bui-pt-6 { + .bui-pt-6 { padding-top: var(--bui-space-6); } - .xs\:bui-pt-7 { + .bui-pt-7 { padding-top: var(--bui-space-7); } - .xs\:bui-pt-8 { + .bui-pt-8 { padding-top: var(--bui-space-8); } - .xs\:bui-pt-9 { + .bui-pt-9 { padding-top: var(--bui-space-9); } - .xs\:bui-pt-10 { + .bui-pt-10 { padding-top: var(--bui-space-10); } - .xs\:bui-pt-11 { + .bui-pt-11 { padding-top: var(--bui-space-11); } - .xs\:bui-pt-12 { + .bui-pt-12 { padding-top: var(--bui-space-12); } - .xs\:bui-pt-13 { + .bui-pt-13 { padding-top: var(--bui-space-13); } - .xs\:bui-pt-14 { + .bui-pt-14 { padding-top: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-pt { - padding-top: var(--pt-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-pt { + padding-top: var(--pt-xs); + } + + .xs\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .xs\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .xs\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .xs\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .xs\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .xs\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .xs\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .xs\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .xs\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .xs\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .xs\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .xs\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .xs\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .xs\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .xs\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .xs\:bui-pt-14 { + padding-top: var(--bui-space-14); + } } - .sm\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-pt { + padding-top: var(--pt-sm); + } + + .sm\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .sm\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .sm\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .sm\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .sm\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .sm\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .sm\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .sm\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .sm\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .sm\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .sm\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .sm\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .sm\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .sm\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .sm\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .sm\:bui-pt-14 { + padding-top: var(--bui-space-14); + } } - .sm\:bui-pt-1 { - padding-top: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-pt { + padding-top: var(--pt-md); + } + + .md\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .md\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .md\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .md\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .md\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .md\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .md\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .md\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .md\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .md\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .md\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .md\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .md\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .md\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .md\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .md\:bui-pt-14 { + padding-top: var(--bui-space-14); + } } - .sm\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-pt { + padding-top: var(--pt-lg); + } + + .lg\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .lg\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .lg\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .lg\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .lg\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .lg\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .lg\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .lg\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .lg\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .lg\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .lg\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .lg\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .lg\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .lg\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .lg\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .lg\:bui-pt-14 { + padding-top: var(--bui-space-14); + } } - .sm\:bui-pt-2 { - padding-top: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-pt { + padding-top: var(--pt-xl); + } - .sm\:bui-pt-3 { - padding-top: var(--bui-space-3); - } + .xl\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } - .sm\:bui-pt-4 { - padding-top: var(--bui-space-4); - } + .xl\:bui-pt-1 { + padding-top: var(--bui-space-1); + } - .sm\:bui-pt-5 { - padding-top: var(--bui-space-5); - } + .xl\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } - .sm\:bui-pt-6 { - padding-top: var(--bui-space-6); - } + .xl\:bui-pt-2 { + padding-top: var(--bui-space-2); + } - .sm\:bui-pt-7 { - padding-top: var(--bui-space-7); - } + .xl\:bui-pt-3 { + padding-top: var(--bui-space-3); + } - .sm\:bui-pt-8 { - padding-top: var(--bui-space-8); - } + .xl\:bui-pt-4 { + padding-top: var(--bui-space-4); + } - .sm\:bui-pt-9 { - padding-top: var(--bui-space-9); - } + .xl\:bui-pt-5 { + padding-top: var(--bui-space-5); + } - .sm\:bui-pt-10 { - padding-top: var(--bui-space-10); - } + .xl\:bui-pt-6 { + padding-top: var(--bui-space-6); + } - .sm\:bui-pt-11 { - padding-top: var(--bui-space-11); - } + .xl\:bui-pt-7 { + padding-top: var(--bui-space-7); + } - .sm\:bui-pt-12 { - padding-top: var(--bui-space-12); - } + .xl\:bui-pt-8 { + padding-top: var(--bui-space-8); + } - .sm\:bui-pt-13 { - padding-top: var(--bui-space-13); - } + .xl\:bui-pt-9 { + padding-top: var(--bui-space-9); + } - .sm\:bui-pt-14 { - padding-top: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-pt { - padding-top: var(--pt-md); - } - - .md\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); - } - - .md\:bui-pt-1 { - padding-top: var(--bui-space-1); - } - - .md\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); - } - - .md\:bui-pt-2 { - padding-top: var(--bui-space-2); - } - - .md\:bui-pt-3 { - padding-top: var(--bui-space-3); - } - - .md\:bui-pt-4 { - padding-top: var(--bui-space-4); - } - - .md\:bui-pt-5 { - padding-top: var(--bui-space-5); - } - - .md\:bui-pt-6 { - padding-top: var(--bui-space-6); - } - - .md\:bui-pt-7 { - padding-top: var(--bui-space-7); - } - - .md\:bui-pt-8 { - padding-top: var(--bui-space-8); - } - - .md\:bui-pt-9 { - padding-top: var(--bui-space-9); - } - - .md\:bui-pt-10 { - padding-top: var(--bui-space-10); - } - - .md\:bui-pt-11 { - padding-top: var(--bui-space-11); - } - - .md\:bui-pt-12 { - padding-top: var(--bui-space-12); - } - - .md\:bui-pt-13 { - padding-top: var(--bui-space-13); - } - - .md\:bui-pt-14 { - padding-top: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-pt { - padding-top: var(--pt-lg); - } - - .lg\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); - } - - .lg\:bui-pt-1 { - padding-top: var(--bui-space-1); - } - - .lg\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); - } - - .lg\:bui-pt-2 { - padding-top: var(--bui-space-2); - } - - .lg\:bui-pt-3 { - padding-top: var(--bui-space-3); - } - - .lg\:bui-pt-4 { - padding-top: var(--bui-space-4); - } - - .lg\:bui-pt-5 { - padding-top: var(--bui-space-5); - } - - .lg\:bui-pt-6 { - padding-top: var(--bui-space-6); - } - - .lg\:bui-pt-7 { - padding-top: var(--bui-space-7); - } - - .lg\:bui-pt-8 { - padding-top: var(--bui-space-8); - } - - .lg\:bui-pt-9 { - padding-top: var(--bui-space-9); - } - - .lg\:bui-pt-10 { - padding-top: var(--bui-space-10); - } - - .lg\:bui-pt-11 { - padding-top: var(--bui-space-11); - } - - .lg\:bui-pt-12 { - padding-top: var(--bui-space-12); - } - - .lg\:bui-pt-13 { - padding-top: var(--bui-space-13); - } - - .lg\:bui-pt-14 { - padding-top: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-pt { - padding-top: var(--pt-xl); - } - - .xl\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); - } - - .xl\:bui-pt-1 { - padding-top: var(--bui-space-1); - } - - .xl\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); - } - - .xl\:bui-pt-2 { - padding-top: var(--bui-space-2); - } - - .xl\:bui-pt-3 { - padding-top: var(--bui-space-3); - } - - .xl\:bui-pt-4 { - padding-top: var(--bui-space-4); - } - - .xl\:bui-pt-5 { - padding-top: var(--bui-space-5); - } - - .xl\:bui-pt-6 { - padding-top: var(--bui-space-6); - } - - .xl\:bui-pt-7 { - padding-top: var(--bui-space-7); - } - - .xl\:bui-pt-8 { - padding-top: var(--bui-space-8); - } - - .xl\:bui-pt-9 { - padding-top: var(--bui-space-9); - } - - .xl\:bui-pt-10 { - padding-top: var(--bui-space-10); - } - - .xl\:bui-pt-11 { - padding-top: var(--bui-space-11); - } - - .xl\:bui-pt-12 { - padding-top: var(--bui-space-12); - } - - .xl\:bui-pt-13 { - padding-top: var(--bui-space-13); - } - - .xl\:bui-pt-14 { - padding-top: var(--bui-space-14); + .xl\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .xl\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .xl\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .xl\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .xl\:bui-pt-14 { + padding-top: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/px.css b/packages/ui/src/css/utilities/px.css index 37a41d832e..bb0cf12bbb 100644 --- a/packages/ui/src/css/utilities/px.css +++ b/packages/ui/src/css/utilities/px.css @@ -1,524 +1,542 @@ -.bui-px { - padding-left: var(--px); - padding-right: var(--px); -} +/* + * 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. + */ -.bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); -} - -.bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); -} - -.bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); -} - -.bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); -} - -.bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); -} - -.bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); -} - -.bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); -} - -.bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); -} - -.bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); -} - -.bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); -} - -.bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); -} - -.bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); -} - -.bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); -} - -.bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); -} - -.bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); -} - -.bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-px { - padding-left: var(--px-xs); - padding-right: var(--px-xs); +@layer utilities { + .bui-px { + padding-left: var(--px); + padding-right: var(--px); } - .xs\:bui-px-0\.5 { + .bui-px-0\.5 { padding-left: var(--bui-space-0_5); padding-right: var(--bui-space-0_5); } - .xs\:bui-px-1 { + .bui-px-1 { padding-left: var(--bui-space-1); padding-right: var(--bui-space-1); } - .xs\:bui-px-1\.5 { + .bui-px-1\.5 { padding-left: var(--bui-space-1_5); padding-right: var(--bui-space-1_5); } - .xs\:bui-px-2 { + .bui-px-2 { padding-left: var(--bui-space-2); padding-right: var(--bui-space-2); } - .xs\:bui-px-3 { + .bui-px-3 { padding-left: var(--bui-space-3); padding-right: var(--bui-space-3); } - .xs\:bui-px-4 { + .bui-px-4 { padding-left: var(--bui-space-4); padding-right: var(--bui-space-4); } - .xs\:bui-px-5 { + .bui-px-5 { padding-left: var(--bui-space-5); padding-right: var(--bui-space-5); } - .xs\:bui-px-6 { + .bui-px-6 { padding-left: var(--bui-space-6); padding-right: var(--bui-space-6); } - .xs\:bui-px-7 { + .bui-px-7 { padding-left: var(--bui-space-7); padding-right: var(--bui-space-7); } - .xs\:bui-px-8 { + .bui-px-8 { padding-left: var(--bui-space-8); padding-right: var(--bui-space-8); } - .xs\:bui-px-9 { + .bui-px-9 { padding-left: var(--bui-space-9); padding-right: var(--bui-space-9); } - .xs\:bui-px-10 { + .bui-px-10 { padding-left: var(--bui-space-10); padding-right: var(--bui-space-10); } - .xs\:bui-px-11 { + .bui-px-11 { padding-left: var(--bui-space-11); padding-right: var(--bui-space-11); } - .xs\:bui-px-12 { + .bui-px-12 { padding-left: var(--bui-space-12); padding-right: var(--bui-space-12); } - .xs\:bui-px-13 { + .bui-px-13 { padding-left: var(--bui-space-13); padding-right: var(--bui-space-13); } - .xs\:bui-px-14 { + .bui-px-14 { padding-left: var(--bui-space-14); padding-right: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-px { - padding-left: var(--px-sm); - padding-right: var(--px-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-px { + padding-left: var(--px-xs); + padding-right: var(--px-xs); + } + + .xs\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .xs\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .xs\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .xs\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .xs\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .xs\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .xs\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .xs\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .xs\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .xs\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .xs\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .xs\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .xs\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .xs\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .xs\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .xs\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } } - .sm\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-px { + padding-left: var(--px-sm); + padding-right: var(--px-sm); + } + + .sm\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .sm\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .sm\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .sm\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .sm\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .sm\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .sm\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .sm\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .sm\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .sm\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .sm\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .sm\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .sm\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .sm\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .sm\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .sm\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } } - .sm\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-px { + padding-left: var(--px-md); + padding-right: var(--px-md); + } + + .md\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .md\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .md\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .md\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .md\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .md\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .md\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .md\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .md\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .md\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .md\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .md\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .md\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .md\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .md\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .md\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } } - .sm\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-px { + padding-left: var(--px-lg); + padding-right: var(--px-lg); + } + + .lg\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .lg\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .lg\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .lg\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .lg\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .lg\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .lg\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .lg\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .lg\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .lg\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .lg\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .lg\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .lg\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .lg\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .lg\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .lg\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } } - .sm\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-px { + padding-left: var(--px-xl); + padding-right: var(--px-xl); + } - .sm\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } + .xl\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } - .sm\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } + .xl\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } - .sm\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } + .xl\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } - .sm\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } + .xl\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } - .sm\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } + .xl\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } - .sm\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } + .xl\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } - .sm\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } + .xl\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } - .sm\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } + .xl\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } - .sm\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } + .xl\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } - .sm\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } + .xl\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } - .sm\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } + .xl\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } - .sm\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-px { - padding-left: var(--px-md); - padding-right: var(--px-md); - } - - .md\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); - } - - .md\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); - } - - .md\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); - } - - .md\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } - - .md\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } - - .md\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } - - .md\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } - - .md\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } - - .md\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } - - .md\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } - - .md\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } - - .md\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } - - .md\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } - - .md\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } - - .md\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } - - .md\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-px { - padding-left: var(--px-lg); - padding-right: var(--px-lg); - } - - .lg\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); - } - - .lg\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); - } - - .lg\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); - } - - .lg\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } - - .lg\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } - - .lg\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } - - .lg\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } - - .lg\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } - - .lg\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } - - .lg\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } - - .lg\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } - - .lg\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } - - .lg\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } - - .lg\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } - - .lg\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } - - .lg\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-px { - padding-left: var(--px-xl); - padding-right: var(--px-xl); - } - - .xl\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); - } - - .xl\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); - } - - .xl\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); - } - - .xl\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } - - .xl\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } - - .xl\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } - - .xl\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } - - .xl\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } - - .xl\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } - - .xl\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } - - .xl\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } - - .xl\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } - - .xl\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } - - .xl\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } - - .xl\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } - - .xl\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); + .xl\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .xl\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .xl\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .xl\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .xl\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/py.css b/packages/ui/src/css/utilities/py.css index e3738df00c..aeaef05c6e 100644 --- a/packages/ui/src/css/utilities/py.css +++ b/packages/ui/src/css/utilities/py.css @@ -1,524 +1,542 @@ -.bui-py { - padding-top: var(--py); - padding-bottom: var(--py); -} +/* + * 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. + */ -.bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); -} - -.bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); -} - -.bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); -} - -.bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); -} - -.bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); -} - -.bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); -} - -.bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); -} - -.bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); -} - -.bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); -} - -.bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); -} - -.bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); -} - -.bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); -} - -.bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); -} - -.bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); -} - -.bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); -} - -.bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-py { - padding-top: var(--py-xs); - padding-bottom: var(--py-xs); +@layer utilities { + .bui-py { + padding-top: var(--py); + padding-bottom: var(--py); } - .xs\:bui-py-0\.5 { + .bui-py-0\.5 { padding-top: var(--bui-space-0_5); padding-bottom: var(--bui-space-0_5); } - .xs\:bui-py-1 { + .bui-py-1 { padding-top: var(--bui-space-1); padding-bottom: var(--bui-space-1); } - .xs\:bui-py-1\.5 { + .bui-py-1\.5 { padding-top: var(--bui-space-1_5); padding-bottom: var(--bui-space-1_5); } - .xs\:bui-py-2 { + .bui-py-2 { padding-top: var(--bui-space-2); padding-bottom: var(--bui-space-2); } - .xs\:bui-py-3 { + .bui-py-3 { padding-top: var(--bui-space-3); padding-bottom: var(--bui-space-3); } - .xs\:bui-py-4 { + .bui-py-4 { padding-top: var(--bui-space-4); padding-bottom: var(--bui-space-4); } - .xs\:bui-py-5 { + .bui-py-5 { padding-top: var(--bui-space-5); padding-bottom: var(--bui-space-5); } - .xs\:bui-py-6 { + .bui-py-6 { padding-top: var(--bui-space-6); padding-bottom: var(--bui-space-6); } - .xs\:bui-py-7 { + .bui-py-7 { padding-top: var(--bui-space-7); padding-bottom: var(--bui-space-7); } - .xs\:bui-py-8 { + .bui-py-8 { padding-top: var(--bui-space-8); padding-bottom: var(--bui-space-8); } - .xs\:bui-py-9 { + .bui-py-9 { padding-top: var(--bui-space-9); padding-bottom: var(--bui-space-9); } - .xs\:bui-py-10 { + .bui-py-10 { padding-top: var(--bui-space-10); padding-bottom: var(--bui-space-10); } - .xs\:bui-py-11 { + .bui-py-11 { padding-top: var(--bui-space-11); padding-bottom: var(--bui-space-11); } - .xs\:bui-py-12 { + .bui-py-12 { padding-top: var(--bui-space-12); padding-bottom: var(--bui-space-12); } - .xs\:bui-py-13 { + .bui-py-13 { padding-top: var(--bui-space-13); padding-bottom: var(--bui-space-13); } - .xs\:bui-py-14 { + .bui-py-14 { padding-top: var(--bui-space-14); padding-bottom: var(--bui-space-14); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-py { - padding-top: var(--py-sm); - padding-bottom: var(--py-sm); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-py { + padding-top: var(--py-xs); + padding-bottom: var(--py-xs); + } + + .xs\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .xs\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .xs\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .xs\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .xs\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .xs\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .xs\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .xs\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .xs\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .xs\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .xs\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .xs\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .xs\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .xs\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .xs\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .xs\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } } - .sm\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-py { + padding-top: var(--py-sm); + padding-bottom: var(--py-sm); + } + + .sm\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .sm\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .sm\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .sm\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .sm\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .sm\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .sm\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .sm\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .sm\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .sm\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .sm\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .sm\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .sm\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .sm\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .sm\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .sm\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } } - .sm\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-py { + padding-top: var(--py-md); + padding-bottom: var(--py-md); + } + + .md\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .md\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .md\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .md\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .md\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .md\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .md\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .md\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .md\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .md\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .md\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .md\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .md\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .md\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .md\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .md\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } } - .sm\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-py { + padding-top: var(--py-lg); + padding-bottom: var(--py-lg); + } + + .lg\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .lg\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .lg\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .lg\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .lg\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .lg\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .lg\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .lg\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .lg\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .lg\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .lg\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .lg\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .lg\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .lg\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .lg\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .lg\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } } - .sm\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-py { + padding-top: var(--py-xl); + padding-bottom: var(--py-xl); + } - .sm\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } + .xl\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } - .sm\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } + .xl\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } - .sm\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } + .xl\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } - .sm\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } + .xl\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } - .sm\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } + .xl\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } - .sm\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } + .xl\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } - .sm\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } + .xl\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } - .sm\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } + .xl\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } - .sm\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } + .xl\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } - .sm\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } + .xl\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } - .sm\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } + .xl\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } - .sm\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-py { - padding-top: var(--py-md); - padding-bottom: var(--py-md); - } - - .md\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); - } - - .md\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); - } - - .md\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); - } - - .md\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } - - .md\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } - - .md\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } - - .md\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } - - .md\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } - - .md\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } - - .md\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } - - .md\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } - - .md\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } - - .md\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } - - .md\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } - - .md\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } - - .md\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-py { - padding-top: var(--py-lg); - padding-bottom: var(--py-lg); - } - - .lg\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); - } - - .lg\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); - } - - .lg\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); - } - - .lg\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } - - .lg\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } - - .lg\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } - - .lg\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } - - .lg\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } - - .lg\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } - - .lg\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } - - .lg\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } - - .lg\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } - - .lg\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } - - .lg\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } - - .lg\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } - - .lg\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-py { - padding-top: var(--py-xl); - padding-bottom: var(--py-xl); - } - - .xl\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); - } - - .xl\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); - } - - .xl\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); - } - - .xl\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } - - .xl\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } - - .xl\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } - - .xl\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } - - .xl\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } - - .xl\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } - - .xl\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } - - .xl\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } - - .xl\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } - - .xl\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } - - .xl\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } - - .xl\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } - - .xl\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); + .xl\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .xl\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .xl\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .xl\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .xl\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } } } diff --git a/packages/ui/src/css/utilities/sm.css b/packages/ui/src/css/utilities/sm.css index 61baaa6b0d..a9c8ea8ab5 100644 --- a/packages/ui/src/css/utilities/sm.css +++ b/packages/ui/src/css/utilities/sm.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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. diff --git a/packages/ui/src/css/utilities/width.css b/packages/ui/src/css/utilities/width.css index 6dad08814a..5a9ff0a899 100644 --- a/packages/ui/src/css/utilities/width.css +++ b/packages/ui/src/css/utilities/width.css @@ -1,86 +1,104 @@ -.bui-w { - width: var(--width); -} +/* + * 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. + */ -.bui-min-w { - min-width: var(--min-width); -} - -.bui-max-w { - max-width: var(--max-width); -} - -/* Breakpoint xs */ -@media (min-width: 640px) { - .xs\:bui-w { +@layer utilities { + .bui-w { width: var(--width); } - .xs\:bui-min-w { + .bui-min-w { min-width: var(--min-width); } - .xs\:bui-max-w { + .bui-max-w { max-width: var(--max-width); } -} -/* Breakpoint sm */ -@media (min-width: 768px) { - .sm\:bui-w { - width: var(--width); + /* Breakpoint xs */ + @media (min-width: 640px) { + .xs\:bui-w { + width: var(--width); + } + + .xs\:bui-min-w { + min-width: var(--min-width); + } + + .xs\:bui-max-w { + max-width: var(--max-width); + } } - .sm\:bui-min-w { - min-width: var(--min-width); + /* Breakpoint sm */ + @media (min-width: 768px) { + .sm\:bui-w { + width: var(--width); + } + + .sm\:bui-min-w { + min-width: var(--min-width); + } + + .sm\:bui-max-w { + max-width: var(--max-width); + } } - .sm\:bui-max-w { - max-width: var(--max-width); - } -} - -/* Breakpoint md */ -@media (min-width: 1024px) { - .md\:bui-w { - width: var(--width); - } - - .md\:bui-min-w { - min-width: var(--min-width); - } - - .md\:bui-max-w { - max-width: var(--max-width); - } -} - -/* Breakpoint lg */ -@media (min-width: 1280px) { - .lg\:bui-w { - width: var(--width); - } - - .lg\:bui-min-w { - min-width: var(--min-width); - } - - .lg\:bui-max-w { - max-width: var(--max-width); - } -} - -/* Breakpoint xl */ -@media (min-width: 1536px) { - .xl\:bui-w { - width: var(--width); - } - - .xl\:bui-min-w { - min-width: var(--min-width); - } - - .xl\:bui-max-w { - max-width: var(--max-width); + /* Breakpoint md */ + @media (min-width: 1024px) { + .md\:bui-w { + width: var(--width); + } + + .md\:bui-min-w { + min-width: var(--min-width); + } + + .md\:bui-max-w { + max-width: var(--max-width); + } + } + + /* Breakpoint lg */ + @media (min-width: 1280px) { + .lg\:bui-w { + width: var(--width); + } + + .lg\:bui-min-w { + min-width: var(--min-width); + } + + .lg\:bui-max-w { + max-width: var(--max-width); + } + } + + /* Breakpoint xl */ + @media (min-width: 1536px) { + .xl\:bui-w { + width: var(--width); + } + + .xl\:bui-min-w { + min-width: var(--min-width); + } + + .xl\:bui-max-w { + max-width: var(--max-width); + } } } diff --git a/packages/ui/src/css/utilities/xs.css b/packages/ui/src/css/utilities/xs.css index 27adb7c7e4..2907c7d468 100644 --- a/packages/ui/src/css/utilities/xs.css +++ b/packages/ui/src/css/utilities/xs.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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. From f78b0b02b8ce612774d20ee3e723858a2f337162 Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Wed, 10 Sep 2025 12:23:26 +0300 Subject: [PATCH 128/244] feat(dev): allow running example app with docker this PR allows backstage contributors to run the example app against actual postgres, opensearch and redis services using docker and docker compose file. no changeset as this doesn't affect any published packages. Signed-off-by: Hellgren Heikki --- CONTRIBUTING.md | 10 +++++++++ app-config.docker.yaml | 23 +++++++++++++++++++++ docker-compose.deps.yml | 39 +++++++++++++++++++++++++++++++++++ package.json | 1 + packages/backend/package.json | 1 + packages/backend/src/index.ts | 13 ++++++++++-- yarn.lock | 3 ++- 7 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 app-config.docker.yaml create mode 100644 docker-compose.deps.yml diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9413206197..ba40be86c8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -102,6 +102,16 @@ Visit and you should see the bleeding edge of Backstage If you want to get a better understanding of the layout of the repo now that you have a local copy running feel free to review the [Backstage Project Structure](https://backstage.io/docs/getting-started/#general-folder-structure) documentation. +#### Using Docker for the Example App + +You can run the Example App using Docker with Postgres, OpenSearch and Redis services. This setup very closely resembles how Backstage is run in production in many occasions. + +To start the Example App with Docker, make sure you have Docker and Docker Compose installed on your machine, then run the following command from the root of the repository: + +```bash +yarn start:docker +``` + ## Coding Guidelines All code is formatted with `prettier` using the configuration in the repo. If possible, we recommend configuring your editor to format automatically, but you can also use the `yarn prettier --write ` command to format files. diff --git a/app-config.docker.yaml b/app-config.docker.yaml new file mode 100644 index 0000000000..07f7c7ac8c --- /dev/null +++ b/app-config.docker.yaml @@ -0,0 +1,23 @@ +# To run local backstage instance with docker services, +# run: +# 1. `docker compose -f docker-compose.deps.yml up --wait` +# 2. `BACKSTAGE_ENV=docker yarn dev` +backend: + database: + client: pg + connection: + host: localhost + port: 5432 + user: postgres + password: postgres + cache: + store: redis + connection: redis://localhost:6379 + +search: + elasticsearch: + provider: opensearch + node: 'http://localhost:9200' + auth: + username: admin + password: admin diff --git a/docker-compose.deps.yml b/docker-compose.deps.yml new file mode 100644 index 0000000000..c7515eca04 --- /dev/null +++ b/docker-compose.deps.yml @@ -0,0 +1,39 @@ +#!/usr/bin/env docker compose -f +name: backstage +services: + psql: + image: postgres:17.6 + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - '5432:5432' + healthcheck: + test: ['CMD-SHELL', 'pg_isready'] + interval: 10s + retries: 5 + start_period: 30s + timeout: 10s + redis: + image: redis:8.2.1-alpine + ports: + - '6379:6379' + healthcheck: + test: ['CMD-SHELL', 'redis-cli ping | grep PONG'] + interval: 1s + timeout: 3s + retries: 5 + opensearch: + image: opensearchproject/opensearch:2.19.3 + environment: + plugins.security.disabled: true + discovery.type: single-node + OPENSEARCH_INITIAL_ADMIN_PASSWORD: Opensearch1! + ports: + - '9200:9200' + - '9600:9600' + healthcheck: + test: 'curl --fail opensearch:9200/_cat/health >/dev/null || exit 1' + interval: 5s + timeout: 5s + retries: 30 diff --git a/package.json b/package.json index 7aed18ab74..2a5dad098a 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "snyk:test:package": "yarn snyk:test --include", "start": "backstage-cli repo start", "start-backend": "echo \"Use 'yarn start example-backend' instead\"", + "start:docker": "docker compose -f docker-compose.deps.yml up --wait && BACKSTAGE_ENV=docker yarn start", "start:microsite": "cd microsite/ && yarn start", "start:next": "yarn start example-app-next example-backend", "storybook": "storybook dev -p 6006", diff --git a/packages/backend/package.json b/packages/backend/package.json index 64c2f1dd47..ad34f429f8 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -60,6 +60,7 @@ "@backstage/plugin-scaffolder-backend-module-notifications": "workspace:^", "@backstage/plugin-search-backend": "workspace:^", "@backstage/plugin-search-backend-module-catalog": "workspace:^", + "@backstage/plugin-search-backend-module-elasticsearch": "workspace:^", "@backstage/plugin-search-backend-module-explore": "workspace:^", "@backstage/plugin-search-backend-module-techdocs": "workspace:^", "@backstage/plugin-search-backend-node": "workspace:^", diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index e32d3148b3..541c3bd791 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -15,18 +15,27 @@ */ import { createBackend } from '@backstage/backend-defaults'; -import { createBackendFeatureLoader } from '@backstage/backend-plugin-api'; +import { + coreServices, + createBackendFeatureLoader, +} from '@backstage/backend-plugin-api'; const backend = createBackend(); // An example of how to group together and load multiple features. You can also // access root-scoped services by adding `deps`. const searchLoader = createBackendFeatureLoader({ - *loader() { + deps: { + config: coreServices.rootConfig, + }, + *loader({ config }) { yield import('@backstage/plugin-search-backend'); yield import('@backstage/plugin-search-backend-module-catalog'); yield import('@backstage/plugin-search-backend-module-explore'); yield import('@backstage/plugin-search-backend-module-techdocs'); + if (config.has('search.elasticsearch')) { + yield import('@backstage/plugin-search-backend-module-elasticsearch'); + } }, }); diff --git a/yarn.lock b/yarn.lock index 50a73bb657..b267519b8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6710,7 +6710,7 @@ __metadata: languageName: unknown linkType: soft -"@backstage/plugin-search-backend-module-elasticsearch@workspace:plugins/search-backend-module-elasticsearch": +"@backstage/plugin-search-backend-module-elasticsearch@workspace:^, @backstage/plugin-search-backend-module-elasticsearch@workspace:plugins/search-backend-module-elasticsearch": version: 0.0.0-use.local resolution: "@backstage/plugin-search-backend-module-elasticsearch@workspace:plugins/search-backend-module-elasticsearch" dependencies: @@ -30142,6 +30142,7 @@ __metadata: "@backstage/plugin-scaffolder-backend-module-notifications": "workspace:^" "@backstage/plugin-search-backend": "workspace:^" "@backstage/plugin-search-backend-module-catalog": "workspace:^" + "@backstage/plugin-search-backend-module-elasticsearch": "workspace:^" "@backstage/plugin-search-backend-module-explore": "workspace:^" "@backstage/plugin-search-backend-module-techdocs": "workspace:^" "@backstage/plugin-search-backend-node": "workspace:^" From af4d9b492e43a81a887a4ab514a4b5d1d29b71bc Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 8 Oct 2025 15:07:09 +0100 Subject: [PATCH 129/244] Update components Signed-off-by: Charles de Dreuille --- .changeset/seven-lines-stay.md | 5 + .../src/components/Avatar/Avatar.styles.css | 88 ++-- packages/ui/src/components/Box/styles.css | 26 +- packages/ui/src/components/Button/styles.css | 210 ++++---- .../ui/src/components/ButtonIcon/styles.css | 24 +- .../ui/src/components/Card/Card.styles.css | 50 +- .../ui/src/components/Checkbox/styles.css | 106 ++-- .../Collapsible/Collapsible.styles.css | 18 +- .../ui/src/components/Container/styles.css | 34 +- .../FieldError/FieldError.styles.css | 30 +- .../FieldLabel/FieldLabel.styles.css | 64 ++- packages/ui/src/components/Flex/styles.css | 12 +- packages/ui/src/components/Grid/styles.css | 22 +- .../src/components/Header/Header.styles.css | 146 +++--- .../HeaderPage/HeaderPage.styles.css | 54 ++- packages/ui/src/components/Icon/styles.css | 10 +- packages/ui/src/components/Link/styles.css | 30 +- .../ui/src/components/Menu/Menu.styles.css | 456 +++++++++--------- .../PasswordField/PasswordField.styles.css | 102 ++-- .../src/components/Popover/Popover.styles.css | 20 +- .../RadioGroup/RadioGroup.styles.css | 174 ++++--- .../ScrollArea/ScrollArea.styles.css | 92 ++-- .../SearchField/SearchField.styles.css | 226 ++++----- .../src/components/Select/Select.styles.css | 298 ++++++------ .../components/Skeleton/Skeleton.styles.css | 18 +- .../src/components/Switch/Switch.styles.css | 92 ++-- .../ui/src/components/Table/Table.styles.css | 250 +++++----- .../TablePagination.styles.css | 56 ++- .../ui/src/components/Tabs/Tabs.styles.css | 168 ++++--- .../components/TagGroup/TagGroup.styles.css | 126 ++--- packages/ui/src/components/Text/styles.css | 142 +++--- .../components/TextField/TextField.styles.css | 192 ++++---- .../src/components/Tooltip/Tooltip.styles.css | 182 +++---- 33 files changed, 1868 insertions(+), 1655 deletions(-) create mode 100644 .changeset/seven-lines-stay.md diff --git a/.changeset/seven-lines-stay.md b/.changeset/seven-lines-stay.md new file mode 100644 index 0000000000..4148a4eb83 --- /dev/null +++ b/.changeset/seven-lines-stay.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +We are restructuring our CSS to have a better layer structure. diff --git a/packages/ui/src/components/Avatar/Avatar.styles.css b/packages/ui/src/components/Avatar/Avatar.styles.css index ce3afea3b5..ce2573c4b0 100644 --- a/packages/ui/src/components/Avatar/Avatar.styles.css +++ b/packages/ui/src/components/Avatar/Avatar.styles.css @@ -14,52 +14,54 @@ * limitations under the License. */ -.bui-AvatarRoot { - display: inline-flex; - justify-content: center; - align-items: center; - vertical-align: middle; - border-radius: 100%; - user-select: none; - font-weight: 500; - color: var(--bui-fg-primary); - background-color: var(--bui-bg-surface-2); - font-size: 1rem; - line-height: 1; - overflow: hidden; - height: 2rem; - width: 2rem; -} +@layer components { + .bui-AvatarRoot { + display: inline-flex; + justify-content: center; + align-items: center; + vertical-align: middle; + border-radius: 100%; + user-select: none; + font-weight: 500; + color: var(--bui-fg-primary); + background-color: var(--bui-bg-surface-2); + font-size: 1rem; + line-height: 1; + overflow: hidden; + height: 2rem; + width: 2rem; + } -.bui-AvatarRoot[data-size='small'] { - height: 1.5rem; - width: 1.5rem; -} + .bui-AvatarRoot[data-size='small'] { + height: 1.5rem; + width: 1.5rem; + } -.bui-AvatarRoot[data-size='medium'] { - height: 2rem; - width: 2rem; -} + .bui-AvatarRoot[data-size='medium'] { + height: 2rem; + width: 2rem; + } -.bui-AvatarRoot[data-size='large'] { - height: 3rem; - width: 3rem; -} + .bui-AvatarRoot[data-size='large'] { + height: 3rem; + width: 3rem; + } -.bui-AvatarImage { - object-fit: cover; - height: 100%; - width: 100%; -} + .bui-AvatarImage { + object-fit: cover; + height: 100%; + width: 100%; + } -.bui-AvatarFallback { - align-items: center; - display: flex; - justify-content: center; - height: 100%; - width: 100%; - font-size: var(--bui-font-size-3); - font-weight: var(--bui-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--bui-border); - border-radius: var(--bui-radius-full); + .bui-AvatarFallback { + align-items: center; + display: flex; + justify-content: center; + height: 100%; + width: 100%; + font-size: var(--bui-font-size-3); + font-weight: var(--bui-font-weight-regular); + box-shadow: inset 0 0 0 1px var(--bui-border); + border-radius: var(--bui-radius-full); + } } diff --git a/packages/ui/src/components/Box/styles.css b/packages/ui/src/components/Box/styles.css index c499657230..a1648b476c 100644 --- a/packages/ui/src/components/Box/styles.css +++ b/packages/ui/src/components/Box/styles.css @@ -1,5 +1,23 @@ -.bui-Box { - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); +/* + * 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. + */ + +@layer components { + .bui-Box { + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + } } diff --git a/packages/ui/src/components/Button/styles.css b/packages/ui/src/components/Button/styles.css index 03138a7c44..aec754c740 100644 --- a/packages/ui/src/components/Button/styles.css +++ b/packages/ui/src/components/Button/styles.css @@ -14,118 +14,120 @@ * limitations under the License. */ -.bui-Button { - border: none; - display: inline-flex; - align-items: center; - justify-content: center; - user-select: none; - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-bold); - padding: 0; - cursor: pointer; - border-radius: var(--bui-radius-2); - gap: var(--bui-space-1_5); - flex-shrink: 0; +@layer components { + .bui-Button { + border: none; + display: inline-flex; + align-items: center; + justify-content: center; + user-select: none; + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-bold); + padding: 0; + cursor: pointer; + border-radius: var(--bui-radius-2); + gap: var(--bui-space-1_5); + flex-shrink: 0; - &[data-disabled='true'] { - cursor: not-allowed; - } -} - -.bui-Button[data-variant='primary'] { - background-color: var(--bui-bg-solid); - color: var(--bui-fg-solid); - - &:hover { - background-color: var(--bui-bg-solid-hover); - transition: background-color 150ms ease; + &[data-disabled='true'] { + cursor: not-allowed; + } } - &:active { - background-color: var(--bui-bg-solid-pressed); + .bui-Button[data-variant='primary'] { + background-color: var(--bui-bg-solid); + color: var(--bui-fg-solid); + + &:hover { + background-color: var(--bui-bg-solid-hover); + transition: background-color 150ms ease; + } + + &:active { + background-color: var(--bui-bg-solid-pressed); + } + + &:focus-visible { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } + + &[data-disabled='true'] { + background-color: var(--bui-bg-solid-disabled); + color: var(--bui-fg-solid-disabled); + } } - &:focus-visible { - outline: 2px solid var(--bui-ring); - outline-offset: 2px; - } - - &[data-disabled='true'] { - background-color: var(--bui-bg-solid-disabled); - color: var(--bui-fg-solid-disabled); - } -} - -.bui-Button[data-variant='secondary'] { - background-color: var(--bui-bg-surface-1); - box-shadow: inset 0 0 0 1px var(--bui-border); - color: var(--bui-fg-primary); - - &:hover { - box-shadow: inset 0 0 0 1px var(--bui-border-hover); - transition: box-shadow 150ms ease; - } - - &:active { - box-shadow: inset 0 0 0 1px var(--bui-border-pressed); - } - - &:focus-visible { - outline: none; - transition: none; - box-shadow: inset 0 0 0 2px var(--bui-ring); - } - - &[data-disabled='true'] { - box-shadow: inset 0 0 0 1px var(--bui-border-disabled); - color: var(--bui-fg-disabled); - } -} - -.bui-Button[data-variant='tertiary'] { - background-color: transparent; - color: var(--bui-fg-primary); - - &:hover { + .bui-Button[data-variant='secondary'] { background-color: var(--bui-bg-surface-1); - transition: background-color 200ms ease; + box-shadow: inset 0 0 0 1px var(--bui-border); + color: var(--bui-fg-primary); + + &:hover { + box-shadow: inset 0 0 0 1px var(--bui-border-hover); + transition: box-shadow 150ms ease; + } + + &:active { + box-shadow: inset 0 0 0 1px var(--bui-border-pressed); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--bui-ring); + } + + &[data-disabled='true'] { + box-shadow: inset 0 0 0 1px var(--bui-border-disabled); + color: var(--bui-fg-disabled); + } } - &:active { - background-color: var(--bui-bg-surface-2); - } - - &:focus-visible { - outline: none; - transition: none; - box-shadow: inset 0 0 0 2px var(--bui-ring); - } - - &[data-disabled='true'] { + .bui-Button[data-variant='tertiary'] { background-color: transparent; - color: var(--bui-fg-disabled); + color: var(--bui-fg-primary); + + &:hover { + background-color: var(--bui-bg-surface-1); + transition: background-color 200ms ease; + } + + &:active { + background-color: var(--bui-bg-surface-2); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--bui-ring); + } + + &[data-disabled='true'] { + background-color: transparent; + color: var(--bui-fg-disabled); + } + } + + .bui-Button[data-size='medium'] { + font-size: var(--bui-font-size-4); + padding: 0 var(--bui-space-3); + height: 2.5rem; + } + + .bui-Button[data-size='small'] { + font-size: var(--bui-font-size-3); + padding: 0 var(--bui-space-2); + height: 2rem; + } + + .bui-Button[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + .bui-Button[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; } } - -.bui-Button[data-size='medium'] { - font-size: var(--bui-font-size-4); - padding: 0 var(--bui-space-3); - height: 2.5rem; -} - -.bui-Button[data-size='small'] { - font-size: var(--bui-font-size-3); - padding: 0 var(--bui-space-2); - height: 2rem; -} - -.bui-Button[data-size='small'] svg { - width: 1rem; - height: 1rem; -} - -.bui-Button[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; -} diff --git a/packages/ui/src/components/ButtonIcon/styles.css b/packages/ui/src/components/ButtonIcon/styles.css index cbd19071a9..56b73a8a66 100644 --- a/packages/ui/src/components/ButtonIcon/styles.css +++ b/packages/ui/src/components/ButtonIcon/styles.css @@ -14,17 +14,19 @@ * limitations under the License. */ -.bui-ButtonIcon { - align-items: center; - justify-content: center; -} +@layer components { + .bui-ButtonIcon { + align-items: center; + justify-content: center; + } -.bui-ButtonIcon[data-size='small'] { - padding: 0; - width: 2rem; -} + .bui-ButtonIcon[data-size='small'] { + padding: 0; + width: 2rem; + } -.bui-ButtonIcon[data-size='medium'] { - padding: 0; - width: 2.5rem; + .bui-ButtonIcon[data-size='medium'] { + padding: 0; + width: 2.5rem; + } } diff --git a/packages/ui/src/components/Card/Card.styles.css b/packages/ui/src/components/Card/Card.styles.css index 1643ba0b8a..670e5de2c3 100644 --- a/packages/ui/src/components/Card/Card.styles.css +++ b/packages/ui/src/components/Card/Card.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,30 +14,32 @@ * limitations under the License. */ -.bui-Card { - display: flex; - flex-direction: column; - gap: var(--bui-space-3); - background-color: var(--bui-bg-surface-1); - border-radius: var(--bui-radius-3); - padding-block: var(--bui-space-3); - color: var(--bui-fg-primary); - border: 1px solid var(--bui-border); - overflow: hidden; - min-height: 0; - width: 100%; -} +@layer components { + .bui-Card { + display: flex; + flex-direction: column; + gap: var(--bui-space-3); + background-color: var(--bui-bg-surface-1); + border-radius: var(--bui-radius-3); + padding-block: var(--bui-space-3); + color: var(--bui-fg-primary); + border: 1px solid var(--bui-border); + overflow: hidden; + min-height: 0; + width: 100%; + } -.bui-CardBody { - flex: 1; - min-height: 0; - overflow: auto; -} + .bui-CardBody { + flex: 1; + min-height: 0; + overflow: auto; + } -.bui-CardHeader { - padding-inline: var(--bui-space-3); -} + .bui-CardHeader { + padding-inline: var(--bui-space-3); + } -.bui-CardFooter { - padding-inline: var(--bui-space-3); + .bui-CardFooter { + padding-inline: var(--bui-space-3); + } } diff --git a/packages/ui/src/components/Checkbox/styles.css b/packages/ui/src/components/Checkbox/styles.css index 75d57e72aa..af813d4098 100644 --- a/packages/ui/src/components/Checkbox/styles.css +++ b/packages/ui/src/components/Checkbox/styles.css @@ -1,52 +1,70 @@ -.bui-CheckboxRoot { - border: none; - display: flex; - align-items: center; - justify-content: center; - width: 1rem; - height: 1rem; - box-shadow: inset 0 0 0 1px var(--bui-border); - cursor: pointer; - border-radius: 2px; - transition: background-color 0.2s ease-in-out; - background-color: var(--bui-bg-surface-1); - padding: 0; - flex-shrink: 0; -} +/* + * 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. + */ -.bui-CheckboxRoot:focus-visible { - transition: none; - outline: 2px solid var(--bui-ring); - outline-offset: 2px; -} +@layer components { + .bui-CheckboxRoot { + border: none; + display: flex; + align-items: center; + justify-content: center; + width: 1rem; + height: 1rem; + box-shadow: inset 0 0 0 1px var(--bui-border); + cursor: pointer; + border-radius: 2px; + transition: background-color 0.2s ease-in-out; + background-color: var(--bui-bg-surface-1); + padding: 0; + flex-shrink: 0; + } -.bui-CheckboxRoot[data-checked] { - background-color: var(--bui-bg-solid); - box-shadow: none; - color: var(--bui-fg-solid); -} + .bui-CheckboxRoot:focus-visible { + transition: none; + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } -.bui-CheckboxLabel { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - user-select: none; + .bui-CheckboxRoot[data-checked] { + background-color: var(--bui-bg-solid); + box-shadow: none; + color: var(--bui-fg-solid); + } - &:hover { - & .bui-CheckboxRoot:not([data-checked]) { - box-shadow: inset 0 0 0 1px var(--bui-border-hover); + .bui-CheckboxLabel { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + user-select: none; + + &:hover { + & .bui-CheckboxRoot:not([data-checked]) { + box-shadow: inset 0 0 0 1px var(--bui-border-hover); + } } } -} -.bui-CheckboxIndicator { - display: flex; - align-items: center; - justify-content: center; - color: var(--bui-fg-solid); + .bui-CheckboxIndicator { + display: flex; + align-items: center; + justify-content: center; + color: var(--bui-fg-solid); + } } diff --git a/packages/ui/src/components/Collapsible/Collapsible.styles.css b/packages/ui/src/components/Collapsible/Collapsible.styles.css index e1fbf00a82..35b0992a62 100644 --- a/packages/ui/src/components/Collapsible/Collapsible.styles.css +++ b/packages/ui/src/components/Collapsible/Collapsible.styles.css @@ -14,14 +14,16 @@ * limitations under the License. */ -.bui-CollapsiblePanel { - display: flex; - height: var(--collapsible-panel-height); - overflow: hidden; - transition: all 150ms ease-out; +@layer components { + .bui-CollapsiblePanel { + display: flex; + height: var(--collapsible-panel-height); + overflow: hidden; + transition: all 150ms ease-out; - &[data-starting-style], - &[data-ending-style] { - height: 0; + &[data-starting-style], + &[data-ending-style] { + height: 0; + } } } diff --git a/packages/ui/src/components/Container/styles.css b/packages/ui/src/components/Container/styles.css index a812b7c767..515e449457 100644 --- a/packages/ui/src/components/Container/styles.css +++ b/packages/ui/src/components/Container/styles.css @@ -1,12 +1,30 @@ -.bui-Container { - max-width: 120rem; - padding-inline: var(--bui-space-4); - margin-inline: auto; - transition: padding 0.2s ease-in-out; -} +/* + * 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. + */ -@media (min-width: 640px) { +@layer components { .bui-Container { - padding-inline: var(--bui-space-5); + max-width: 120rem; + padding-inline: var(--bui-space-4); + margin-inline: auto; + transition: padding 0.2s ease-in-out; + } + + @media (min-width: 640px) { + .bui-Container { + padding-inline: var(--bui-space-5); + } } } diff --git a/packages/ui/src/components/FieldError/FieldError.styles.css b/packages/ui/src/components/FieldError/FieldError.styles.css index e69e8637d3..90b0547ab7 100644 --- a/packages/ui/src/components/FieldError/FieldError.styles.css +++ b/packages/ui/src/components/FieldError/FieldError.styles.css @@ -1,7 +1,25 @@ -.bui-FieldError { - display: inline-block; - color: var(--bui-fg-danger); - font-size: var(--bui-font-size-2); - font-weight: var(--bui-font-weight-regular); - margin-top: var(--bui-space-2); +/* + * 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. + */ + +@layer components { + .bui-FieldError { + display: inline-block; + color: var(--bui-fg-danger); + font-size: var(--bui-font-size-2); + font-weight: var(--bui-font-weight-regular); + margin-top: var(--bui-space-2); + } } diff --git a/packages/ui/src/components/FieldLabel/FieldLabel.styles.css b/packages/ui/src/components/FieldLabel/FieldLabel.styles.css index 2dfc28a49d..0a70e69ea2 100644 --- a/packages/ui/src/components/FieldLabel/FieldLabel.styles.css +++ b/packages/ui/src/components/FieldLabel/FieldLabel.styles.css @@ -1,27 +1,45 @@ -.bui-FieldLabelWrapper { - display: flex; - flex-direction: column; - margin-bottom: var(--bui-space-3); - gap: var(--bui-space-1); -} +/* + * 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. + */ -.bui-FieldLabel { - color: var(--bui-fg-primary); - margin-right: auto; - cursor: pointer; - font-weight: var(--bui-font-weight-regular); - font-size: var(--bui-font-size-2); -} +@layer components { + .bui-FieldLabelWrapper { + display: flex; + flex-direction: column; + margin-bottom: var(--bui-space-3); + gap: var(--bui-space-1); + } -.bui-FieldSecondaryLabel { - color: var(--bui-fg-secondary); - font-weight: var(--bui-font-weight-regular); - margin-left: var(--bui-space-1); -} + .bui-FieldLabel { + color: var(--bui-fg-primary); + margin-right: auto; + cursor: pointer; + font-weight: var(--bui-font-weight-regular); + font-size: var(--bui-font-size-2); + } -.bui-FieldDescription { - font-weight: var(--bui-font-weight-regular); - font-size: var(--bui-font-size-2); - color: var(--bui-fg-secondary); - margin: 0; + .bui-FieldSecondaryLabel { + color: var(--bui-fg-secondary); + font-weight: var(--bui-font-weight-regular); + margin-left: var(--bui-space-1); + } + + .bui-FieldDescription { + font-weight: var(--bui-font-weight-regular); + font-size: var(--bui-font-size-2); + color: var(--bui-fg-secondary); + margin: 0; + } } diff --git a/packages/ui/src/components/Flex/styles.css b/packages/ui/src/components/Flex/styles.css index 96c94ab58a..7c5eee12cd 100644 --- a/packages/ui/src/components/Flex/styles.css +++ b/packages/ui/src/components/Flex/styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,9 +14,11 @@ * limitations under the License. */ -.bui-Flex { - display: flex; +@layer components { + .bui-Flex { + display: flex; - /* This helps when using `truncate` on text inside a flex container */ - min-width: 0; + /* This helps when using `truncate` on text inside a flex container */ + min-width: 0; + } } diff --git a/packages/ui/src/components/Grid/styles.css b/packages/ui/src/components/Grid/styles.css index e21191ad47..28e792ab54 100644 --- a/packages/ui/src/components/Grid/styles.css +++ b/packages/ui/src/components/Grid/styles.css @@ -1,3 +1,21 @@ -.bui-Grid { - display: grid; +/* + * 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. + */ + +@layer components { + .bui-Grid { + display: grid; + } } diff --git a/packages/ui/src/components/Header/Header.styles.css b/packages/ui/src/components/Header/Header.styles.css index 69c0065394..56f5573e0f 100644 --- a/packages/ui/src/components/Header/Header.styles.css +++ b/packages/ui/src/components/Header/Header.styles.css @@ -14,81 +14,83 @@ * limitations under the License. */ -.bui-HeaderToolbar { - margin-bottom: var(--bui-space-6); +@layer components { + .bui-HeaderToolbar { + margin-bottom: var(--bui-space-6); - &::before { - content: ''; - position: absolute; - top: 0; - left: 0px; - right: 0px; + &::before { + content: ''; + position: absolute; + top: 0; + left: 0px; + right: 0px; + height: 16px; + background-color: var(--bui-bg); + z-index: 0; + } + + &[data-has-tabs='true'] { + margin-bottom: 0; + } + } + + .bui-HeaderToolbarWrapper { + position: relative; + z-index: 1; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + background-color: var(--bui-bg-surface-1); + padding-inline: var(--bui-space-5); + border-bottom: 1px solid var(--bui-border); + color: var(--bui-fg-primary); + height: 52px; + } + + .bui-HeaderToolbarContent { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } + + .bui-HeaderToolbarName { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-3); + font-weight: var(--bui-font-weight-regular); + flex-shrink: 0; + } + + .bui-HeaderToolbarIcon { + width: 16px; height: 16px; - background-color: var(--bui-bg); - z-index: 0; + color: var(--bui-fg-primary); + + & svg { + width: 100%; + height: 100%; + } } - &[data-has-tabs='true'] { - margin-bottom: 0; + .bui-HeaderToolbarControls { + position: absolute; + right: var(--bui-space-5); + top: 50%; + transform: translateY(-50%); + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } + + .bui-HeaderTabsWrapper { + margin-bottom: var(--bui-space-4); + padding-inline: var(--bui-space-3); + border-bottom: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); } } - -.bui-HeaderToolbarWrapper { - position: relative; - z-index: 1; - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - background-color: var(--bui-bg-surface-1); - padding-inline: var(--bui-space-5); - border-bottom: 1px solid var(--bui-border); - color: var(--bui-fg-primary); - height: 52px; -} - -.bui-HeaderToolbarContent { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); -} - -.bui-HeaderToolbarName { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-3); - font-weight: var(--bui-font-weight-regular); - flex-shrink: 0; -} - -.bui-HeaderToolbarIcon { - width: 16px; - height: 16px; - color: var(--bui-fg-primary); - - & svg { - width: 100%; - height: 100%; - } -} - -.bui-HeaderToolbarControls { - position: absolute; - right: var(--bui-space-5); - top: 50%; - transform: translateY(-50%); - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); -} - -.bui-HeaderTabsWrapper { - margin-bottom: var(--bui-space-4); - padding-inline: var(--bui-space-3); - border-bottom: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); -} diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.styles.css b/packages/ui/src/components/HeaderPage/HeaderPage.styles.css index aca756872c..b85320c9d4 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.styles.css +++ b/packages/ui/src/components/HeaderPage/HeaderPage.styles.css @@ -14,34 +14,36 @@ * limitations under the License. */ -.bui-HeaderPage { - display: flex; - flex-direction: column; - gap: var(--bui-space-1); - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); -} +@layer components { + .bui-HeaderPage { + display: flex; + flex-direction: column; + gap: var(--bui-space-1); + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } -.bui-HeaderPageContent { - display: flex; - flex-direction: row; - justify-content: space-between; -} + .bui-HeaderPageContent { + display: flex; + flex-direction: row; + justify-content: space-between; + } -.bui-HeaderPageTabsWrapper { - margin-left: -8px; -} + .bui-HeaderPageTabsWrapper { + margin-left: -8px; + } -.bui-HeaderPageControls { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); -} + .bui-HeaderPageControls { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } -.bui-HeaderPageBreadcrumbs { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); + .bui-HeaderPageBreadcrumbs { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } } diff --git a/packages/ui/src/components/Icon/styles.css b/packages/ui/src/components/Icon/styles.css index a6a3f7d49c..b96d9d5f2b 100644 --- a/packages/ui/src/components/Icon/styles.css +++ b/packages/ui/src/components/Icon/styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,7 +14,9 @@ * limitations under the License. */ -.bui-Icon { - width: 1rem; - height: 1rem; +@layer components { + .bui-Icon { + width: 1rem; + height: 1rem; + } } diff --git a/packages/ui/src/components/Link/styles.css b/packages/ui/src/components/Link/styles.css index 76a56e2d7a..5931a1dfe2 100644 --- a/packages/ui/src/components/Link/styles.css +++ b/packages/ui/src/components/Link/styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,19 +14,21 @@ * limitations under the License. */ -.bui-Link { - font-family: var(--bui-font-regular); - padding: 0; - margin: 0; - cursor: pointer; - text-decoration-line: none; - display: inline-block; +@layer components { + .bui-Link { + font-family: var(--bui-font-regular); + padding: 0; + margin: 0; + cursor: pointer; + text-decoration-line: none; + display: inline-block; - &:hover { - text-decoration-line: underline; - text-decoration-style: solid; - text-decoration-thickness: min(2px, max(1px, 0.05em)); - text-underline-offset: calc(0.025em + 2px); - text-decoration-color: color-mix(in srgb, currentColor 30%, transparent); + &:hover { + text-decoration-line: underline; + text-decoration-style: solid; + text-decoration-thickness: min(2px, max(1px, 0.05em)); + text-underline-offset: calc(0.025em + 2px); + text-decoration-color: color-mix(in srgb, currentColor 30%, transparent); + } } } diff --git a/packages/ui/src/components/Menu/Menu.styles.css b/packages/ui/src/components/Menu/Menu.styles.css index 1d21233ae3..507c772d71 100644 --- a/packages/ui/src/components/Menu/Menu.styles.css +++ b/packages/ui/src/components/Menu/Menu.styles.css @@ -14,256 +14,258 @@ * limitations under the License. */ -.bui-MenuPopover { - display: flex; - flex-direction: column; - border: 1px solid var(--bui-border); - border-radius: var(--bui-radius-2); - background: var(--bui-bg-surface-1); - color: var(--bui-fg-primary); - outline: none; - transition: transform 200ms, opacity 200ms; - /* Let React Aria handle height constraints naturally */ - min-height: 0; - /* Remove overflow from popover since ScrollArea will handle it */ - overflow: hidden; - - &[data-entering], - &[data-exiting] { - transform: var(--origin); - opacity: 0; - } - - &[data-placement='top'] { - --origin: translateY(8px); - } - - &[data-placement='bottom'] { - --origin: translateY(-8px); - } - - &[data-placement='right'] { - --origin: translateX(-8px); - } - - &[data-placement='left'] { - --origin: translateX(8px); - } -} - -.bui-MenuContent { - max-height: inherit; - box-sizing: border-box; - overflow: auto; - padding: var(--bui-space-1); - min-width: 150px; - box-sizing: border-box; - outline: none; -} - -/* Ensure ScrollArea works properly within MenuRA popover */ -.bui-MenuPopover .bui-ScrollAreaRoot { - /* Take full height of popover */ - height: 100%; - min-height: 0; - flex: 1; - /* Ensure the root container has proper height constraints */ - display: flex; - flex-direction: column; -} - -.bui-MenuPopover .bui-ScrollAreaScrollbar { - margin-inline: var(--bui-space-1_5); -} - -.bui-MenuItem { - display: flex; - align-items: center; - justify-content: space-between; - height: 2rem; - padding-inline: var(--bui-space-2); - border-radius: var(--bui-radius-2); - outline: none; - cursor: default; - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-3); - gap: var(--bui-space-6); - - &[data-focused] { - background: var(--bui-bg-surface-2); +@layer components { + .bui-MenuPopover { + display: flex; + flex-direction: column; + border: 1px solid var(--bui-border); + border-radius: var(--bui-radius-2); + background: var(--bui-bg-surface-1); color: var(--bui-fg-primary); - } + outline: none; + transition: transform 200ms, opacity 200ms; + /* Let React Aria handle height constraints naturally */ + min-height: 0; + /* Remove overflow from popover since ScrollArea will handle it */ + overflow: hidden; - &[data-open] { - background: var(--bui-bg-surface-2); - color: var(--bui-fg-primary); - } + &[data-entering], + &[data-exiting] { + transform: var(--origin); + opacity: 0; + } - &[data-color='danger'] { - color: var(--bui-fg-danger); - } + &[data-placement='top'] { + --origin: translateY(8px); + } - &[data-color='danger'][data-focused] { - background: var(--bui-bg-danger); - color: var(--bui-fg-danger); - } + &[data-placement='bottom'] { + --origin: translateY(-8px); + } - &[data-has-submenu] { - & > .bui-MenuItemArrow { - display: block; + &[data-placement='right'] { + --origin: translateX(-8px); + } + + &[data-placement='left'] { + --origin: translateX(8px); } } -} -.bui-MenuItemListBox { - display: flex; - align-items: center; - justify-content: space-between; - height: 2rem; - padding-inline: var(--bui-space-2); - border-radius: var(--bui-radius-2); - outline: none; - cursor: default; - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-3); - gap: var(--bui-space-6); - - &:hover { - background: var(--bui-bg-surface-2); - color: var(--bui-fg-primary); + .bui-MenuContent { + max-height: inherit; + box-sizing: border-box; + overflow: auto; + padding: var(--bui-space-1); + min-width: 150px; + box-sizing: border-box; + outline: none; } - &[data-selected] .bui-MenuItemListBoxCheck { - & > svg { - opacity: 1; + /* Ensure ScrollArea works properly within MenuRA popover */ + .bui-MenuPopover .bui-ScrollAreaRoot { + /* Take full height of popover */ + height: 100%; + min-height: 0; + flex: 1; + /* Ensure the root container has proper height constraints */ + display: flex; + flex-direction: column; + } + + .bui-MenuPopover .bui-ScrollAreaScrollbar { + margin-inline: var(--bui-space-1_5); + } + + .bui-MenuItem { + display: flex; + align-items: center; + justify-content: space-between; + height: 2rem; + padding-inline: var(--bui-space-2); + border-radius: var(--bui-radius-2); + outline: none; + cursor: default; + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-3); + gap: var(--bui-space-6); + + &[data-focused] { + background: var(--bui-bg-surface-2); color: var(--bui-fg-primary); } - } -} -.bui-MenuItemListBoxCheck { - display: flex; - align-items: center; - justify-content: center; - width: 1rem; - height: 1rem; + &[data-open] { + background: var(--bui-bg-surface-2); + color: var(--bui-fg-primary); + } - & > svg { - opacity: 0; - width: 1rem; - height: 1rem; - } -} + &[data-color='danger'] { + color: var(--bui-fg-danger); + } -.bui-MenuItemContent { - display: flex; - align-items: center; - gap: var(--bui-space-2); + &[data-color='danger'][data-focused] { + background: var(--bui-bg-danger); + color: var(--bui-fg-danger); + } - & > svg { - width: 1rem; - height: 1rem; - } -} - -.bui-MenuItemArrow { - display: none; - width: 1rem; - height: 1rem; - - & > svg { - width: 1rem; - height: 1rem; - } -} - -.bui-MenuSection { - &:first-child .bui-MenuSectionHeader { - padding-top: 0; - } -} - -.bui-MenuSectionHeader { - height: 2rem; - display: flex; - align-items: center; - padding-top: var(--bui-space-3); - padding-left: var(--bui-space-2); - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-1); - font-weight: bold; - letter-spacing: 0.05rem; - text-transform: uppercase; -} - -.bui-MenuSeparator { - height: 1px; - background: var(--bui-border); - margin-inline: var(--bui-space-1_5); - margin-block: var(--bui-space-1); -} - -.bui-MenuSearchField { - position: relative; - font-family: var(--bui-font-regular); - width: 100%; - flex-shrink: 0; - - &[data-empty] { - .bui-MenuSearchFieldClear { - display: none; + &[data-has-submenu] { + & > .bui-MenuItemArrow { + display: block; + } } } -} -.bui-MenuSearchFieldInput { - display: flex; - align-items: center; - padding: 0 var(--bui-space-3); - border: none; - border-bottom: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - width: 100%; - height: 2rem; - cursor: inherit; - outline: none; + .bui-MenuItemListBox { + display: flex; + align-items: center; + justify-content: space-between; + height: 2rem; + padding-inline: var(--bui-space-2); + border-radius: var(--bui-radius-2); + outline: none; + cursor: default; + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-3); + gap: var(--bui-space-6); - &::-webkit-search-cancel-button, - &::-webkit-search-decoration { - -webkit-appearance: none; + &:hover { + background: var(--bui-bg-surface-2); + color: var(--bui-fg-primary); + } + + &[data-selected] .bui-MenuItemListBoxCheck { + & > svg { + opacity: 1; + color: var(--bui-fg-primary); + } + } } -} -.bui-MenuSearchFieldClear { - position: absolute; - right: var(--bui-space-2); - 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(--bui-fg-secondary); - transition: color 0.2s ease-in-out; - - & > svg { + .bui-MenuItemListBoxCheck { + display: flex; + align-items: center; + justify-content: center; width: 1rem; height: 1rem; + + & > svg { + opacity: 0; + width: 1rem; + height: 1rem; + } + } + + .bui-MenuItemContent { + display: flex; + align-items: center; + gap: var(--bui-space-2); + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuItemArrow { + display: none; + width: 1rem; + height: 1rem; + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuSection { + &:first-child .bui-MenuSectionHeader { + padding-top: 0; + } + } + + .bui-MenuSectionHeader { + height: 2rem; + display: flex; + align-items: center; + padding-top: var(--bui-space-3); + padding-left: var(--bui-space-2); + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-1); + font-weight: bold; + letter-spacing: 0.05rem; + text-transform: uppercase; + } + + .bui-MenuSeparator { + height: 1px; + background: var(--bui-border); + margin-inline: var(--bui-space-1_5); + margin-block: var(--bui-space-1); + } + + .bui-MenuSearchField { + position: relative; + font-family: var(--bui-font-regular); + width: 100%; + flex-shrink: 0; + + &[data-empty] { + .bui-MenuSearchFieldClear { + display: none; + } + } + } + + .bui-MenuSearchFieldInput { + display: flex; + align-items: center; + padding: 0 var(--bui-space-3); + border: none; + border-bottom: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + width: 100%; + height: 2rem; + cursor: inherit; + outline: none; + + &::-webkit-search-cancel-button, + &::-webkit-search-decoration { + -webkit-appearance: none; + } + } + + .bui-MenuSearchFieldClear { + position: absolute; + right: var(--bui-space-2); + 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(--bui-fg-secondary); + transition: color 0.2s ease-in-out; + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuEmptyState { + padding: var(--bui-space-1); + color: var(--bui-fg-secondary); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); } } - -.bui-MenuEmptyState { - padding: var(--bui-space-1); - color: var(--bui-fg-secondary); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); -} diff --git a/packages/ui/src/components/PasswordField/PasswordField.styles.css b/packages/ui/src/components/PasswordField/PasswordField.styles.css index 371d769ea6..55ea499a2c 100644 --- a/packages/ui/src/components/PasswordField/PasswordField.styles.css +++ b/packages/ui/src/components/PasswordField/PasswordField.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,57 +14,59 @@ * limitations under the License. */ -.bui-PasswordField { - display: flex; - flex-direction: column; - font-family: var(--bui-font-regular); - width: 100%; - flex-shrink: 0; - /* Reserve space for browser/password manager icon (e.g. 1Password) */ - --bui-passwordmanager-icon-width: var(--bui-space-1); -} - -.bui-InputVisibility { - position: absolute; - right: var(--bui-passwordmanager-icon-width); - top: 0; - bottom: 0; - background-color: transparent; - cursor: pointer; - border: none; - padding: 0; - margin: 0; - display: flex; - align-items: center; - justify-content: center; - color: var(--bui-fg-primary); - - /* Size: small */ - &[data-size='small'] { - width: 2rem; - height: 2rem; - } - &[data-size='small'] svg { - width: 1rem; - height: 1rem; +@layer components { + .bui-PasswordField { + display: flex; + flex-direction: column; + font-family: var(--bui-font-regular); + width: 100%; + flex-shrink: 0; + /* Reserve space for browser/password manager icon (e.g. 1Password) */ + --bui-passwordmanager-icon-width: var(--bui-space-1); } - /* Size: medium */ - &[data-size='medium'] { - width: 2.5rem; - height: 2.5rem; + .bui-InputVisibility { + position: absolute; + right: var(--bui-passwordmanager-icon-width); + top: 0; + bottom: 0; + background-color: transparent; + cursor: pointer; + border: none; + padding: 0; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + color: var(--bui-fg-primary); + + /* Size: small */ + &[data-size='small'] { + width: 2rem; + height: 2rem; + } + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + /* Size: medium */ + &[data-size='medium'] { + width: 2.5rem; + height: 2.5rem; + } + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } } - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; + + /* Ensure input has enough right padding for our toggle + PM icon */ + .bui-PasswordField .bui-InputWrapper[data-size='small'] .bui-Input { + padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); + } + + .bui-PasswordField .bui-InputWrapper[data-size='medium'] .bui-Input { + padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); } } - -/* Ensure input has enough right padding for our toggle + PM icon */ -.bui-PasswordField .bui-InputWrapper[data-size='small'] .bui-Input { - padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); -} - -.bui-PasswordField .bui-InputWrapper[data-size='medium'] .bui-Input { - padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); -} diff --git a/packages/ui/src/components/Popover/Popover.styles.css b/packages/ui/src/components/Popover/Popover.styles.css index 23ae5c1019..3f1cf66440 100644 --- a/packages/ui/src/components/Popover/Popover.styles.css +++ b/packages/ui/src/components/Popover/Popover.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,12 +14,14 @@ * limitations under the License. */ -.bui-Popover { - margin-right: 12px; - overflow: scroll; - background-color: var(--bui-bg-surface-1); - border: 1px solid var(--bui-border); - border-radius: var(--bui-radius-3); - padding-block: var(--bui-space-1); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +@layer components { + .bui-Popover { + margin-right: 12px; + overflow: scroll; + background-color: var(--bui-bg-surface-1); + border: 1px solid var(--bui-border); + border-radius: var(--bui-radius-3); + padding-block: var(--bui-space-1); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + } } diff --git a/packages/ui/src/components/RadioGroup/RadioGroup.styles.css b/packages/ui/src/components/RadioGroup/RadioGroup.styles.css index f12d5571e0..400a5216f4 100644 --- a/packages/ui/src/components/RadioGroup/RadioGroup.styles.css +++ b/packages/ui/src/components/RadioGroup/RadioGroup.styles.css @@ -1,95 +1,113 @@ -.bui-RadioGroup { - display: flex; - flex-direction: column; - color: var(--bui-fg-primary); -} +/* + * 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. + */ -.bui-RadioGroup[data-orientation='horizontal'] .bui-RadioGroupContent { - flex-direction: row; - gap: var(--bui-space-4); -} - -.bui-RadioGroupContent { - display: flex; - flex-direction: column; - gap: var(--bui-space-2); -} - -.bui-Radio { - display: flex; - /* This is needed so the HiddenInput is positioned correctly */ - position: relative; - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-2); - color: var(--bui-fg-primary); - forced-color-adjust: none; - - &:before { - content: ''; - display: block; - width: 1rem; - height: 1rem; - box-sizing: border-box; - border: 0.125rem solid var(--bui-border); - background: var(--bui-gray-1); - border-radius: var(--bui-radius-full); - transition: all 200ms; +@layer components { + .bui-RadioGroup { + display: flex; + flex-direction: column; + color: var(--bui-fg-primary); } - &[data-pressed]:before { - border-color: var(--bui-border); + .bui-RadioGroup[data-orientation='horizontal'] .bui-RadioGroupContent { + flex-direction: row; + gap: var(--bui-space-4); } - &[data-selected] { + .bui-RadioGroupContent { + display: flex; + flex-direction: column; + gap: var(--bui-space-2); + } + + .bui-Radio { + display: flex; + /* This is needed so the HiddenInput is positioned correctly */ + position: relative; + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-2); + color: var(--bui-fg-primary); + forced-color-adjust: none; + &:before { - border-color: var(--bui-bg-solid); - border-width: 0.25rem; + content: ''; + display: block; + width: 1rem; + height: 1rem; + box-sizing: border-box; + border: 0.125rem solid var(--bui-border); + background: var(--bui-gray-1); + border-radius: var(--bui-radius-full); + transition: all 200ms; } &[data-pressed]:before { - border-color: var(--bui-bg-solid); - } - } - - &[data-focus-visible]:before { - outline: 2px solid var(--bui-ring); - outline-offset: 2px; - } - - &[data-disabled] { - cursor: not-allowed; - color: var(--bui-fg-disabled); - - &:before { - border-color: var(--bui-border-disabled); - background: var(--bui-bg-disabled); + border-color: var(--bui-border); } - &[data-selected]:before { - border-color: var(--bui-border-disabled); - } - } + &[data-selected] { + &:before { + border-color: var(--bui-bg-solid); + border-width: 0.25rem; + } - &[data-invalid]:before { - border-color: var(--bui-border-danger); - } - - &[data-invalid][data-selected]:before { - border-color: var(--bui-border-danger); - } - - /* Ensure disabled state prevails over invalid state */ - &[data-disabled][data-invalid] { - color: var(--bui-fg-disabled); - - &:before { - border-color: var(--bui-border-disabled); - background: var(--bui-bg-disabled); + &[data-pressed]:before { + border-color: var(--bui-bg-solid); + } } - &[data-selected]:before { - border-color: var(--bui-border-disabled); + &[data-focus-visible]:before { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } + + &[data-disabled] { + cursor: not-allowed; + color: var(--bui-fg-disabled); + + &:before { + border-color: var(--bui-border-disabled); + background: var(--bui-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--bui-border-disabled); + } + } + + &[data-invalid]:before { + border-color: var(--bui-border-danger); + } + + &[data-invalid][data-selected]:before { + border-color: var(--bui-border-danger); + } + + /* Ensure disabled state prevails over invalid state */ + &[data-disabled][data-invalid] { + color: var(--bui-fg-disabled); + + &:before { + border-color: var(--bui-border-disabled); + background: var(--bui-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--bui-border-disabled); + } } } } diff --git a/packages/ui/src/components/ScrollArea/ScrollArea.styles.css b/packages/ui/src/components/ScrollArea/ScrollArea.styles.css index 209168c329..4e2fea06a6 100644 --- a/packages/ui/src/components/ScrollArea/ScrollArea.styles.css +++ b/packages/ui/src/components/ScrollArea/ScrollArea.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,52 +14,54 @@ * limitations under the License. */ -.bui-ScrollAreaRoot { - box-sizing: border-box; - width: 100%; -} - -.bui-ScrollAreaViewport { - height: 100%; - overscroll-behavior: contain; -} - -.bui-ScrollAreaContent { - display: flex; - flex-direction: column; - gap: 1rem; - padding-block: 0.75rem; - padding-left: 1rem; - padding-right: 1.5rem; -} - -.bui-ScrollAreaScrollbar { - display: flex; - justify-content: center; - background-color: var(--bui-scrollbar); - width: 0.25rem; - border-radius: 0.375rem; - margin: 0.5rem; - opacity: 0; - transition: opacity 150ms 300ms; - - &[data-hovering], - &[data-scrolling] { - opacity: 1; - transition-duration: 75ms; - transition-delay: 0ms; +@layer components { + .bui-ScrollAreaRoot { + box-sizing: border-box; + width: 100%; } - &::before { - content: ''; - position: absolute; - width: 1.25rem; + .bui-ScrollAreaViewport { height: 100%; + overscroll-behavior: contain; + } + + .bui-ScrollAreaContent { + display: flex; + flex-direction: column; + gap: 1rem; + padding-block: 0.75rem; + padding-left: 1rem; + padding-right: 1.5rem; + } + + .bui-ScrollAreaScrollbar { + display: flex; + justify-content: center; + background-color: var(--bui-scrollbar); + width: 0.25rem; + border-radius: 0.375rem; + margin: 0.5rem; + opacity: 0; + transition: opacity 150ms 300ms; + + &[data-hovering], + &[data-scrolling] { + opacity: 1; + transition-duration: 75ms; + transition-delay: 0ms; + } + + &::before { + content: ''; + position: absolute; + width: 1.25rem; + height: 100%; + } + } + + .bui-ScrollAreaThumb { + width: 100%; + border-radius: inherit; + background-color: var(--bui-scrollbar-thumb); } } - -.bui-ScrollAreaThumb { - width: 100%; - border-radius: inherit; - background-color: var(--bui-scrollbar-thumb); -} diff --git a/packages/ui/src/components/SearchField/SearchField.styles.css b/packages/ui/src/components/SearchField/SearchField.styles.css index a13c455b44..996ee1eb07 100644 --- a/packages/ui/src/components/SearchField/SearchField.styles.css +++ b/packages/ui/src/components/SearchField/SearchField.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,125 +14,127 @@ * limitations under the License. */ -.bui-SearchField { - flex: 1; - flex-shrink: 0; +@layer components { + .bui-SearchField { + flex: 1; + flex-shrink: 0; - &[data-empty] { - .bui-InputClear { - display: none; + &[data-empty] { + .bui-InputClear { + display: none; + } + } + + &[data-start-collapsed='true'] { + transition: flex-basis 0.3s ease-in-out; + padding: 0; + flex: 0 1 auto; + + &[data-collapsed='true'] { + flex-basis: 200px; + } + + &[data-collapsed='false'] { + cursor: pointer; + + &[data-size='medium'] { + flex-basis: 2.5rem; + height: 2.5rem; + } + + &[data-size='small'] { + flex-basis: 2rem; + height: 2rem; + } + + &[data-size='medium'] .bui-Input { + &::placeholder { + opacity: 0; + } + } + + &[data-size='small'] .bui-Input { + &::placeholder { + opacity: 0; + } + } + + .bui-InputWrapper { + .bui-Input[data-icon] { + padding-right: 0px; + } + } + } } } - &[data-start-collapsed='true'] { - transition: flex-basis 0.3s ease-in-out; + .bui-SearchField .bui-Input { + transition: padding 0.3s ease-in-out, border-color 0.2s ease-in-out, + outline-color 0.2s ease-in-out; + + &[data-hovered] { + border-color: var(--bui-border-hover); + } + + &[data-focused] { + border-color: var(--bui-border-pressed); + outline-width: 0px; + } + } + + .bui-SearchField .bui-InputWrapper { + .bui-Input[data-icon] { + padding-right: var(--bui-space-6); + } + } + + .bui-SearchField .bui-InputIcon { + left: 0; + display: flex; + justify-content: center; + + &[data-size='small'] { + width: var(--bui-space-8); + } + + &[data-size='medium'] { + width: var(--bui-space-10); + } + } + + .bui-InputClear { + position: absolute; + right: 0; + top: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background-color: transparent; + border: none; padding: 0; - flex: 0 1 auto; - - &[data-collapsed='true'] { - flex-basis: 200px; - } - - &[data-collapsed='false'] { - cursor: pointer; - - &[data-size='medium'] { - flex-basis: 2.5rem; - height: 2.5rem; - } - - &[data-size='small'] { - flex-basis: 2rem; - height: 2rem; - } - - &[data-size='medium'] .bui-Input { - &::placeholder { - opacity: 0; - } - } - - &[data-size='small'] .bui-Input { - &::placeholder { - opacity: 0; - } - } - - .bui-InputWrapper { - .bui-Input[data-icon] { - padding-right: 0px; - } - } - } - } -} - -.bui-SearchField .bui-Input { - transition: padding 0.3s ease-in-out, border-color 0.2s ease-in-out, - outline-color 0.2s ease-in-out; - - &[data-hovered] { - border-color: var(--bui-border-hover); + margin: 0; + cursor: pointer; + color: var(--bui-fg-secondary); + transition: color 0.2s ease-in-out; } - &[data-focused] { - border-color: var(--bui-border-pressed); - outline-width: 0px; - } -} - -.bui-SearchField .bui-InputWrapper { - .bui-Input[data-icon] { - padding-right: var(--bui-space-6); - } -} - -.bui-SearchField .bui-InputIcon { - left: 0; - display: flex; - justify-content: center; - - &[data-size='small'] { - width: var(--bui-space-8); + .bui-InputClear:hover { + color: var(--bui-fg-primary); } - &[data-size='medium'] { - width: var(--bui-space-10); + .bui-InputClear[data-size='small'] { + width: 2rem; + height: 2rem; + } + + .bui-InputClear[data-size='medium'] { + width: 2.5rem; + height: 2.5rem; + } + + .bui-InputClear svg { + width: 1rem; + height: 1rem; } } - -.bui-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(--bui-fg-secondary); - transition: color 0.2s ease-in-out; -} - -.bui-InputClear:hover { - color: var(--bui-fg-primary); -} - -.bui-InputClear[data-size='small'] { - width: 2rem; - height: 2rem; -} - -.bui-InputClear[data-size='medium'] { - width: 2.5rem; - height: 2.5rem; -} - -.bui-InputClear svg { - width: 1rem; - height: 1rem; -} diff --git a/packages/ui/src/components/Select/Select.styles.css b/packages/ui/src/components/Select/Select.styles.css index 2cbadfda32..a8dbe759dc 100644 --- a/packages/ui/src/components/Select/Select.styles.css +++ b/packages/ui/src/components/Select/Select.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,163 +14,165 @@ * limitations under the License. */ -.bui-Select[data-invalid] { - & .bui-SelectTrigger { - border-color: var(--bui-fg-danger); - } -} - -.bui-SelectTrigger { - box-sizing: border-box; - border-radius: var(--bui-radius-3); - border: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - display: flex; - justify-content: space-between; - align-items: center; - cursor: pointer; - gap: var(--bui-space-2); - width: 100%; - - & svg { - flex-shrink: 0; - color: var(--bui-fg-secondary); +@layer components { + .bui-Select[data-invalid] { + & .bui-SelectTrigger { + border-color: var(--bui-fg-danger); + } } - &[data-size='small'] { - height: 2rem; - padding-inline: var(--bui-space-3); + .bui-SelectTrigger { + box-sizing: border-box; + border-radius: var(--bui-radius-3); + border: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + gap: var(--bui-space-2); + width: 100%; + + & svg { + flex-shrink: 0; + color: var(--bui-fg-secondary); + } + + &[data-size='small'] { + height: 2rem; + padding-inline: var(--bui-space-3); + } + + &[data-size='medium'] { + height: 3rem; + padding-inline: var(--bui-space-4); + } + + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } + + &::placeholder { + color: var(--bui-fg-secondary); + } + + &:hover { + transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; + border-color: var(--bui-border-hover); + } + + &:focus-visible { + border-color: var(--bui-border-pressed); + outline: 0; + } + + &[data-invalid] { + border-color: var(--bui-fg-danger); + } + &[data-invalid]:hover { + border-width: 2px; + } + + &[data-invalid]:focus-visible { + border-width: 2px; + } + + &[disabled] { + cursor: not-allowed; + border-color: var(--bui-border-disabled); + color: var(--bui-fg-disabled); + } + + &[disabled] .bui-SelectValue { + color: var(--bui-fg-disabled); + } + + &[data-popup-open] .bui-SelectIcon { + transform: rotate(180deg); + } } - &[data-size='medium'] { - height: 3rem; - padding-inline: var(--bui-space-4); - } - - &[data-size='small'] svg { - width: 1rem; - height: 1rem; - } - - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; - } - - &::placeholder { - color: var(--bui-fg-secondary); - } - - &:hover { - transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; - border-color: var(--bui-border-hover); - } - - &:focus-visible { - border-color: var(--bui-border-pressed); - outline: 0; - } - - &[data-invalid] { - border-color: var(--bui-fg-danger); - } - &[data-invalid]:hover { - border-width: 2px; - } - - &[data-invalid]:focus-visible { - border-width: 2px; - } - - &[disabled] { - cursor: not-allowed; - border-color: var(--bui-border-disabled); - color: var(--bui-fg-disabled); - } - - &[disabled] .bui-SelectValue { - color: var(--bui-fg-disabled); - } - - &[data-popup-open] .bui-SelectIcon { - transform: rotate(180deg); - } -} - -.bui-SelectValue { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - width: 100%; - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - text-align: left; - - & .bui-SelectItemIndicator { - display: none; - } - - &[disabled] { - color: var(--bui-fg-disabled); - } -} - -.bui-SelectItem { - position: relative; - width: var(--anchor-width); - display: grid; - grid-template-areas: 'icon text'; - grid-template-columns: 1rem 1fr; - align-items: center; - padding-block: var(--bui-space-2); - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-4); - color: var(--bui-fg-primary); - border-radius: var(--bui-radius-3); - cursor: pointer; - user-select: none; - font-size: var(--bui-font-size-3); - gap: var(--bui-space-1); - outline: none; - - &[data-focused] { - z-index: 0; - position: relative; + .bui-SelectValue { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: 100%; + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); color: var(--bui-fg-primary); + text-align: left; + + & .bui-SelectItemIndicator { + display: none; + } + + &[disabled] { + color: var(--bui-fg-disabled); + } } - &[data-focused]::before { - content: ''; - z-index: -1; - position: absolute; - inset-block: 0; - inset-inline: 0.25rem; - border-radius: 0.25rem; - background-color: var(--bui-bg-tint-hover); + .bui-SelectItem { + position: relative; + width: var(--anchor-width); + display: grid; + grid-template-areas: 'icon text'; + grid-template-columns: 1rem 1fr; + align-items: center; + padding-block: var(--bui-space-2); + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-4); + color: var(--bui-fg-primary); + border-radius: var(--bui-radius-3); + cursor: pointer; + user-select: none; + font-size: var(--bui-font-size-3); + gap: var(--bui-space-1); + outline: none; + + &[data-focused] { + z-index: 0; + position: relative; + color: var(--bui-fg-primary); + } + + &[data-focused]::before { + content: ''; + z-index: -1; + position: absolute; + inset-block: 0; + inset-inline: 0.25rem; + border-radius: 0.25rem; + background-color: var(--bui-bg-tint-hover); + } + + &[data-disabled] { + cursor: not-allowed; + color: var(--bui-fg-disabled); + } + + &[data-selected] .bui-SelectItemIndicator { + opacity: 1; + } } - &[data-disabled] { - cursor: not-allowed; - color: var(--bui-fg-disabled); + .bui-SelectItemIndicator { + grid-area: icon; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 0.2s ease-in-out; } - &[data-selected] .bui-SelectItemIndicator { - opacity: 1; + .bui-SelectItemLabel { + flex: 1; + grid-area: text; } } - -.bui-SelectItemIndicator { - grid-area: icon; - display: flex; - align-items: center; - justify-content: center; - opacity: 0; - transition: opacity 0.2s ease-in-out; -} - -.bui-SelectItemLabel { - flex: 1; - grid-area: text; -} diff --git a/packages/ui/src/components/Skeleton/Skeleton.styles.css b/packages/ui/src/components/Skeleton/Skeleton.styles.css index bbbb6deaeb..cbf297d24d 100644 --- a/packages/ui/src/components/Skeleton/Skeleton.styles.css +++ b/packages/ui/src/components/Skeleton/Skeleton.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,12 +14,14 @@ * limitations under the License. */ -.bui-Skeleton { - animation: var(--bui-animate-pulse); - background-color: var(--bui-bg-surface-2); - border-radius: var(--bui-radius-2); -} +@layer components { + .bui-Skeleton { + animation: var(--bui-animate-pulse); + background-color: var(--bui-bg-surface-2); + border-radius: var(--bui-radius-2); + } -.bui-Skeleton[data-rounded='true'] { - border-radius: var(--bui-radius-full); + .bui-Skeleton[data-rounded='true'] { + border-radius: var(--bui-radius-full); + } } diff --git a/packages/ui/src/components/Switch/Switch.styles.css b/packages/ui/src/components/Switch/Switch.styles.css index ee2a24d013..58735e2b78 100644 --- a/packages/ui/src/components/Switch/Switch.styles.css +++ b/packages/ui/src/components/Switch/Switch.styles.css @@ -14,61 +14,63 @@ * limitations under the License. */ -.bui-Switch { - display: flex; - /* This is needed so the HiddenInput is positioned correctly */ - position: relative; - align-items: center; - gap: var(--bui-space-3); - font-size: var(--bui-font-size-3); - color: var(--bui-fg-primary); - cursor: pointer; - - &[data-pressed] .bui-SwitchIndicator { - &:before { - background: var(--bui-fg-solid); - } - } - - &[data-selected] { - .bui-SwitchIndicator { - background: var(--bui-bg-solid); +@layer components { + .bui-Switch { + display: flex; + /* This is needed so the HiddenInput is positioned correctly */ + position: relative; + align-items: center; + gap: var(--bui-space-3); + font-size: var(--bui-font-size-3); + color: var(--bui-fg-primary); + cursor: pointer; + &[data-pressed] .bui-SwitchIndicator { &:before { background: var(--bui-fg-solid); - transform: translateX(100%); } } - &[data-pressed] { - .indicator { - background: var(--bui-gray-3); + &[data-selected] { + .bui-SwitchIndicator { + background: var(--bui-bg-solid); + + &:before { + background: var(--bui-fg-solid); + transform: translateX(100%); + } } + + &[data-pressed] { + .indicator { + background: var(--bui-gray-3); + } + } + } + + &[data-focus-visible] .bui-SwitchIndicator { + outline: 2px solid; + outline-offset: 2px; } } - &[data-focus-visible] .bui-SwitchIndicator { - outline: 2px solid; - outline-offset: 2px; - } -} - -.bui-SwitchIndicator { - width: 2rem; - height: 1.143rem; - border: 2px; - background: var(--bui-gray-3); - border-radius: 1.143rem; - transition: all 200ms; - - &:before { - content: ''; - display: block; - margin: 0.143rem; - width: 0.857rem; - height: 0.857rem; - background: var(--bui-fg-solid); - border-radius: 16px; + .bui-SwitchIndicator { + width: 2rem; + height: 1.143rem; + border: 2px; + background: var(--bui-gray-3); + border-radius: 1.143rem; transition: all 200ms; + + &:before { + content: ''; + display: block; + margin: 0.143rem; + width: 0.857rem; + height: 0.857rem; + background: var(--bui-fg-solid); + border-radius: 16px; + transition: all 200ms; + } } } diff --git a/packages/ui/src/components/Table/Table.styles.css b/packages/ui/src/components/Table/Table.styles.css index 84d417604a..0bb49be742 100644 --- a/packages/ui/src/components/Table/Table.styles.css +++ b/packages/ui/src/components/Table/Table.styles.css @@ -14,136 +14,138 @@ * limitations under the License. */ -.bui-Table { - width: 100%; - caption-side: bottom; - border-collapse: collapse; -} - -.bui-TableHeader { - border-bottom: 1px solid var(--bui-border); - transition: color 0.2s ease-in-out; -} - -.bui-TableHead { - text-align: left; - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); - color: var(--bui-fg-primary); -} - -.bui-TableHeadSortButton { - cursor: pointer; - user-select: none; - display: inline-flex; - align-items: center; - gap: var(--bui-space-1); - - &:hover svg { - opacity: 0.5; +@layer components { + .bui-Table { + width: 100%; + caption-side: bottom; + border-collapse: collapse; } - & svg { - opacity: 0; - transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; + .bui-TableHeader { + border-bottom: 1px solid var(--bui-border); + transition: color 0.2s ease-in-out; } - &[data-sort-order='asc'] svg { - opacity: 1; - transform: rotate(0); + .bui-TableHead { + text-align: left; + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + color: var(--bui-fg-primary); } - &[data-sort-order='desc'] svg { - opacity: 1; - transform: rotate(180deg); - } -} - -.bui-TableBody { - color: var(--bui-fg-primary); -} - -.bui-TableRow { - border-bottom: 1px solid var(--bui-border); - transition: color 0.2s ease-in-out; - - &[data-react-aria-pressable='true'] { + .bui-TableHeadSortButton { cursor: pointer; + user-select: none; + display: inline-flex; + align-items: center; + gap: var(--bui-space-1); + + &:hover svg { + opacity: 0.5; + } + + & svg { + opacity: 0; + transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; + } + + &[data-sort-order='asc'] svg { + opacity: 1; + transform: rotate(0); + } + + &[data-sort-order='desc'] svg { + opacity: 1; + transform: rotate(180deg); + } + } + + .bui-TableBody { + color: var(--bui-fg-primary); + } + + .bui-TableRow { + border-bottom: 1px solid var(--bui-border); + transition: color 0.2s ease-in-out; + + &[data-react-aria-pressable='true'] { + cursor: pointer; + } + } + + .bui-TableBody .bui-TableRow:hover { + background-color: var(--bui-gray-2); + } + + .bui-TableCell { + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + } + + .bui-TableCell { + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + } + + .bui-TableCellContentWrapper { + display: inline-flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } + + .bui-TableCellIcon, + .bui-TableCellIcon svg { + display: inline-flex; + align-items: center; + color: var(--bui-fg-primary); + } + + .bui-TableCellContent { + display: flex; + flex-direction: column; + gap: var(--bui-space-0_5); + } + + .bui-TableCellProfile { + display: flex; + flex-direction: row; + gap: var(--bui-space-2); + align-items: center; + } + + .bui-TableCellProfileAvatar { + display: inline-flex; + justify-content: center; + align-items: center; + vertical-align: middle; + border-radius: 100%; + user-select: none; + font-weight: 500; + color: var(--bui-fg-primary); + background-color: var(--bui-bg-surface-2); + font-size: 1rem; + line-height: 1; + overflow: hidden; + height: 1.25rem; + width: 1.25rem; + } + + .bui-TableCellProfileAvatarImage { + object-fit: cover; + height: 100%; + width: 100%; + } + + .bui-TableCellProfileAvatarFallback { + align-items: center; + display: flex; + justify-content: center; + height: 100%; + width: 100%; + font-size: var(--bui-font-size-2); + font-weight: var(--bui-font-weight-regular); + box-shadow: inset 0 0 0 1px var(--bui-border); + border-radius: var(--bui-radius-full); } } - -.bui-TableBody .bui-TableRow:hover { - background-color: var(--bui-gray-2); -} - -.bui-TableCell { - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); -} - -.bui-TableCell { - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); -} - -.bui-TableCellContentWrapper { - display: inline-flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); -} - -.bui-TableCellIcon, -.bui-TableCellIcon svg { - display: inline-flex; - align-items: center; - color: var(--bui-fg-primary); -} - -.bui-TableCellContent { - display: flex; - flex-direction: column; - gap: var(--bui-space-0_5); -} - -.bui-TableCellProfile { - display: flex; - flex-direction: row; - gap: var(--bui-space-2); - align-items: center; -} - -.bui-TableCellProfileAvatar { - display: inline-flex; - justify-content: center; - align-items: center; - vertical-align: middle; - border-radius: 100%; - user-select: none; - font-weight: 500; - color: var(--bui-fg-primary); - background-color: var(--bui-bg-surface-2); - font-size: 1rem; - line-height: 1; - overflow: hidden; - height: 1.25rem; - width: 1.25rem; -} - -.bui-TableCellProfileAvatarImage { - object-fit: cover; - height: 100%; - width: 100%; -} - -.bui-TableCellProfileAvatarFallback { - align-items: center; - display: flex; - justify-content: center; - height: 100%; - width: 100%; - font-size: var(--bui-font-size-2); - font-weight: var(--bui-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--bui-border); - border-radius: var(--bui-radius-full); -} diff --git a/packages/ui/src/components/TablePagination/TablePagination.styles.css b/packages/ui/src/components/TablePagination/TablePagination.styles.css index f7cbb44fc2..e305967ebe 100644 --- a/packages/ui/src/components/TablePagination/TablePagination.styles.css +++ b/packages/ui/src/components/TablePagination/TablePagination.styles.css @@ -1,23 +1,41 @@ -.bui-DataTablePagination { - display: flex; - align-items: center; - justify-content: space-between; - padding-top: var(--bui-space-5); -} +/* + * 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. + */ -.bui-DataTablePagination--left { - display: flex; - align-items: center; - justify-content: space-between; -} +@layer components { + .bui-DataTablePagination { + display: flex; + align-items: center; + justify-content: space-between; + padding-top: var(--bui-space-5); + } -.bui-DataTablePagination--right { - display: flex; - align-items: center; - justify-content: space-between; - gap: var(--bui-space-2); -} + .bui-DataTablePagination--left { + display: flex; + align-items: center; + justify-content: space-between; + } -.bui-DataTablePagination--select { - min-width: 10.5rem; + .bui-DataTablePagination--right { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--bui-space-2); + } + + .bui-DataTablePagination--select { + min-width: 10.5rem; + } } diff --git a/packages/ui/src/components/Tabs/Tabs.styles.css b/packages/ui/src/components/Tabs/Tabs.styles.css index 819fe458ed..a58d123559 100644 --- a/packages/ui/src/components/Tabs/Tabs.styles.css +++ b/packages/ui/src/components/Tabs/Tabs.styles.css @@ -1,82 +1,100 @@ -.bui-Tabs { - /* 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; - --active-transition-duration: 0s; +/* + * 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. + */ - --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; -} +@layer components { + .bui-Tabs { + /* 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; + --active-transition-duration: 0s; -.bui-TabList { - display: flex; - flex-direction: row; -} + --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; + } -.bui-TabListWrapper { - position: relative; -} + .bui-TabList { + display: flex; + flex-direction: row; + } -.bui-Tab { - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-secondary); - height: 36px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - position: relative; - z-index: 2; - padding-inline: var(--bui-space-2); + .bui-TabListWrapper { + position: relative; + } - &[data-selected='true'] { - color: var(--bui-fg-primary); + .bui-Tab { + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-secondary); + height: 36px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + position: relative; + z-index: 2; + padding-inline: var(--bui-space-2); + + &[data-selected='true'] { + color: var(--bui-fg-primary); + } + } + + .bui-TabActive { + content: ''; + position: absolute; + left: calc(var(--active-tab-left) + var(--bui-space-2)); + bottom: -1px; + width: calc(var(--active-tab-width) - var(--bui-space-4)); + height: 1px; + background-color: var(--bui-fg-primary); + border-radius: 4px; + transition: left var(--active-transition-duration) ease-out, + opacity 0.15s ease-out, width var(--active-transition-duration) ease-out; + opacity: 1; + } + + .bui-TabHovered { + 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(--bui-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; + } + + .bui-TabPanel { + padding-inline: var(--bui-space-2); + padding-top: var(--bui-space-4); } } - -.bui-TabActive { - content: ''; - position: absolute; - left: calc(var(--active-tab-left) + var(--bui-space-2)); - bottom: -1px; - width: calc(var(--active-tab-width) - var(--bui-space-4)); - height: 1px; - background-color: var(--bui-fg-primary); - border-radius: 4px; - transition: left var(--active-transition-duration) ease-out, - opacity 0.15s ease-out, width var(--active-transition-duration) ease-out; - opacity: 1; -} - -.bui-TabHovered { - 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(--bui-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; -} - -.bui-TabPanel { - padding-inline: var(--bui-space-2); - padding-top: var(--bui-space-4); -} diff --git a/packages/ui/src/components/TagGroup/TagGroup.styles.css b/packages/ui/src/components/TagGroup/TagGroup.styles.css index 9da99a4290..096d003f83 100644 --- a/packages/ui/src/components/TagGroup/TagGroup.styles.css +++ b/packages/ui/src/components/TagGroup/TagGroup.styles.css @@ -14,77 +14,79 @@ * limitations under the License. */ -.bui-TagList { - display: flex; - flex-wrap: wrap; - gap: var(--bui-space-2); -} +@layer components { + .bui-TagList { + display: flex; + flex-wrap: wrap; + gap: var(--bui-space-2); + } -.bui-Tag { - color: var(--bui-fg-primary); - background-color: var(--bui-gray-2); - border-radius: var(--bui-radius-2); - display: flex; - align-items: center; - justify-content: center; - font-weight: var(--bui-font-weight-regular); - gap: var(--bui-space-1); - transition-property: background-color, box-shadow, color; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - box-sizing: border-box; -} + .bui-Tag { + color: var(--bui-fg-primary); + background-color: var(--bui-gray-2); + border-radius: var(--bui-radius-2); + display: flex; + align-items: center; + justify-content: center; + font-weight: var(--bui-font-weight-regular); + gap: var(--bui-space-1); + transition-property: background-color, box-shadow, color; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + box-sizing: border-box; + } -.bui-Tag[data-size='small'] { - height: 26px; - padding: 0 var(--bui-space-2); - font-size: var(--bui-font-size-1); -} + .bui-Tag[data-size='small'] { + height: 26px; + padding: 0 var(--bui-space-2); + font-size: var(--bui-font-size-1); + } -.bui-Tag[data-size='medium'] { - height: 32px; - padding: 0 var(--bui-space-2); - font-size: var(--bui-font-size-2); -} + .bui-Tag[data-size='medium'] { + height: 32px; + padding: 0 var(--bui-space-2); + font-size: var(--bui-font-size-2); + } -.bui-Tag[data-hovered] { - background-color: var(--bui-gray-3); - cursor: pointer; -} + .bui-Tag[data-hovered] { + background-color: var(--bui-gray-3); + cursor: pointer; + } -.bui-Tag[data-focus-visible] { - outline: 2px solid var(--bui-ring); - outline-offset: 1px; -} + .bui-Tag[data-focus-visible] { + outline: 2px solid var(--bui-ring); + outline-offset: 1px; + } -.bui-Tag[data-selected] { - box-shadow: inset 0 0 0 1px var(--bui-gray-8); -} + .bui-Tag[data-selected] { + box-shadow: inset 0 0 0 1px var(--bui-gray-8); + } -.bui-Tag[data-disabled] { - color: var(--bui-fg-disabled); - cursor: not-allowed; -} + .bui-Tag[data-disabled] { + color: var(--bui-fg-disabled); + cursor: not-allowed; + } -.bui-TagRemoveButton { - background-color: transparent; - border: none; - cursor: pointer; - color: var(--bui-fg-primary); - padding: 0; - margin: 0; - width: 1rem; - height: 1rem; -} - -.bui-TagIcon { - display: flex; - align-items: center; - justify-content: center; - transition: color 0.2s ease-in-out; - - svg { + .bui-TagRemoveButton { + background-color: transparent; + border: none; + cursor: pointer; + color: var(--bui-fg-primary); + padding: 0; + margin: 0; width: 1rem; height: 1rem; } + + .bui-TagIcon { + display: flex; + align-items: center; + justify-content: center; + transition: color 0.2s ease-in-out; + + svg { + width: 1rem; + height: 1rem; + } + } } diff --git a/packages/ui/src/components/Text/styles.css b/packages/ui/src/components/Text/styles.css index 562d2a5356..47f38fe30d 100644 --- a/packages/ui/src/components/Text/styles.css +++ b/packages/ui/src/components/Text/styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,90 +14,92 @@ * limitations under the License. */ -.bui-Text { - font-family: var(--bui-font-regular); - padding: 0; - margin: 0; -} +@layer components { + .bui-Text { + font-family: var(--bui-font-regular); + padding: 0; + margin: 0; + } -.bui-Text[data-variant='title-large'] { - font-size: var(--bui-font-size-8); - line-height: 140%; -} + .bui-Text[data-variant='title-large'] { + font-size: var(--bui-font-size-8); + line-height: 140%; + } -.bui-Text[data-variant='title-medium'] { - font-size: var(--bui-font-size-7); - line-height: 140%; -} + .bui-Text[data-variant='title-medium'] { + font-size: var(--bui-font-size-7); + line-height: 140%; + } -.bui-Text[data-variant='title-small'] { - font-size: var(--bui-font-size-6); - line-height: 140%; -} + .bui-Text[data-variant='title-small'] { + font-size: var(--bui-font-size-6); + line-height: 140%; + } -.bui-Text[data-variant='title-x-small'] { - font-size: var(--bui-font-size-5); - line-height: 140%; -} + .bui-Text[data-variant='title-x-small'] { + font-size: var(--bui-font-size-5); + line-height: 140%; + } -.bui-Text[data-variant='body-large'] { - font-size: var(--bui-font-size-4); - line-height: 140%; -} + .bui-Text[data-variant='body-large'] { + font-size: var(--bui-font-size-4); + line-height: 140%; + } -.bui-Text[data-variant='body-medium'] { - font-size: var(--bui-font-size-3); - line-height: 140%; -} + .bui-Text[data-variant='body-medium'] { + font-size: var(--bui-font-size-3); + line-height: 140%; + } -.bui-Text[data-variant='body-small'] { - font-size: var(--bui-font-size-2); - line-height: 140%; -} + .bui-Text[data-variant='body-small'] { + font-size: var(--bui-font-size-2); + line-height: 140%; + } -.bui-Text[data-variant='body-x-small'] { - font-size: var(--bui-font-size-1); - line-height: 140%; -} + .bui-Text[data-variant='body-x-small'] { + font-size: var(--bui-font-size-1); + line-height: 140%; + } -.bui-Text[data-weight='regular'] { - font-weight: var(--bui-font-weight-regular); -} + .bui-Text[data-weight='regular'] { + font-weight: var(--bui-font-weight-regular); + } -.bui-Text[data-weight='bold'] { - font-weight: var(--bui-font-weight-bold); -} + .bui-Text[data-weight='bold'] { + font-weight: var(--bui-font-weight-bold); + } -.bui-Text[data-color='primary'] { - color: var(--bui-fg-primary); -} + .bui-Text[data-color='primary'] { + color: var(--bui-fg-primary); + } -.bui-Text[data-color='secondary'] { - color: var(--bui-fg-secondary); -} + .bui-Text[data-color='secondary'] { + color: var(--bui-fg-secondary); + } -.bui-Text[data-color='danger'] { - color: var(--bui-fg-danger); -} + .bui-Text[data-color='danger'] { + color: var(--bui-fg-danger); + } -.bui-Text[data-color='warning'] { - color: var(--bui-fg-warning); -} + .bui-Text[data-color='warning'] { + color: var(--bui-fg-warning); + } -.bui-Text[data-color='success'] { - color: var(--bui-fg-success); -} + .bui-Text[data-color='success'] { + color: var(--bui-fg-success); + } -.bui-Text[data-truncate] { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} + .bui-Text[data-truncate] { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } -.bui-Text[data-as='span'], -.bui-Text[data-as='label'], -.bui-Text[data-as='strong'], -.bui-Text[data-as='em'], -.bui-Text[data-as='small'] { - display: inline-block; + .bui-Text[data-as='span'], + .bui-Text[data-as='label'], + .bui-Text[data-as='strong'], + .bui-Text[data-as='em'], + .bui-Text[data-as='small'] { + display: inline-block; + } } diff --git a/packages/ui/src/components/TextField/TextField.styles.css b/packages/ui/src/components/TextField/TextField.styles.css index 792d5d85c9..170349a760 100644 --- a/packages/ui/src/components/TextField/TextField.styles.css +++ b/packages/ui/src/components/TextField/TextField.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,105 +14,107 @@ * limitations under the License. */ -.bui-TextField { - display: flex; - flex-direction: column; - font-family: var(--bui-font-regular); - width: 100%; - flex-shrink: 0; -} - -.bui-InputWrapper { - position: relative; - - &[data-size='small'] .bui-Input { - height: 2rem; +@layer components { + .bui-TextField { + display: flex; + flex-direction: column; + font-family: var(--bui-font-regular); + width: 100%; + flex-shrink: 0; } - &[data-size='medium'] .bui-Input { - height: 2.5rem; + .bui-InputWrapper { + position: relative; + + &[data-size='small'] .bui-Input { + height: 2rem; + } + + &[data-size='medium'] .bui-Input { + height: 2.5rem; + } + + &[data-size='small'] .bui-Input[data-icon] { + padding-left: var(--bui-space-8); + } + + &[data-size='medium'] .bui-Input[data-icon] { + padding-left: var(--bui-space-9); + } } - &[data-size='small'] .bui-Input[data-icon] { - padding-left: var(--bui-space-8); + .bui-InputIcon { + position: absolute; + left: var(--bui-space-3); + top: 50%; + transform: translateY(-50%); + margin-right: var(--bui-space-1); + color: var(--bui-fg-primary); + flex-shrink: 0; + pointer-events: none; + /* To animate the icon when the input is collapsed */ + transition: left 0.2s ease-in-out; + + &[data-size='small'], + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + &[data-size='medium'], + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } } - &[data-size='medium'] .bui-Input[data-icon] { - padding-left: var(--bui-space-9); - } -} - -.bui-InputIcon { - position: absolute; - left: var(--bui-space-3); - top: 50%; - transform: translateY(-50%); - margin-right: var(--bui-space-1); - color: var(--bui-fg-primary); - flex-shrink: 0; - pointer-events: none; - /* To animate the icon when the input is collapsed */ - transition: left 0.2s ease-in-out; - - &[data-size='small'], - &[data-size='small'] svg { - width: 1rem; - height: 1rem; - } - - &[data-size='medium'], - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; - } -} - -.bui-Input { - display: flex; - align-items: center; - padding: 0 var(--bui-space-3); - border-radius: var(--bui-radius-2); - border: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; - width: 100%; - height: 100%; - cursor: inherit; - - &::-webkit-search-cancel-button, - &::-webkit-search-decoration { - -webkit-appearance: none; - } - - &::placeholder { - color: var(--bui-fg-secondary); - } - - &[data-focused] { - outline-color: var(--bui-border-pressed); - outline-width: 0px; - } - - &[data-hovered] { - border-color: var(--bui-border-hover); - } - - &[data-focused] { - border-color: var(--bui-border-pressed); - outline-width: 0px; - } - - &[data-invalid] { - border-color: var(--bui-fg-danger); - } - - &[data-disabled] { - opacity: 0.5; - cursor: not-allowed; - border: 1px solid var(--bui-border-disabled); + .bui-Input { + display: flex; + align-items: center; + padding: 0 var(--bui-space-3); + border-radius: var(--bui-radius-2); + border: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; + width: 100%; + height: 100%; + cursor: inherit; + + &::-webkit-search-cancel-button, + &::-webkit-search-decoration { + -webkit-appearance: none; + } + + &::placeholder { + color: var(--bui-fg-secondary); + } + + &[data-focused] { + outline-color: var(--bui-border-pressed); + outline-width: 0px; + } + + &[data-hovered] { + border-color: var(--bui-border-hover); + } + + &[data-focused] { + border-color: var(--bui-border-pressed); + outline-width: 0px; + } + + &[data-invalid] { + border-color: var(--bui-fg-danger); + } + + &[data-disabled] { + opacity: 0.5; + cursor: not-allowed; + border: 1px solid var(--bui-border-disabled); + } } } diff --git a/packages/ui/src/components/Tooltip/Tooltip.styles.css b/packages/ui/src/components/Tooltip/Tooltip.styles.css index f80a12bbc1..7c035888ed 100644 --- a/packages/ui/src/components/Tooltip/Tooltip.styles.css +++ b/packages/ui/src/components/Tooltip/Tooltip.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 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,110 +14,112 @@ * limitations under the License. */ -.bui-Tooltip { - box-shadow: 0 10px 15px -3px rgba(0 0 0 / 0.1), - 0 4px 6px -4px rgba(0 0 0 / 0.1); - border-radius: 4px; - background: var(--bui-bg-surface-1); - border: 1px solid var(--bui-gray-3); - forced-color-adjust: none; - outline: none; - padding: var(--bui-space-2) var(--bui-space-3); - max-width: 240px; - /* fixes FF gap */ - transform: translate3d(0, 0, 0); - transition: transform 200ms, opacity 200ms; - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - color: var(--bui-fg-primary); +@layer components { + .bui-Tooltip { + box-shadow: 0 10px 15px -3px rgba(0 0 0 / 0.1), + 0 4px 6px -4px rgba(0 0 0 / 0.1); + border-radius: 4px; + background: var(--bui-bg-surface-1); + border: 1px solid var(--bui-gray-3); + forced-color-adjust: none; + outline: none; + padding: var(--bui-space-2) var(--bui-space-3); + max-width: 240px; + /* fixes FF gap */ + transform: translate3d(0, 0, 0); + transition: transform 200ms, opacity 200ms; + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + color: var(--bui-fg-primary); - &[data-entering], - &[data-exiting] { - transform: var(--origin); - opacity: 0; + &[data-entering], + &[data-exiting] { + transform: var(--origin); + opacity: 0; + } + + --tooltip-offset: var(--bui-space-3); + + &[data-placement='top'] { + margin-bottom: var(--tooltip-offset); + --origin: translateY(4px); + } + + &[data-placement='right'] { + margin-left: var(--tooltip-offset); + --origin: translateX(-4px); + } + + &[data-placement='bottom'] { + margin-top: var(--tooltip-offset); + --origin: translateY(-4px); + } + + &[data-placement='left'] { + margin-right: var(--tooltip-offset); + --origin: translateX(4px); + } } - --tooltip-offset: var(--bui-space-3); + .bui-TooltipArrow { + & svg { + display: block; - &[data-placement='top'] { - margin-bottom: var(--tooltip-offset); - --origin: translateY(4px); - } - - &[data-placement='right'] { - margin-left: var(--tooltip-offset); - --origin: translateX(-4px); - } - - &[data-placement='bottom'] { - margin-top: var(--tooltip-offset); - --origin: translateY(-4px); - } - - &[data-placement='left'] { - margin-right: var(--tooltip-offset); - --origin: translateX(4px); - } -} - -.bui-TooltipArrow { - & svg { - display: block; - - /* The tooltip is rendered overlaying the main + /* The tooltip is rendered overlaying the main tooltip element by 1px. This causes the borders to overlap, which causes minor visual artifacts with transparent border colors. To mitigate this, we split the stroke and fill across separate elements in order to guarantee that the stroke is always overlaying a consistent color. */ - path:nth-child(1) { - fill: var(--bui-bg-surface-1); - } + path:nth-child(1) { + fill: var(--bui-bg-surface-1); + } - path:nth-child(2) { - fill: var(--bui-gray-3); - } + path:nth-child(2) { + fill: var(--bui-gray-3); + } - /* The arrow svg overlaps the tooltip by 2px, so we + /* The arrow svg overlaps the tooltip by 2px, so we need to adjust the margins accordingly. */ - --tooltip-arrow-overlap: -2px; - } - - &[data-placement='top'] svg { - margin-top: var(--tooltip-arrow-overlap); - } - - &[data-placement='bottom'] svg { - margin-bottom: var(--tooltip-arrow-overlap); - transform: rotate(180deg); - } - - &[data-placement='right'] svg { - margin-right: var(--tooltip-arrow-overlap); - transform: rotate(90deg); - } - - &[data-placement='left'] svg { - margin-left: var(--tooltip-arrow-overlap); - transform: rotate(-90deg); - } -} - -[data-theme='dark'] { - .bui-Tooltip { - background: var(--bui-bg-surface-2); - box-shadow: none; - border: 1px solid var(--bui-gray-4); - } - - .bui-TooltipArrow { - svg path:nth-child(1) { - fill: var(--bui-bg-surface-2); + --tooltip-arrow-overlap: -2px; } - svg path:nth-child(2) { - fill: var(--bui-gray-4); + &[data-placement='top'] svg { + margin-top: var(--tooltip-arrow-overlap); + } + + &[data-placement='bottom'] svg { + margin-bottom: var(--tooltip-arrow-overlap); + transform: rotate(180deg); + } + + &[data-placement='right'] svg { + margin-right: var(--tooltip-arrow-overlap); + transform: rotate(90deg); + } + + &[data-placement='left'] svg { + margin-left: var(--tooltip-arrow-overlap); + transform: rotate(-90deg); + } + } + + [data-theme='dark'] { + .bui-Tooltip { + background: var(--bui-bg-surface-2); + box-shadow: none; + border: 1px solid var(--bui-gray-4); + } + + .bui-TooltipArrow { + svg path:nth-child(1) { + fill: var(--bui-bg-surface-2); + } + + svg path:nth-child(2) { + fill: var(--bui-gray-4); + } } } } From 9e0c6d6eaf351ba27cc2eaba0ed7b2c72a44b30f Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 9 Oct 2025 11:36:33 +0100 Subject: [PATCH 130/244] Improve core Signed-off-by: Charles de Dreuille --- packages/ui/css/styles.css | 21572 +++++++++++++++++---------------- packages/ui/src/css/core.css | 196 +- 2 files changed, 10802 insertions(+), 10966 deletions(-) diff --git a/packages/ui/css/styles.css b/packages/ui/css/styles.css index 6ca70c9c43..65fe585e39 100644 --- a/packages/ui/css/styles.css +++ b/packages/ui/css/styles.css @@ -1,4 +1,141 @@ /*! modern-normalize v3.0.1 | MIT License | https://github.com/sindresorhus/modern-normalize */ +@layer tokens { + :root { + --bui-font-regular: system-ui; + --bui-font-monospace: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace; + --bui-font-weight-regular: 400; + --bui-font-weight-bold: 600; + --bui-font-size-1: .625rem; + --bui-font-size-2: .75rem; + --bui-font-size-3: .875rem; + --bui-font-size-4: 1rem; + --bui-font-size-5: 1.25rem; + --bui-font-size-6: 1.5rem; + --bui-font-size-7: 2rem; + --bui-font-size-8: 3rem; + --bui-font-size-9: 4rem; + --bui-font-size-10: 5.75rem; + --bui-space: .25rem; + --bui-space-0_5: calc(var(--bui-space) * .5); + --bui-space-1: var(--bui-space); + --bui-space-1_5: calc(var(--bui-space) * 1.5); + --bui-space-2: calc(var(--bui-space) * 2); + --bui-space-3: calc(var(--bui-space) * 3); + --bui-space-4: calc(var(--bui-space) * 4); + --bui-space-5: calc(var(--bui-space) * 5); + --bui-space-6: calc(var(--bui-space) * 6); + --bui-space-7: calc(var(--bui-space) * 7); + --bui-space-8: calc(var(--bui-space) * 8); + --bui-space-9: calc(var(--bui-space) * 9); + --bui-space-10: calc(var(--bui-space) * 10); + --bui-space-11: calc(var(--bui-space) * 11); + --bui-space-12: calc(var(--bui-space) * 12); + --bui-space-13: calc(var(--bui-space) * 13); + --bui-space-14: calc(var(--bui-space) * 14); + --bui-radius-1: calc(.125rem); + --bui-radius-2: calc(.25rem); + --bui-radius-3: calc(.5rem); + --bui-radius-4: calc(.75rem); + --bui-radius-5: calc(1rem); + --bui-radius-6: calc(1.25rem); + --bui-radius-full: 9999px; + --bui-black: #000; + --bui-white: #fff; + --bui-gray-1: #f8f8f8; + --bui-gray-2: #ececec; + --bui-gray-3: #d9d9d9; + --bui-gray-4: #c1c1c1; + --bui-gray-5: #9e9e9e; + --bui-gray-6: #8c8c8c; + --bui-gray-7: #757575; + --bui-gray-8: #595959; + --bui-bg: var(--bui-gray-1); + --bui-bg-surface-1: var(--bui-white); + --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-solid: #1f5493; + --bui-bg-solid-hover: #163a66; + --bui-bg-solid-pressed: #0f2b4e; + --bui-bg-solid-disabled: #ebebeb; + --bui-bg-tint: transparent; + --bui-bg-tint-hover: #1f549366; + --bui-bg-tint-pressed: #1f549399; + --bui-bg-tint-disabled: #ebebeb; + --bui-bg-danger: #feebe7; + --bui-bg-warning: #fff2b2; + --bui-bg-success: #e6f6eb; + --bui-fg-primary: var(--bui-black); + --bui-fg-secondary: var(--bui-gray-7); + --bui-fg-link: #1f5493; + --bui-fg-link-hover: #1f2d5c; + --bui-fg-disabled: #9e9e9e; + --bui-fg-solid: var(--bui-white); + --bui-fg-solid-disabled: #9c9c9c; + --bui-fg-tint: #1f5493; + --bui-fg-tint-disabled: var(--bui-gray-5); + --bui-fg-danger: #e22b2b; + --bui-fg-warning: #e36d05; + --bui-fg-success: #1db954; + --bui-border: #0000001a; + --bui-border-hover: #0003; + --bui-border-pressed: #0006; + --bui-border-disabled: #0000001a; + --bui-border-danger: #f87a7a; + --bui-border-warning: #e36d05; + --bui-border-success: #53db83; + --bui-ring: #1f5493; + --bui-scrollbar: #a0a0a03b; + --bui-scrollbar-thumb: #a0a0a0; + --bui-animate-pulse: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite; + } + + [data-theme-mode="dark"] { + --bui-gray-1: #191919; + --bui-gray-2: #242424; + --bui-gray-3: #373737; + --bui-gray-4: #464646; + --bui-gray-5: #575757; + --bui-gray-6: #7b7b7b; + --bui-gray-7: #9e9e9e; + --bui-gray-8: #b4b4b4; + --bui-bg: #333; + --bui-bg-surface-1: #424242; + --bui-bg-surface-2: var(--bui-gray-2); + --bui-bg-solid: #9cc9ff; + --bui-bg-solid-hover: #83b9fd; + --bui-bg-solid-pressed: #83b9fd; + --bui-bg-solid-disabled: #222; + --bui-bg-tint: transparent; + --bui-bg-tint-hover: #9cc9ff1f; + --bui-bg-tint-pressed: #9cc9ff29; + --bui-bg-tint-disabled: transparent; + --bui-bg-danger: #3b1219; + --bui-bg-warning: #302008; + --bui-bg-success: #132d21; + --bui-fg-primary: var(--bui-white); + --bui-fg-secondary: var(--bui-gray-7); + --bui-fg-link: #9cc9ff; + --bui-fg-link-hover: #7eb5f7; + --bui-fg-disabled: var(--bui-gray-7); + --bui-fg-solid: #101821; + --bui-fg-solid-disabled: var(--bui-gray-5); + --bui-fg-tint: #9cc9ff; + --bui-fg-tint-disabled: var(--bui-gray-5); + --bui-fg-danger: #e22b2b; + --bui-fg-warning: #e36d05; + --bui-fg-success: #1db954; + --bui-border: #ffffff1f; + --bui-border-hover: #fff6; + --bui-border-pressed: #ffffff80; + --bui-border-disabled: #fff3; + --bui-border-danger: #f87a7a; + --bui-border-warning: #e36d05; + --bui-border-success: #53db83; + --bui-ring: #1f5493; + --bui-scrollbar: #3636363a; + --bui-scrollbar-thumb: #575757; + } +} + @layer base { *, :before, :after { box-sizing: border-box; @@ -87,10986 +224,10857 @@ summary { display: list-item; } -} -.bui-p { - padding: var(--p); -} - -.bui-p-0\.5 { - padding: var(--bui-space-0_5); -} - -.bui-p-1 { - padding: var(--bui-space-1); -} - -.bui-p-1\.5 { - padding: var(--bui-space-1_5); -} - -.bui-p-2 { - padding: var(--bui-space-2); -} - -.bui-p-3 { - padding: var(--bui-space-3); -} - -.bui-p-4 { - padding: var(--bui-space-4); -} - -.bui-p-5 { - padding: var(--bui-space-5); -} - -.bui-p-6 { - padding: var(--bui-space-6); -} - -.bui-p-7 { - padding: var(--bui-space-7); -} - -.bui-p-8 { - padding: var(--bui-space-8); -} - -.bui-p-9 { - padding: var(--bui-space-9); -} - -.bui-p-10 { - padding: var(--bui-space-10); -} - -.bui-p-11 { - padding: var(--bui-space-11); -} - -.bui-p-12 { - padding: var(--bui-space-12); -} - -.bui-p-13 { - padding: var(--bui-space-13); -} - -.bui-p-14 { - padding: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-p { - padding: var(--p-xs); - } - - .xs\:bui-p-0\.5 { - padding: var(--bui-space-0_5); - } - - .xs\:bui-p-1 { - padding: var(--bui-space-1); - } - - .xs\:bui-p-1\.5 { - padding: var(--bui-space-1_5); - } - - .xs\:bui-p-2 { - padding: var(--bui-space-2); - } - - .xs\:bui-p-3 { - padding: var(--bui-space-3); - } - - .xs\:bui-p-4 { - padding: var(--bui-space-4); - } - - .xs\:bui-p-5 { - padding: var(--bui-space-5); - } - - .xs\:bui-p-6 { - padding: var(--bui-space-6); - } - - .xs\:bui-p-7 { - padding: var(--bui-space-7); - } - - .xs\:bui-p-8 { - padding: var(--bui-space-8); - } - - .xs\:bui-p-9 { - padding: var(--bui-space-9); - } - - .xs\:bui-p-10 { - padding: var(--bui-space-10); - } - - .xs\:bui-p-11 { - padding: var(--bui-space-11); - } - - .xs\:bui-p-12 { - padding: var(--bui-space-12); - } - - .xs\:bui-p-13 { - padding: var(--bui-space-13); - } - - .xs\:bui-p-14 { - padding: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-p { - padding: var(--p-sm); - } - - .sm\:bui-p-0\.5 { - padding: var(--bui-space-0_5); - } - - .sm\:bui-p-1 { - padding: var(--bui-space-1); - } - - .sm\:bui-p-1\.5 { - padding: var(--bui-space-1_5); - } - - .sm\:bui-p-2 { - padding: var(--bui-space-2); - } - - .sm\:bui-p-3 { - padding: var(--bui-space-3); - } - - .sm\:bui-p-4 { - padding: var(--bui-space-4); - } - - .sm\:bui-p-5 { - padding: var(--bui-space-5); - } - - .sm\:bui-p-6 { - padding: var(--bui-space-6); - } - - .sm\:bui-p-7 { - padding: var(--bui-space-7); - } - - .sm\:bui-p-8 { - padding: var(--bui-space-8); - } - - .sm\:bui-p-9 { - padding: var(--bui-space-9); - } - - .sm\:bui-p-10 { - padding: var(--bui-space-10); - } - - .sm\:bui-p-11 { - padding: var(--bui-space-11); - } - - .sm\:bui-p-12 { - padding: var(--bui-space-12); - } - - .sm\:bui-p-13 { - padding: var(--bui-space-13); - } - - .sm\:bui-p-14 { - padding: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-p { - padding: var(--p-md); - } - - .md\:bui-p-0\.5 { - padding: var(--bui-space-0_5); - } - - .md\:bui-p-1 { - padding: var(--bui-space-1); - } - - .md\:bui-p-1\.5 { - padding: var(--bui-space-1_5); - } - - .md\:bui-p-2 { - padding: var(--bui-space-2); - } - - .md\:bui-p-3 { - padding: var(--bui-space-3); - } - - .md\:bui-p-4 { - padding: var(--bui-space-4); - } - - .md\:bui-p-5 { - padding: var(--bui-space-5); - } - - .md\:bui-p-6 { - padding: var(--bui-space-6); - } - - .md\:bui-p-7 { - padding: var(--bui-space-7); - } - - .md\:bui-p-8 { - padding: var(--bui-space-8); - } - - .md\:bui-p-9 { - padding: var(--bui-space-9); - } - - .md\:bui-p-10 { - padding: var(--bui-space-10); - } - - .md\:bui-p-11 { - padding: var(--bui-space-11); - } - - .md\:bui-p-12 { - padding: var(--bui-space-12); - } - - .md\:bui-p-13 { - padding: var(--bui-space-13); - } - - .md\:bui-p-14 { - padding: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-p { - padding: var(--p-lg); - } - - .lg\:bui-p-0\.5 { - padding: var(--bui-space-0_5); - } - - .lg\:bui-p-1 { - padding: var(--bui-space-1); - } - - .lg\:bui-p-1\.5 { - padding: var(--bui-space-1_5); - } - - .lg\:bui-p-2 { - padding: var(--bui-space-2); - } - - .lg\:bui-p-3 { - padding: var(--bui-space-3); - } - - .lg\:bui-p-4 { - padding: var(--bui-space-4); - } - - .lg\:bui-p-5 { - padding: var(--bui-space-5); - } - - .lg\:bui-p-6 { - padding: var(--bui-space-6); - } - - .lg\:bui-p-7 { - padding: var(--bui-space-7); - } - - .lg\:bui-p-8 { - padding: var(--bui-space-8); - } - - .lg\:bui-p-9 { - padding: var(--bui-space-9); - } - - .lg\:bui-p-10 { - padding: var(--bui-space-10); - } - - .lg\:bui-p-11 { - padding: var(--bui-space-11); - } - - .lg\:bui-p-12 { - padding: var(--bui-space-12); - } - - .lg\:bui-p-13 { - padding: var(--bui-space-13); - } - - .lg\:bui-p-14 { - padding: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-p { - padding: var(--p-xl); - } - - .xl\:bui-p-0\.5 { - padding: var(--bui-space-0_5); - } - - .xl\:bui-p-1 { - padding: var(--bui-space-1); - } - - .xl\:bui-p-1\.5 { - padding: var(--bui-space-1_5); - } - - .xl\:bui-p-2 { - padding: var(--bui-space-2); - } - - .xl\:bui-p-3 { - padding: var(--bui-space-3); - } - - .xl\:bui-p-4 { - padding: var(--bui-space-4); - } - - .xl\:bui-p-5 { - padding: var(--bui-space-5); - } - - .xl\:bui-p-6 { - padding: var(--bui-space-6); - } - - .xl\:bui-p-7 { - padding: var(--bui-space-7); - } - - .xl\:bui-p-8 { - padding: var(--bui-space-8); - } - - .xl\:bui-p-9 { - padding: var(--bui-space-9); - } - - .xl\:bui-p-10 { - padding: var(--bui-space-10); - } - - .xl\:bui-p-11 { - padding: var(--bui-space-11); - } - - .xl\:bui-p-12 { - padding: var(--bui-space-12); - } - - .xl\:bui-p-13 { - padding: var(--bui-space-13); - } - - .xl\:bui-p-14 { - padding: var(--bui-space-14); - } -} - -.bui-pl { - padding-left: var(--pl); -} - -.bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); -} - -.bui-pl-1 { - padding-left: var(--bui-space-1); -} - -.bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); -} - -.bui-pl-2 { - padding-left: var(--bui-space-2); -} - -.bui-pl-3 { - padding-left: var(--bui-space-3); -} - -.bui-pl-4 { - padding-left: var(--bui-space-4); -} - -.bui-pl-5 { - padding-left: var(--bui-space-5); -} - -.bui-pl-6 { - padding-left: var(--bui-space-6); -} - -.bui-pl-7 { - padding-left: var(--bui-space-7); -} - -.bui-pl-8 { - padding-left: var(--bui-space-8); -} - -.bui-pl-9 { - padding-left: var(--bui-space-9); -} - -.bui-pl-10 { - padding-left: var(--bui-space-10); -} - -.bui-pl-11 { - padding-left: var(--bui-space-11); -} - -.bui-pl-12 { - padding-left: var(--bui-space-12); -} - -.bui-pl-13 { - padding-left: var(--bui-space-13); -} - -.bui-pl-14 { - padding-left: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-pl { - padding-left: var(--pl-xs); - } - - .xs\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); - } - - .xs\:bui-pl-1 { - padding-left: var(--bui-space-1); - } - - .xs\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); - } - - .xs\:bui-pl-2 { - padding-left: var(--bui-space-2); - } - - .xs\:bui-pl-3 { - padding-left: var(--bui-space-3); - } - - .xs\:bui-pl-4 { - padding-left: var(--bui-space-4); - } - - .xs\:bui-pl-5 { - padding-left: var(--bui-space-5); - } - - .xs\:bui-pl-6 { - padding-left: var(--bui-space-6); - } - - .xs\:bui-pl-7 { - padding-left: var(--bui-space-7); - } - - .xs\:bui-pl-8 { - padding-left: var(--bui-space-8); - } - - .xs\:bui-pl-9 { - padding-left: var(--bui-space-9); - } - - .xs\:bui-pl-10 { - padding-left: var(--bui-space-10); - } - - .xs\:bui-pl-11 { - padding-left: var(--bui-space-11); - } - - .xs\:bui-pl-12 { - padding-left: var(--bui-space-12); - } - - .xs\:bui-pl-13 { - padding-left: var(--bui-space-13); - } - - .xs\:bui-pl-14 { - padding-left: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-pl { - padding-left: var(--pl-sm); - } - - .sm\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); - } - - .sm\:bui-pl-1 { - padding-left: var(--bui-space-1); - } - - .sm\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); - } - - .sm\:bui-pl-2 { - padding-left: var(--bui-space-2); - } - - .sm\:bui-pl-3 { - padding-left: var(--bui-space-3); - } - - .sm\:bui-pl-4 { - padding-left: var(--bui-space-4); - } - - .sm\:bui-pl-5 { - padding-left: var(--bui-space-5); - } - - .sm\:bui-pl-6 { - padding-left: var(--bui-space-6); - } - - .sm\:bui-pl-7 { - padding-left: var(--bui-space-7); - } - - .sm\:bui-pl-8 { - padding-left: var(--bui-space-8); - } - - .sm\:bui-pl-9 { - padding-left: var(--bui-space-9); - } - - .sm\:bui-pl-10 { - padding-left: var(--bui-space-10); - } - - .sm\:bui-pl-11 { - padding-left: var(--bui-space-11); - } - - .sm\:bui-pl-12 { - padding-left: var(--bui-space-12); - } - - .sm\:bui-pl-13 { - padding-left: var(--bui-space-13); - } - - .sm\:bui-pl-14 { - padding-left: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-pl { - padding-left: var(--pl-md); - } - - .md\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); - } - - .md\:bui-pl-1 { - padding-left: var(--bui-space-1); - } - - .md\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); - } - - .md\:bui-pl-2 { - padding-left: var(--bui-space-2); - } - - .md\:bui-pl-3 { - padding-left: var(--bui-space-3); - } - - .md\:bui-pl-4 { - padding-left: var(--bui-space-4); - } - - .md\:bui-pl-5 { - padding-left: var(--bui-space-5); - } - - .md\:bui-pl-6 { - padding-left: var(--bui-space-6); - } - - .md\:bui-pl-7 { - padding-left: var(--bui-space-7); - } - - .md\:bui-pl-8 { - padding-left: var(--bui-space-8); - } - - .md\:bui-pl-9 { - padding-left: var(--bui-space-9); - } - - .md\:bui-pl-10 { - padding-left: var(--bui-space-10); - } - - .md\:bui-pl-11 { - padding-left: var(--bui-space-11); - } - - .md\:bui-pl-12 { - padding-left: var(--bui-space-12); - } - - .md\:bui-pl-13 { - padding-left: var(--bui-space-13); - } - - .md\:bui-pl-14 { - padding-left: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-pl { - padding-left: var(--pl-lg); - } - - .lg\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); - } - - .lg\:bui-pl-1 { - padding-left: var(--bui-space-1); - } - - .lg\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); - } - - .lg\:bui-pl-2 { - padding-left: var(--bui-space-2); - } - - .lg\:bui-pl-3 { - padding-left: var(--bui-space-3); - } - - .lg\:bui-pl-4 { - padding-left: var(--bui-space-4); - } - - .lg\:bui-pl-5 { - padding-left: var(--bui-space-5); - } - - .lg\:bui-pl-6 { - padding-left: var(--bui-space-6); - } - - .lg\:bui-pl-7 { - padding-left: var(--bui-space-7); - } - - .lg\:bui-pl-8 { - padding-left: var(--bui-space-8); - } - - .lg\:bui-pl-9 { - padding-left: var(--bui-space-9); - } - - .lg\:bui-pl-10 { - padding-left: var(--bui-space-10); - } - - .lg\:bui-pl-11 { - padding-left: var(--bui-space-11); - } - - .lg\:bui-pl-12 { - padding-left: var(--bui-space-12); - } - - .lg\:bui-pl-13 { - padding-left: var(--bui-space-13); - } - - .lg\:bui-pl-14 { - padding-left: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-pl { - padding-left: var(--pl-xl); - } - - .xl\:bui-pl-0\.5 { - padding-left: var(--bui-space-0_5); - } - - .xl\:bui-pl-1 { - padding-left: var(--bui-space-1); - } - - .xl\:bui-pl-1\.5 { - padding-left: var(--bui-space-1_5); - } - - .xl\:bui-pl-2 { - padding-left: var(--bui-space-2); - } - - .xl\:bui-pl-3 { - padding-left: var(--bui-space-3); - } - - .xl\:bui-pl-4 { - padding-left: var(--bui-space-4); - } - - .xl\:bui-pl-5 { - padding-left: var(--bui-space-5); - } - - .xl\:bui-pl-6 { - padding-left: var(--bui-space-6); - } - - .xl\:bui-pl-7 { - padding-left: var(--bui-space-7); - } - - .xl\:bui-pl-8 { - padding-left: var(--bui-space-8); - } - - .xl\:bui-pl-9 { - padding-left: var(--bui-space-9); - } - - .xl\:bui-pl-10 { - padding-left: var(--bui-space-10); - } - - .xl\:bui-pl-11 { - padding-left: var(--bui-space-11); - } - - .xl\:bui-pl-12 { - padding-left: var(--bui-space-12); - } - - .xl\:bui-pl-13 { - padding-left: var(--bui-space-13); - } - - .xl\:bui-pl-14 { - padding-left: var(--bui-space-14); - } -} - -.bui-pr { - padding-right: var(--pr); -} - -.bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); -} - -.bui-pr-1 { - padding-right: var(--bui-space-1); -} - -.bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); -} - -.bui-pr-2 { - padding-right: var(--bui-space-2); -} - -.bui-pr-3 { - padding-right: var(--bui-space-3); -} - -.bui-pr-4 { - padding-right: var(--bui-space-4); -} - -.bui-pr-5 { - padding-right: var(--bui-space-5); -} - -.bui-pr-6 { - padding-right: var(--bui-space-6); -} - -.bui-pr-7 { - padding-right: var(--bui-space-7); -} - -.bui-pr-8 { - padding-right: var(--bui-space-8); -} - -.bui-pr-9 { - padding-right: var(--bui-space-9); -} - -.bui-pr-10 { - padding-right: var(--bui-space-10); -} - -.bui-pr-11 { - padding-right: var(--bui-space-11); -} - -.bui-pr-12 { - padding-right: var(--bui-space-12); -} - -.bui-pr-13 { - padding-right: var(--bui-space-13); -} - -.bui-pr-14 { - padding-right: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-pr { - padding-right: var(--pr-xs); - } - - .xs\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); - } - - .xs\:bui-pr-1 { - padding-right: var(--bui-space-1); - } - - .xs\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); - } - - .xs\:bui-pr-2 { - padding-right: var(--bui-space-2); - } - - .xs\:bui-pr-3 { - padding-right: var(--bui-space-3); - } - - .xs\:bui-pr-4 { - padding-right: var(--bui-space-4); - } - - .xs\:bui-pr-5 { - padding-right: var(--bui-space-5); - } - - .xs\:bui-pr-6 { - padding-right: var(--bui-space-6); - } - - .xs\:bui-pr-7 { - padding-right: var(--bui-space-7); - } - - .xs\:bui-pr-8 { - padding-right: var(--bui-space-8); - } - - .xs\:bui-pr-9 { - padding-right: var(--bui-space-9); - } - - .xs\:bui-pr-10 { - padding-right: var(--bui-space-10); - } - - .xs\:bui-pr-11 { - padding-right: var(--bui-space-11); - } - - .xs\:bui-pr-12 { - padding-right: var(--bui-space-12); - } - - .xs\:bui-pr-13 { - padding-right: var(--bui-space-13); - } - - .xs\:bui-pr-14 { - padding-right: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-pr { - padding-right: var(--pr-sm); - } - - .sm\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); - } - - .sm\:bui-pr-1 { - padding-right: var(--bui-space-1); - } - - .sm\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); - } - - .sm\:bui-pr-2 { - padding-right: var(--bui-space-2); - } - - .sm\:bui-pr-3 { - padding-right: var(--bui-space-3); - } - - .sm\:bui-pr-4 { - padding-right: var(--bui-space-4); - } - - .sm\:bui-pr-5 { - padding-right: var(--bui-space-5); - } - - .sm\:bui-pr-6 { - padding-right: var(--bui-space-6); - } - - .sm\:bui-pr-7 { - padding-right: var(--bui-space-7); - } - - .sm\:bui-pr-8 { - padding-right: var(--bui-space-8); - } - - .sm\:bui-pr-9 { - padding-right: var(--bui-space-9); - } - - .sm\:bui-pr-10 { - padding-right: var(--bui-space-10); - } - - .sm\:bui-pr-11 { - padding-right: var(--bui-space-11); - } - - .sm\:bui-pr-12 { - padding-right: var(--bui-space-12); - } - - .sm\:bui-pr-13 { - padding-right: var(--bui-space-13); - } - - .sm\:bui-pr-14 { - padding-right: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-pr { - padding-right: var(--pr-md); - } - - .md\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); - } - - .md\:bui-pr-1 { - padding-right: var(--bui-space-1); - } - - .md\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); - } - - .md\:bui-pr-2 { - padding-right: var(--bui-space-2); - } - - .md\:bui-pr-3 { - padding-right: var(--bui-space-3); - } - - .md\:bui-pr-4 { - padding-right: var(--bui-space-4); - } - - .md\:bui-pr-5 { - padding-right: var(--bui-space-5); - } - - .md\:bui-pr-6 { - padding-right: var(--bui-space-6); - } - - .md\:bui-pr-7 { - padding-right: var(--bui-space-7); - } - - .md\:bui-pr-8 { - padding-right: var(--bui-space-8); - } - - .md\:bui-pr-9 { - padding-right: var(--bui-space-9); - } - - .md\:bui-pr-10 { - padding-right: var(--bui-space-10); - } - - .md\:bui-pr-11 { - padding-right: var(--bui-space-11); - } - - .md\:bui-pr-12 { - padding-right: var(--bui-space-12); - } - - .md\:bui-pr-13 { - padding-right: var(--bui-space-13); - } - - .md\:bui-pr-14 { - padding-right: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-pr { - padding-right: var(--pr-lg); - } - - .lg\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); - } - - .lg\:bui-pr-1 { - padding-right: var(--bui-space-1); - } - - .lg\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); - } - - .lg\:bui-pr-2 { - padding-right: var(--bui-space-2); - } - - .lg\:bui-pr-3 { - padding-right: var(--bui-space-3); - } - - .lg\:bui-pr-4 { - padding-right: var(--bui-space-4); - } - - .lg\:bui-pr-5 { - padding-right: var(--bui-space-5); - } - - .lg\:bui-pr-6 { - padding-right: var(--bui-space-6); - } - - .lg\:bui-pr-7 { - padding-right: var(--bui-space-7); - } - - .lg\:bui-pr-8 { - padding-right: var(--bui-space-8); - } - - .lg\:bui-pr-9 { - padding-right: var(--bui-space-9); - } - - .lg\:bui-pr-10 { - padding-right: var(--bui-space-10); - } - - .lg\:bui-pr-11 { - padding-right: var(--bui-space-11); - } - - .lg\:bui-pr-12 { - padding-right: var(--bui-space-12); - } - - .lg\:bui-pr-13 { - padding-right: var(--bui-space-13); - } - - .lg\:bui-pr-14 { - padding-right: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-pr { - padding-right: var(--pr-xl); - } - - .xl\:bui-pr-0\.5 { - padding-right: var(--bui-space-0_5); - } - - .xl\:bui-pr-1 { - padding-right: var(--bui-space-1); - } - - .xl\:bui-pr-1\.5 { - padding-right: var(--bui-space-1_5); - } - - .xl\:bui-pr-2 { - padding-right: var(--bui-space-2); - } - - .xl\:bui-pr-3 { - padding-right: var(--bui-space-3); - } - - .xl\:bui-pr-4 { - padding-right: var(--bui-space-4); - } - - .xl\:bui-pr-5 { - padding-right: var(--bui-space-5); - } - - .xl\:bui-pr-6 { - padding-right: var(--bui-space-6); - } - - .xl\:bui-pr-7 { - padding-right: var(--bui-space-7); - } - - .xl\:bui-pr-8 { - padding-right: var(--bui-space-8); - } - - .xl\:bui-pr-9 { - padding-right: var(--bui-space-9); - } - - .xl\:bui-pr-10 { - padding-right: var(--bui-space-10); - } - - .xl\:bui-pr-11 { - padding-right: var(--bui-space-11); - } - - .xl\:bui-pr-12 { - padding-right: var(--bui-space-12); - } - - .xl\:bui-pr-13 { - padding-right: var(--bui-space-13); - } - - .xl\:bui-pr-14 { - padding-right: var(--bui-space-14); - } -} - -.bui-pt { - padding-top: var(--pt); -} - -.bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); -} - -.bui-pt-1 { - padding-top: var(--bui-space-1); -} - -.bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); -} - -.bui-pt-2 { - padding-top: var(--bui-space-2); -} - -.bui-pt-3 { - padding-top: var(--bui-space-3); -} - -.bui-pt-4 { - padding-top: var(--bui-space-4); -} - -.bui-pt-5 { - padding-top: var(--bui-space-5); -} - -.bui-pt-6 { - padding-top: var(--bui-space-6); -} - -.bui-pt-7 { - padding-top: var(--bui-space-7); -} - -.bui-pt-8 { - padding-top: var(--bui-space-8); -} - -.bui-pt-9 { - padding-top: var(--bui-space-9); -} - -.bui-pt-10 { - padding-top: var(--bui-space-10); -} - -.bui-pt-11 { - padding-top: var(--bui-space-11); -} - -.bui-pt-12 { - padding-top: var(--bui-space-12); -} - -.bui-pt-13 { - padding-top: var(--bui-space-13); -} - -.bui-pt-14 { - padding-top: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-pt { - padding-top: var(--pt-xs); - } - - .xs\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); - } - - .xs\:bui-pt-1 { - padding-top: var(--bui-space-1); - } - - .xs\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); - } - - .xs\:bui-pt-2 { - padding-top: var(--bui-space-2); - } - - .xs\:bui-pt-3 { - padding-top: var(--bui-space-3); - } - - .xs\:bui-pt-4 { - padding-top: var(--bui-space-4); - } - - .xs\:bui-pt-5 { - padding-top: var(--bui-space-5); - } - - .xs\:bui-pt-6 { - padding-top: var(--bui-space-6); - } - - .xs\:bui-pt-7 { - padding-top: var(--bui-space-7); - } - - .xs\:bui-pt-8 { - padding-top: var(--bui-space-8); - } - - .xs\:bui-pt-9 { - padding-top: var(--bui-space-9); - } - - .xs\:bui-pt-10 { - padding-top: var(--bui-space-10); - } - - .xs\:bui-pt-11 { - padding-top: var(--bui-space-11); - } - - .xs\:bui-pt-12 { - padding-top: var(--bui-space-12); - } - - .xs\:bui-pt-13 { - padding-top: var(--bui-space-13); - } - - .xs\:bui-pt-14 { - padding-top: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-pt { - padding-top: var(--pt-sm); - } - - .sm\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); - } - - .sm\:bui-pt-1 { - padding-top: var(--bui-space-1); - } - - .sm\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); - } - - .sm\:bui-pt-2 { - padding-top: var(--bui-space-2); - } - - .sm\:bui-pt-3 { - padding-top: var(--bui-space-3); - } - - .sm\:bui-pt-4 { - padding-top: var(--bui-space-4); - } - - .sm\:bui-pt-5 { - padding-top: var(--bui-space-5); - } - - .sm\:bui-pt-6 { - padding-top: var(--bui-space-6); - } - - .sm\:bui-pt-7 { - padding-top: var(--bui-space-7); - } - - .sm\:bui-pt-8 { - padding-top: var(--bui-space-8); - } - - .sm\:bui-pt-9 { - padding-top: var(--bui-space-9); - } - - .sm\:bui-pt-10 { - padding-top: var(--bui-space-10); - } - - .sm\:bui-pt-11 { - padding-top: var(--bui-space-11); - } - - .sm\:bui-pt-12 { - padding-top: var(--bui-space-12); - } - - .sm\:bui-pt-13 { - padding-top: var(--bui-space-13); - } - - .sm\:bui-pt-14 { - padding-top: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-pt { - padding-top: var(--pt-md); - } - - .md\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); - } - - .md\:bui-pt-1 { - padding-top: var(--bui-space-1); - } - - .md\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); - } - - .md\:bui-pt-2 { - padding-top: var(--bui-space-2); - } - - .md\:bui-pt-3 { - padding-top: var(--bui-space-3); - } - - .md\:bui-pt-4 { - padding-top: var(--bui-space-4); - } - - .md\:bui-pt-5 { - padding-top: var(--bui-space-5); - } - - .md\:bui-pt-6 { - padding-top: var(--bui-space-6); - } - - .md\:bui-pt-7 { - padding-top: var(--bui-space-7); - } - - .md\:bui-pt-8 { - padding-top: var(--bui-space-8); - } - - .md\:bui-pt-9 { - padding-top: var(--bui-space-9); - } - - .md\:bui-pt-10 { - padding-top: var(--bui-space-10); - } - - .md\:bui-pt-11 { - padding-top: var(--bui-space-11); - } - - .md\:bui-pt-12 { - padding-top: var(--bui-space-12); - } - - .md\:bui-pt-13 { - padding-top: var(--bui-space-13); - } - - .md\:bui-pt-14 { - padding-top: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-pt { - padding-top: var(--pt-lg); - } - - .lg\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); - } - - .lg\:bui-pt-1 { - padding-top: var(--bui-space-1); - } - - .lg\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); - } - - .lg\:bui-pt-2 { - padding-top: var(--bui-space-2); - } - - .lg\:bui-pt-3 { - padding-top: var(--bui-space-3); - } - - .lg\:bui-pt-4 { - padding-top: var(--bui-space-4); - } - - .lg\:bui-pt-5 { - padding-top: var(--bui-space-5); - } - - .lg\:bui-pt-6 { - padding-top: var(--bui-space-6); - } - - .lg\:bui-pt-7 { - padding-top: var(--bui-space-7); - } - - .lg\:bui-pt-8 { - padding-top: var(--bui-space-8); - } - - .lg\:bui-pt-9 { - padding-top: var(--bui-space-9); - } - - .lg\:bui-pt-10 { - padding-top: var(--bui-space-10); - } - - .lg\:bui-pt-11 { - padding-top: var(--bui-space-11); - } - - .lg\:bui-pt-12 { - padding-top: var(--bui-space-12); - } - - .lg\:bui-pt-13 { - padding-top: var(--bui-space-13); - } - - .lg\:bui-pt-14 { - padding-top: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-pt { - padding-top: var(--pt-xl); - } - - .xl\:bui-pt-0\.5 { - padding-top: var(--bui-space-0_5); - } - - .xl\:bui-pt-1 { - padding-top: var(--bui-space-1); - } - - .xl\:bui-pt-1\.5 { - padding-top: var(--bui-space-1_5); - } - - .xl\:bui-pt-2 { - padding-top: var(--bui-space-2); - } - - .xl\:bui-pt-3 { - padding-top: var(--bui-space-3); - } - - .xl\:bui-pt-4 { - padding-top: var(--bui-space-4); - } - - .xl\:bui-pt-5 { - padding-top: var(--bui-space-5); - } - - .xl\:bui-pt-6 { - padding-top: var(--bui-space-6); - } - - .xl\:bui-pt-7 { - padding-top: var(--bui-space-7); - } - - .xl\:bui-pt-8 { - padding-top: var(--bui-space-8); - } - - .xl\:bui-pt-9 { - padding-top: var(--bui-space-9); - } - - .xl\:bui-pt-10 { - padding-top: var(--bui-space-10); - } - - .xl\:bui-pt-11 { - padding-top: var(--bui-space-11); - } - - .xl\:bui-pt-12 { - padding-top: var(--bui-space-12); - } - - .xl\:bui-pt-13 { - padding-top: var(--bui-space-13); - } - - .xl\:bui-pt-14 { - padding-top: var(--bui-space-14); - } -} - -.bui-pb { - padding-bottom: var(--pb); -} - -.bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); -} - -.bui-pb-1 { - padding-bottom: var(--bui-space-1); -} - -.bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); -} - -.bui-pb-2 { - padding-bottom: var(--bui-space-2); -} - -.bui-pb-3 { - padding-bottom: var(--bui-space-3); -} - -.bui-pb-4 { - padding-bottom: var(--bui-space-4); -} - -.bui-pb-5 { - padding-bottom: var(--bui-space-5); -} - -.bui-pb-6 { - padding-bottom: var(--bui-space-6); -} - -.bui-pb-7 { - padding-bottom: var(--bui-space-7); -} - -.bui-pb-8 { - padding-bottom: var(--bui-space-8); -} - -.bui-pb-9 { - padding-bottom: var(--bui-space-9); -} - -.bui-pb-10 { - padding-bottom: var(--bui-space-10); -} - -.bui-pb-11 { - padding-bottom: var(--bui-space-11); -} - -.bui-pb-12 { - padding-bottom: var(--bui-space-12); -} - -.bui-pb-13 { - padding-bottom: var(--bui-space-13); -} - -.bui-pb-14 { - padding-bottom: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-pb { - padding-bottom: var(--pb-xs); - } - - .xs\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); - } - - .xs\:bui-pb-1 { - padding-bottom: var(--bui-space-1); - } - - .xs\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); - } - - .xs\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } - - .xs\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } - - .xs\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } - - .xs\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } - - .xs\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } - - .xs\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } - - .xs\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } - - .xs\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } - - .xs\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } - - .xs\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } - - .xs\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } - - .xs\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } - - .xs\:bui-pb-14 { - padding-bottom: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-pb { - padding-bottom: var(--pb-sm); - } - - .sm\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); - } - - .sm\:bui-pb-1 { - padding-bottom: var(--bui-space-1); - } - - .sm\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); - } - - .sm\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } - - .sm\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } - - .sm\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } - - .sm\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } - - .sm\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } - - .sm\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } - - .sm\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } - - .sm\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } - - .sm\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } - - .sm\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } - - .sm\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } - - .sm\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } - - .sm\:bui-pb-14 { - padding-bottom: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-pb { - padding-bottom: var(--pb-md); - } - - .md\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); - } - - .md\:bui-pb-1 { - padding-bottom: var(--bui-space-1); - } - - .md\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); - } - - .md\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } - - .md\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } - - .md\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } - - .md\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } - - .md\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } - - .md\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } - - .md\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } - - .md\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } - - .md\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } - - .md\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } - - .md\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } - - .md\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } - - .md\:bui-pb-14 { - padding-bottom: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-pb { - padding-bottom: var(--pb-lg); - } - - .lg\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); - } - - .lg\:bui-pb-1 { - padding-bottom: var(--bui-space-1); - } - - .lg\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); - } - - .lg\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } - - .lg\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } - - .lg\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } - - .lg\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } - - .lg\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } - - .lg\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } - - .lg\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } - - .lg\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } - - .lg\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } - - .lg\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } - - .lg\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } - - .lg\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } - - .lg\:bui-pb-14 { - padding-bottom: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-pb { - padding-bottom: var(--pb-xl); - } - - .xl\:bui-pb-0\.5 { - padding-bottom: var(--bui-space-0_5); - } - - .xl\:bui-pb-1 { - padding-bottom: var(--bui-space-1); - } - - .xl\:bui-pb-1\.5 { - padding-bottom: var(--bui-space-1_5); - } - - .xl\:bui-pb-2 { - padding-bottom: var(--bui-space-2); - } - - .xl\:bui-pb-3 { - padding-bottom: var(--bui-space-3); - } - - .xl\:bui-pb-4 { - padding-bottom: var(--bui-space-4); - } - - .xl\:bui-pb-5 { - padding-bottom: var(--bui-space-5); - } - - .xl\:bui-pb-6 { - padding-bottom: var(--bui-space-6); - } - - .xl\:bui-pb-7 { - padding-bottom: var(--bui-space-7); - } - - .xl\:bui-pb-8 { - padding-bottom: var(--bui-space-8); - } - - .xl\:bui-pb-9 { - padding-bottom: var(--bui-space-9); - } - - .xl\:bui-pb-10 { - padding-bottom: var(--bui-space-10); - } - - .xl\:bui-pb-11 { - padding-bottom: var(--bui-space-11); - } - - .xl\:bui-pb-12 { - padding-bottom: var(--bui-space-12); - } - - .xl\:bui-pb-13 { - padding-bottom: var(--bui-space-13); - } - - .xl\:bui-pb-14 { - padding-bottom: var(--bui-space-14); - } -} - -.bui-py { - padding-top: var(--py); - padding-bottom: var(--py); -} - -.bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); -} - -.bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); -} - -.bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); -} - -.bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); -} - -.bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); -} - -.bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); -} - -.bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); -} - -.bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); -} - -.bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); -} - -.bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); -} - -.bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); -} - -.bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); -} - -.bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); -} - -.bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); -} - -.bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); -} - -.bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-py { - padding-top: var(--py-xs); - padding-bottom: var(--py-xs); - } - - .xs\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); - } - - .xs\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); - } - - .xs\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); - } - - .xs\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } - - .xs\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } - - .xs\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } - - .xs\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } - - .xs\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } - - .xs\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } - - .xs\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } - - .xs\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } - - .xs\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } - - .xs\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } - - .xs\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } - - .xs\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } - - .xs\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-py { - padding-top: var(--py-sm); - padding-bottom: var(--py-sm); - } - - .sm\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); - } - - .sm\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); - } - - .sm\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); - } - - .sm\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } - - .sm\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } - - .sm\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } - - .sm\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } - - .sm\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } - - .sm\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } - - .sm\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } - - .sm\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } - - .sm\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } - - .sm\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } - - .sm\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } - - .sm\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } - - .sm\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-py { - padding-top: var(--py-md); - padding-bottom: var(--py-md); - } - - .md\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); - } - - .md\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); - } - - .md\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); - } - - .md\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } - - .md\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } - - .md\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } - - .md\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } - - .md\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } - - .md\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } - - .md\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } - - .md\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } - - .md\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } - - .md\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } - - .md\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } - - .md\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } - - .md\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-py { - padding-top: var(--py-lg); - padding-bottom: var(--py-lg); - } - - .lg\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); - } - - .lg\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); - } - - .lg\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); - } - - .lg\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } - - .lg\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } - - .lg\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } - - .lg\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } - - .lg\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } - - .lg\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } - - .lg\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } - - .lg\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } - - .lg\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } - - .lg\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } - - .lg\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } - - .lg\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } - - .lg\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-py { - padding-top: var(--py-xl); - padding-bottom: var(--py-xl); - } - - .xl\:bui-py-0\.5 { - padding-top: var(--bui-space-0_5); - padding-bottom: var(--bui-space-0_5); - } - - .xl\:bui-py-1 { - padding-top: var(--bui-space-1); - padding-bottom: var(--bui-space-1); - } - - .xl\:bui-py-1\.5 { - padding-top: var(--bui-space-1_5); - padding-bottom: var(--bui-space-1_5); - } - - .xl\:bui-py-2 { - padding-top: var(--bui-space-2); - padding-bottom: var(--bui-space-2); - } - - .xl\:bui-py-3 { - padding-top: var(--bui-space-3); - padding-bottom: var(--bui-space-3); - } - - .xl\:bui-py-4 { - padding-top: var(--bui-space-4); - padding-bottom: var(--bui-space-4); - } - - .xl\:bui-py-5 { - padding-top: var(--bui-space-5); - padding-bottom: var(--bui-space-5); - } - - .xl\:bui-py-6 { - padding-top: var(--bui-space-6); - padding-bottom: var(--bui-space-6); - } - - .xl\:bui-py-7 { - padding-top: var(--bui-space-7); - padding-bottom: var(--bui-space-7); - } - - .xl\:bui-py-8 { - padding-top: var(--bui-space-8); - padding-bottom: var(--bui-space-8); - } - - .xl\:bui-py-9 { - padding-top: var(--bui-space-9); - padding-bottom: var(--bui-space-9); - } - - .xl\:bui-py-10 { - padding-top: var(--bui-space-10); - padding-bottom: var(--bui-space-10); - } - - .xl\:bui-py-11 { - padding-top: var(--bui-space-11); - padding-bottom: var(--bui-space-11); - } - - .xl\:bui-py-12 { - padding-top: var(--bui-space-12); - padding-bottom: var(--bui-space-12); - } - - .xl\:bui-py-13 { - padding-top: var(--bui-space-13); - padding-bottom: var(--bui-space-13); - } - - .xl\:bui-py-14 { - padding-top: var(--bui-space-14); - padding-bottom: var(--bui-space-14); - } -} - -.bui-px { - padding-left: var(--px); - padding-right: var(--px); -} - -.bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); -} - -.bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); -} - -.bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); -} - -.bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); -} - -.bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); -} - -.bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); -} - -.bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); -} - -.bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); -} - -.bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); -} - -.bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); -} - -.bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); -} - -.bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); -} - -.bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); -} - -.bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); -} - -.bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); -} - -.bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-px { - padding-left: var(--px-xs); - padding-right: var(--px-xs); - } - - .xs\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); - } - - .xs\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); - } - - .xs\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); - } - - .xs\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } - - .xs\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } - - .xs\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } - - .xs\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } - - .xs\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } - - .xs\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } - - .xs\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } - - .xs\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } - - .xs\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } - - .xs\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } - - .xs\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } - - .xs\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } - - .xs\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-px { - padding-left: var(--px-sm); - padding-right: var(--px-sm); - } - - .sm\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); - } - - .sm\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); - } - - .sm\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); - } - - .sm\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } - - .sm\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } - - .sm\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } - - .sm\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } - - .sm\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } - - .sm\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } - - .sm\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } - - .sm\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } - - .sm\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } - - .sm\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } - - .sm\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } - - .sm\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } - - .sm\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-px { - padding-left: var(--px-md); - padding-right: var(--px-md); - } - - .md\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); - } - - .md\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); - } - - .md\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); - } - - .md\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } - - .md\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } - - .md\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } - - .md\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } - - .md\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } - - .md\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } - - .md\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } - - .md\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } - - .md\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } - - .md\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } - - .md\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } - - .md\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } - - .md\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-px { - padding-left: var(--px-lg); - padding-right: var(--px-lg); - } - - .lg\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); - } - - .lg\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); - } - - .lg\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); - } - - .lg\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } - - .lg\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } - - .lg\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } - - .lg\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } - - .lg\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } - - .lg\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } - - .lg\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } - - .lg\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } - - .lg\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } - - .lg\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } - - .lg\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } - - .lg\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } - - .lg\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-px { - padding-left: var(--px-xl); - padding-right: var(--px-xl); - } - - .xl\:bui-px-0\.5 { - padding-left: var(--bui-space-0_5); - padding-right: var(--bui-space-0_5); - } - - .xl\:bui-px-1 { - padding-left: var(--bui-space-1); - padding-right: var(--bui-space-1); - } - - .xl\:bui-px-1\.5 { - padding-left: var(--bui-space-1_5); - padding-right: var(--bui-space-1_5); - } - - .xl\:bui-px-2 { - padding-left: var(--bui-space-2); - padding-right: var(--bui-space-2); - } - - .xl\:bui-px-3 { - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-3); - } - - .xl\:bui-px-4 { - padding-left: var(--bui-space-4); - padding-right: var(--bui-space-4); - } - - .xl\:bui-px-5 { - padding-left: var(--bui-space-5); - padding-right: var(--bui-space-5); - } - - .xl\:bui-px-6 { - padding-left: var(--bui-space-6); - padding-right: var(--bui-space-6); - } - - .xl\:bui-px-7 { - padding-left: var(--bui-space-7); - padding-right: var(--bui-space-7); - } - - .xl\:bui-px-8 { - padding-left: var(--bui-space-8); - padding-right: var(--bui-space-8); - } - - .xl\:bui-px-9 { - padding-left: var(--bui-space-9); - padding-right: var(--bui-space-9); - } - - .xl\:bui-px-10 { - padding-left: var(--bui-space-10); - padding-right: var(--bui-space-10); - } - - .xl\:bui-px-11 { - padding-left: var(--bui-space-11); - padding-right: var(--bui-space-11); - } - - .xl\:bui-px-12 { - padding-left: var(--bui-space-12); - padding-right: var(--bui-space-12); - } - - .xl\:bui-px-13 { - padding-left: var(--bui-space-13); - padding-right: var(--bui-space-13); - } - - .xl\:bui-px-14 { - padding-left: var(--bui-space-14); - padding-right: var(--bui-space-14); - } -} - -.bui-m { - margin: var(--m); -} - -.bui-m-0\.5 { - margin: var(--bui-space-0_5); -} - -.bui-m-1 { - margin: var(--bui-space-1); -} - -.bui-m-1\.5 { - margin: var(--bui-space-1_5); -} - -.bui-m-2 { - margin: var(--bui-space-2); -} - -.bui-m-3 { - margin: var(--bui-space-3); -} - -.bui-m-4 { - margin: var(--bui-space-4); -} - -.bui-m-5 { - margin: var(--bui-space-5); -} - -.bui-m-6 { - margin: var(--bui-space-6); -} - -.bui-m-7 { - margin: var(--bui-space-7); -} - -.bui-m-8 { - margin: var(--bui-space-8); -} - -.bui-m-9 { - margin: var(--bui-space-9); -} - -.bui-m-10 { - margin: var(--bui-space-10); -} - -.bui-m-11 { - margin: var(--bui-space-11); -} - -.bui-m-12 { - margin: var(--bui-space-12); -} - -.bui-m-13 { - margin: var(--bui-space-13); -} - -.bui-m-14 { - margin: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-m { - margin: var(--p-xs); - } - - .xs\:bui-m-0\.5 { - margin: var(--bui-space-0_5); - } - - .xs\:bui-m-1 { - margin: var(--bui-space-1); - } - - .xs\:bui-m-1\.5 { - margin: var(--bui-space-1_5); - } - - .xs\:bui-m-2 { - margin: var(--bui-space-2); - } - - .xs\:bui-m-3 { - margin: var(--bui-space-3); - } - - .xs\:bui-m-4 { - margin: var(--bui-space-4); - } - - .xs\:bui-m-5 { - margin: var(--bui-space-5); - } - - .xs\:bui-m-6 { - margin: var(--bui-space-6); - } - - .xs\:bui-m-7 { - margin: var(--bui-space-7); - } - - .xs\:bui-m-8 { - margin: var(--bui-space-8); - } - - .xs\:bui-m-9 { - margin: var(--bui-space-9); - } - - .xs\:bui-m-10 { - margin: var(--bui-space-10); - } - - .xs\:bui-m-11 { - margin: var(--bui-space-11); - } - - .xs\:bui-m-12 { - margin: var(--bui-space-12); - } - - .xs\:bui-m-13 { - margin: var(--bui-space-13); - } - - .xs\:bui-m-14 { - margin: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-m { - margin: var(--p-sm); - } - - .sm\:bui-m-0\.5 { - margin: var(--bui-space-0_5); - } - - .sm\:bui-m-1 { - margin: var(--bui-space-1); - } - - .sm\:bui-m-1\.5 { - margin: var(--bui-space-1_5); - } - - .sm\:bui-m-2 { - margin: var(--bui-space-2); - } - - .sm\:bui-m-3 { - margin: var(--bui-space-3); - } - - .sm\:bui-m-4 { - margin: var(--bui-space-4); - } - - .sm\:bui-m-5 { - margin: var(--bui-space-5); - } - - .sm\:bui-m-6 { - margin: var(--bui-space-6); - } - - .sm\:bui-m-7 { - margin: var(--bui-space-7); - } - - .sm\:bui-m-8 { - margin: var(--bui-space-8); - } - - .sm\:bui-m-9 { - margin: var(--bui-space-9); - } - - .sm\:bui-m-10 { - margin: var(--bui-space-10); - } - - .sm\:bui-m-11 { - margin: var(--bui-space-11); - } - - .sm\:bui-m-12 { - margin: var(--bui-space-12); - } - - .sm\:bui-m-13 { - margin: var(--bui-space-13); - } - - .sm\:bui-m-14 { - margin: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-m { - margin: var(--p-md); - } - - .md\:bui-m-0\.5 { - margin: var(--bui-space-0_5); - } - - .md\:bui-m-1 { - margin: var(--bui-space-1); - } - - .md\:bui-m-1\.5 { - margin: var(--bui-space-1_5); - } - - .md\:bui-m-2 { - margin: var(--bui-space-2); - } - - .md\:bui-m-3 { - margin: var(--bui-space-3); - } - - .md\:bui-m-4 { - margin: var(--bui-space-4); - } - - .md\:bui-m-5 { - margin: var(--bui-space-5); - } - - .md\:bui-m-6 { - margin: var(--bui-space-6); - } - - .md\:bui-m-7 { - margin: var(--bui-space-7); - } - - .md\:bui-m-8 { - margin: var(--bui-space-8); - } - - .md\:bui-m-9 { - margin: var(--bui-space-9); - } - - .md\:bui-m-10 { - margin: var(--bui-space-10); - } - - .md\:bui-m-11 { - margin: var(--bui-space-11); - } - - .md\:bui-m-12 { - margin: var(--bui-space-12); - } - - .md\:bui-m-13 { - margin: var(--bui-space-13); - } - - .md\:bui-m-14 { - margin: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-m { - margin: var(--p-lg); - } - - .lg\:bui-m-0\.5 { - margin: var(--bui-space-0_5); - } - - .lg\:bui-m-1 { - margin: var(--bui-space-1); - } - - .lg\:bui-m-1\.5 { - margin: var(--bui-space-1_5); - } - - .lg\:bui-m-2 { - margin: var(--bui-space-2); - } - - .lg\:bui-m-3 { - margin: var(--bui-space-3); - } - - .lg\:bui-m-4 { - margin: var(--bui-space-4); - } - - .lg\:bui-m-5 { - margin: var(--bui-space-5); - } - - .lg\:bui-m-6 { - margin: var(--bui-space-6); - } - - .lg\:bui-m-7 { - margin: var(--bui-space-7); - } - - .lg\:bui-m-8 { - margin: var(--bui-space-8); - } - - .lg\:bui-m-9 { - margin: var(--bui-space-9); - } - - .lg\:bui-m-10 { - margin: var(--bui-space-10); - } - - .lg\:bui-m-11 { - margin: var(--bui-space-11); - } - - .lg\:bui-m-12 { - margin: var(--bui-space-12); - } - - .lg\:bui-m-13 { - margin: var(--bui-space-13); - } - - .lg\:bui-m-14 { - margin: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-m { - margin: var(--p-xl); - } - - .xl\:bui-m-0\.5 { - margin: var(--bui-space-0_5); - } - - .xl\:bui-m-1 { - margin: var(--bui-space-1); - } - - .xl\:bui-m-1\.5 { - margin: var(--bui-space-1_5); - } - - .xl\:bui-m-2 { - margin: var(--bui-space-2); - } - - .xl\:bui-m-3 { - margin: var(--bui-space-3); - } - - .xl\:bui-m-4 { - margin: var(--bui-space-4); - } - - .xl\:bui-m-5 { - margin: var(--bui-space-5); - } - - .xl\:bui-m-6 { - margin: var(--bui-space-6); - } - - .xl\:bui-m-7 { - margin: var(--bui-space-7); - } - - .xl\:bui-m-8 { - margin: var(--bui-space-8); - } - - .xl\:bui-m-9 { - margin: var(--bui-space-9); - } - - .xl\:bui-m-10 { - margin: var(--bui-space-10); - } - - .xl\:bui-m-11 { - margin: var(--bui-space-11); - } - - .xl\:bui-m-12 { - margin: var(--bui-space-12); - } - - .xl\:bui-m-13 { - margin: var(--bui-space-13); - } - - .xl\:bui-m-14 { - margin: var(--bui-space-14); - } -} - -.bui-ml { - margin-left: var(--ml); -} - -.bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); -} - -.bui-ml-1 { - margin-left: var(--bui-space-1); -} - -.bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); -} - -.bui-ml-2 { - margin-left: var(--bui-space-2); -} - -.bui-ml-3 { - margin-left: var(--bui-space-3); -} - -.bui-ml-4 { - margin-left: var(--bui-space-4); -} - -.bui-ml-5 { - margin-left: var(--bui-space-5); -} - -.bui-ml-6 { - margin-left: var(--bui-space-6); -} - -.bui-ml-7 { - margin-left: var(--bui-space-7); -} - -.bui-ml-8 { - margin-left: var(--bui-space-8); -} - -.bui-ml-9 { - margin-left: var(--bui-space-9); -} - -.bui-ml-10 { - margin-left: var(--bui-space-10); -} - -.bui-ml-11 { - margin-left: var(--bui-space-11); -} - -.bui-ml-12 { - margin-left: var(--bui-space-12); -} - -.bui-ml-13 { - margin-left: var(--bui-space-13); -} - -.bui-ml-14 { - margin-left: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-ml { - margin-left: var(--pl-xs); - } - - .xs\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); - } - - .xs\:bui-ml-1 { - margin-left: var(--bui-space-1); - } - - .xs\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); - } - - .xs\:bui-ml-2 { - margin-left: var(--bui-space-2); - } - - .xs\:bui-ml-3 { - margin-left: var(--bui-space-3); - } - - .xs\:bui-ml-4 { - margin-left: var(--bui-space-4); - } - - .xs\:bui-ml-5 { - margin-left: var(--bui-space-5); - } - - .xs\:bui-ml-6 { - margin-left: var(--bui-space-6); - } - - .xs\:bui-ml-7 { - margin-left: var(--bui-space-7); - } - - .xs\:bui-ml-8 { - margin-left: var(--bui-space-8); - } - - .xs\:bui-ml-9 { - margin-left: var(--bui-space-9); - } - - .xs\:bui-ml-10 { - margin-left: var(--bui-space-10); - } - - .xs\:bui-ml-11 { - margin-left: var(--bui-space-11); - } - - .xs\:bui-ml-12 { - margin-left: var(--bui-space-12); - } - - .xs\:bui-ml-13 { - margin-left: var(--bui-space-13); - } - - .xs\:bui-ml-14 { - margin-left: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-ml { - margin-left: var(--pl-sm); - } - - .sm\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); - } - - .sm\:bui-ml-1 { - margin-left: var(--bui-space-1); - } - - .sm\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); - } - - .sm\:bui-ml-2 { - margin-left: var(--bui-space-2); - } - - .sm\:bui-ml-3 { - margin-left: var(--bui-space-3); - } - - .sm\:bui-ml-4 { - margin-left: var(--bui-space-4); - } - - .sm\:bui-ml-5 { - margin-left: var(--bui-space-5); - } - - .sm\:bui-ml-6 { - margin-left: var(--bui-space-6); - } - - .sm\:bui-ml-7 { - margin-left: var(--bui-space-7); - } - - .sm\:bui-ml-8 { - margin-left: var(--bui-space-8); - } - - .sm\:bui-ml-9 { - margin-left: var(--bui-space-9); - } - - .sm\:bui-ml-10 { - margin-left: var(--bui-space-10); - } - - .sm\:bui-ml-11 { - margin-left: var(--bui-space-11); - } - - .sm\:bui-ml-12 { - margin-left: var(--bui-space-12); - } - - .sm\:bui-ml-13 { - margin-left: var(--bui-space-13); - } - - .sm\:bui-ml-14 { - margin-left: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-ml { - margin-left: var(--pl-md); - } - - .md\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); - } - - .md\:bui-ml-1 { - margin-left: var(--bui-space-1); - } - - .md\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); - } - - .md\:bui-ml-2 { - margin-left: var(--bui-space-2); - } - - .md\:bui-ml-3 { - margin-left: var(--bui-space-3); - } - - .md\:bui-ml-4 { - margin-left: var(--bui-space-4); - } - - .md\:bui-ml-5 { - margin-left: var(--bui-space-5); - } - - .md\:bui-ml-6 { - margin-left: var(--bui-space-6); - } - - .md\:bui-ml-7 { - margin-left: var(--bui-space-7); - } - - .md\:bui-ml-8 { - margin-left: var(--bui-space-8); - } - - .md\:bui-ml-9 { - margin-left: var(--bui-space-9); - } - - .md\:bui-ml-10 { - margin-left: var(--bui-space-10); - } - - .md\:bui-ml-11 { - margin-left: var(--bui-space-11); - } - - .md\:bui-ml-12 { - margin-left: var(--bui-space-12); - } - - .md\:bui-ml-13 { - margin-left: var(--bui-space-13); - } - - .md\:bui-ml-14 { - margin-left: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-ml { - margin-left: var(--pl-lg); - } - - .lg\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); - } - - .lg\:bui-ml-1 { - margin-left: var(--bui-space-1); - } - - .lg\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); - } - - .lg\:bui-ml-2 { - margin-left: var(--bui-space-2); - } - - .lg\:bui-ml-3 { - margin-left: var(--bui-space-3); - } - - .lg\:bui-ml-4 { - margin-left: var(--bui-space-4); - } - - .lg\:bui-ml-5 { - margin-left: var(--bui-space-5); - } - - .lg\:bui-ml-6 { - margin-left: var(--bui-space-6); - } - - .lg\:bui-ml-7 { - margin-left: var(--bui-space-7); - } - - .lg\:bui-ml-8 { - margin-left: var(--bui-space-8); - } - - .lg\:bui-ml-9 { - margin-left: var(--bui-space-9); - } - - .lg\:bui-ml-10 { - margin-left: var(--bui-space-10); - } - - .lg\:bui-ml-11 { - margin-left: var(--bui-space-11); - } - - .lg\:bui-ml-12 { - margin-left: var(--bui-space-12); - } - - .lg\:bui-ml-13 { - margin-left: var(--bui-space-13); - } - - .lg\:bui-ml-14 { - margin-left: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-ml { - margin-left: var(--pl-xl); - } - - .xl\:bui-ml-0\.5 { - margin-left: var(--bui-space-0_5); - } - - .xl\:bui-ml-1 { - margin-left: var(--bui-space-1); - } - - .xl\:bui-ml-1\.5 { - margin-left: var(--bui-space-1_5); - } - - .xl\:bui-ml-2 { - margin-left: var(--bui-space-2); - } - - .xl\:bui-ml-3 { - margin-left: var(--bui-space-3); - } - - .xl\:bui-ml-4 { - margin-left: var(--bui-space-4); - } - - .xl\:bui-ml-5 { - margin-left: var(--bui-space-5); - } - - .xl\:bui-ml-6 { - margin-left: var(--bui-space-6); - } - - .xl\:bui-ml-7 { - margin-left: var(--bui-space-7); - } - - .xl\:bui-ml-8 { - margin-left: var(--bui-space-8); - } - - .xl\:bui-ml-9 { - margin-left: var(--bui-space-9); - } - - .xl\:bui-ml-10 { - margin-left: var(--bui-space-10); - } - - .xl\:bui-ml-11 { - margin-left: var(--bui-space-11); - } - - .xl\:bui-ml-12 { - margin-left: var(--bui-space-12); - } - - .xl\:bui-ml-13 { - margin-left: var(--bui-space-13); - } - - .xl\:bui-ml-14 { - margin-left: var(--bui-space-14); - } -} - -.bui-mr { - margin-right: var(--mr); -} - -.bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); -} - -.bui-mr-1 { - margin-right: var(--bui-space-1); -} - -.bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); -} - -.bui-mr-2 { - margin-right: var(--bui-space-2); -} - -.bui-mr-3 { - margin-right: var(--bui-space-3); -} - -.bui-mr-4 { - margin-right: var(--bui-space-4); -} - -.bui-mr-5 { - margin-right: var(--bui-space-5); -} - -.bui-mr-6 { - margin-right: var(--bui-space-6); -} - -.bui-mr-7 { - margin-right: var(--bui-space-7); -} - -.bui-mr-8 { - margin-right: var(--bui-space-8); -} - -.bui-mr-9 { - margin-right: var(--bui-space-9); -} - -.bui-mr-10 { - margin-right: var(--bui-space-10); -} - -.bui-mr-11 { - margin-right: var(--bui-space-11); -} - -.bui-mr-12 { - margin-right: var(--bui-space-12); -} - -.bui-mr-13 { - margin-right: var(--bui-space-13); -} - -.bui-mr-14 { - margin-right: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-mr { - margin-right: var(--pr-xs); - } - - .xs\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); - } - - .xs\:bui-mr-1 { - margin-right: var(--bui-space-1); - } - - .xs\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); - } - - .xs\:bui-mr-2 { - margin-right: var(--bui-space-2); - } - - .xs\:bui-mr-3 { - margin-right: var(--bui-space-3); - } - - .xs\:bui-mr-4 { - margin-right: var(--bui-space-4); - } - - .xs\:bui-mr-5 { - margin-right: var(--bui-space-5); - } - - .xs\:bui-mr-6 { - margin-right: var(--bui-space-6); - } - - .xs\:bui-mr-7 { - margin-right: var(--bui-space-7); - } - - .xs\:bui-mr-8 { - margin-right: var(--bui-space-8); - } - - .xs\:bui-mr-9 { - margin-right: var(--bui-space-9); - } - - .xs\:bui-mr-10 { - margin-right: var(--bui-space-10); - } - - .xs\:bui-mr-11 { - margin-right: var(--bui-space-11); - } - - .xs\:bui-mr-12 { - margin-right: var(--bui-space-12); - } - - .xs\:bui-mr-13 { - margin-right: var(--bui-space-13); - } - - .xs\:bui-mr-14 { - margin-right: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-mr { - margin-right: var(--pr-sm); - } - - .sm\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); - } - - .sm\:bui-mr-1 { - margin-right: var(--bui-space-1); - } - - .sm\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); - } - - .sm\:bui-mr-2 { - margin-right: var(--bui-space-2); - } - - .sm\:bui-mr-3 { - margin-right: var(--bui-space-3); - } - - .sm\:bui-mr-4 { - margin-right: var(--bui-space-4); - } - - .sm\:bui-mr-5 { - margin-right: var(--bui-space-5); - } - - .sm\:bui-mr-6 { - margin-right: var(--bui-space-6); - } - - .sm\:bui-mr-7 { - margin-right: var(--bui-space-7); - } - - .sm\:bui-mr-8 { - margin-right: var(--bui-space-8); - } - - .sm\:bui-mr-9 { - margin-right: var(--bui-space-9); - } - - .sm\:bui-mr-10 { - margin-right: var(--bui-space-10); - } - - .sm\:bui-mr-11 { - margin-right: var(--bui-space-11); - } - - .sm\:bui-mr-12 { - margin-right: var(--bui-space-12); - } - - .sm\:bui-mr-13 { - margin-right: var(--bui-space-13); - } - - .sm\:bui-mr-14 { - margin-right: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-mr { - margin-right: var(--pr-md); - } - - .md\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); - } - - .md\:bui-mr-1 { - margin-right: var(--bui-space-1); - } - - .md\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); - } - - .md\:bui-mr-2 { - margin-right: var(--bui-space-2); - } - - .md\:bui-mr-3 { - margin-right: var(--bui-space-3); - } - - .md\:bui-mr-4 { - margin-right: var(--bui-space-4); - } - - .md\:bui-mr-5 { - margin-right: var(--bui-space-5); - } - - .md\:bui-mr-6 { - margin-right: var(--bui-space-6); - } - - .md\:bui-mr-7 { - margin-right: var(--bui-space-7); - } - - .md\:bui-mr-8 { - margin-right: var(--bui-space-8); - } - - .md\:bui-mr-9 { - margin-right: var(--bui-space-9); - } - - .md\:bui-mr-10 { - margin-right: var(--bui-space-10); - } - - .md\:bui-mr-11 { - margin-right: var(--bui-space-11); - } - - .md\:bui-mr-12 { - margin-right: var(--bui-space-12); - } - - .md\:bui-mr-13 { - margin-right: var(--bui-space-13); - } - - .md\:bui-mr-14 { - margin-right: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-mr { - margin-right: var(--pr-lg); - } - - .lg\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); - } - - .lg\:bui-mr-1 { - margin-right: var(--bui-space-1); - } - - .lg\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); - } - - .lg\:bui-mr-2 { - margin-right: var(--bui-space-2); - } - - .lg\:bui-mr-3 { - margin-right: var(--bui-space-3); - } - - .lg\:bui-mr-4 { - margin-right: var(--bui-space-4); - } - - .lg\:bui-mr-5 { - margin-right: var(--bui-space-5); - } - - .lg\:bui-mr-6 { - margin-right: var(--bui-space-6); - } - - .lg\:bui-mr-7 { - margin-right: var(--bui-space-7); - } - - .lg\:bui-mr-8 { - margin-right: var(--bui-space-8); - } - - .lg\:bui-mr-9 { - margin-right: var(--bui-space-9); - } - - .lg\:bui-mr-10 { - margin-right: var(--bui-space-10); - } - - .lg\:bui-mr-11 { - margin-right: var(--bui-space-11); - } - - .lg\:bui-mr-12 { - margin-right: var(--bui-space-12); - } - - .lg\:bui-mr-13 { - margin-right: var(--bui-space-13); - } - - .lg\:bui-mr-14 { - margin-right: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-mr { - margin-right: var(--pr-xl); - } - - .xl\:bui-mr-0\.5 { - margin-right: var(--bui-space-0_5); - } - - .xl\:bui-mr-1 { - margin-right: var(--bui-space-1); - } - - .xl\:bui-mr-1\.5 { - margin-right: var(--bui-space-1_5); - } - - .xl\:bui-mr-2 { - margin-right: var(--bui-space-2); - } - - .xl\:bui-mr-3 { - margin-right: var(--bui-space-3); - } - - .xl\:bui-mr-4 { - margin-right: var(--bui-space-4); - } - - .xl\:bui-mr-5 { - margin-right: var(--bui-space-5); - } - - .xl\:bui-mr-6 { - margin-right: var(--bui-space-6); - } - - .xl\:bui-mr-7 { - margin-right: var(--bui-space-7); - } - - .xl\:bui-mr-8 { - margin-right: var(--bui-space-8); - } - - .xl\:bui-mr-9 { - margin-right: var(--bui-space-9); - } - - .xl\:bui-mr-10 { - margin-right: var(--bui-space-10); - } - - .xl\:bui-mr-11 { - margin-right: var(--bui-space-11); - } - - .xl\:bui-mr-12 { - margin-right: var(--bui-space-12); - } - - .xl\:bui-mr-13 { - margin-right: var(--bui-space-13); - } - - .xl\:bui-mr-14 { - margin-right: var(--bui-space-14); - } -} - -.bui-mt { - margin-top: var(--mt); -} - -.bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); -} - -.bui-mt-1 { - margin-top: var(--bui-space-1); -} - -.bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); -} - -.bui-mt-2 { - margin-top: var(--bui-space-2); -} - -.bui-mt-3 { - margin-top: var(--bui-space-3); -} - -.bui-mt-4 { - margin-top: var(--bui-space-4); -} - -.bui-mt-5 { - margin-top: var(--bui-space-5); -} - -.bui-mt-6 { - margin-top: var(--bui-space-6); -} - -.bui-mt-7 { - margin-top: var(--bui-space-7); -} - -.bui-mt-8 { - margin-top: var(--bui-space-8); -} - -.bui-mt-9 { - margin-top: var(--bui-space-9); -} - -.bui-mt-10 { - margin-top: var(--bui-space-10); -} - -.bui-mt-11 { - margin-top: var(--bui-space-11); -} - -.bui-mt-12 { - margin-top: var(--bui-space-12); -} - -.bui-mt-13 { - margin-top: var(--bui-space-13); -} - -.bui-mt-14 { - margin-top: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-mt { - margin-top: var(--pt-xs); - } - - .xs\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); - } - - .xs\:bui-mt-1 { - margin-top: var(--bui-space-1); - } - - .xs\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); - } - - .xs\:bui-mt-2 { - margin-top: var(--bui-space-2); - } - - .xs\:bui-mt-3 { - margin-top: var(--bui-space-3); - } - - .xs\:bui-mt-4 { - margin-top: var(--bui-space-4); - } - - .xs\:bui-mt-5 { - margin-top: var(--bui-space-5); - } - - .xs\:bui-mt-6 { - margin-top: var(--bui-space-6); - } - - .xs\:bui-mt-7 { - margin-top: var(--bui-space-7); - } - - .xs\:bui-mt-8 { - margin-top: var(--bui-space-8); - } - - .xs\:bui-mt-9 { - margin-top: var(--bui-space-9); - } - - .xs\:bui-mt-10 { - margin-top: var(--bui-space-10); - } - - .xs\:bui-mt-11 { - margin-top: var(--bui-space-11); - } - - .xs\:bui-mt-12 { - margin-top: var(--bui-space-12); - } - - .xs\:bui-mt-13 { - margin-top: var(--bui-space-13); - } - - .xs\:bui-mt-14 { - margin-top: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-mt { - margin-top: var(--pt-sm); - } - - .sm\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); - } - - .sm\:bui-mt-1 { - margin-top: var(--bui-space-1); - } - - .sm\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); - } - - .sm\:bui-mt-2 { - margin-top: var(--bui-space-2); - } - - .sm\:bui-mt-3 { - margin-top: var(--bui-space-3); - } - - .sm\:bui-mt-4 { - margin-top: var(--bui-space-4); - } - - .sm\:bui-mt-5 { - margin-top: var(--bui-space-5); - } - - .sm\:bui-mt-6 { - margin-top: var(--bui-space-6); - } - - .sm\:bui-mt-7 { - margin-top: var(--bui-space-7); - } - - .sm\:bui-mt-8 { - margin-top: var(--bui-space-8); - } - - .sm\:bui-mt-9 { - margin-top: var(--bui-space-9); - } - - .sm\:bui-mt-10 { - margin-top: var(--bui-space-10); - } - - .sm\:bui-mt-11 { - margin-top: var(--bui-space-11); - } - - .sm\:bui-mt-12 { - margin-top: var(--bui-space-12); - } - - .sm\:bui-mt-13 { - margin-top: var(--bui-space-13); - } - - .sm\:bui-mt-14 { - margin-top: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-mt { - margin-top: var(--pt-md); - } - - .md\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); - } - - .md\:bui-mt-1 { - margin-top: var(--bui-space-1); - } - - .md\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); - } - - .md\:bui-mt-2 { - margin-top: var(--bui-space-2); - } - - .md\:bui-mt-3 { - margin-top: var(--bui-space-3); - } - - .md\:bui-mt-4 { - margin-top: var(--bui-space-4); - } - - .md\:bui-mt-5 { - margin-top: var(--bui-space-5); - } - - .md\:bui-mt-6 { - margin-top: var(--bui-space-6); - } - - .md\:bui-mt-7 { - margin-top: var(--bui-space-7); - } - - .md\:bui-mt-8 { - margin-top: var(--bui-space-8); - } - - .md\:bui-mt-9 { - margin-top: var(--bui-space-9); - } - - .md\:bui-mt-10 { - margin-top: var(--bui-space-10); - } - - .md\:bui-mt-11 { - margin-top: var(--bui-space-11); - } - - .md\:bui-mt-12 { - margin-top: var(--bui-space-12); - } - - .md\:bui-mt-13 { - margin-top: var(--bui-space-13); - } - - .md\:bui-mt-14 { - margin-top: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-mt { - margin-top: var(--pt-lg); - } - - .lg\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); - } - - .lg\:bui-mt-1 { - margin-top: var(--bui-space-1); - } - - .lg\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); - } - - .lg\:bui-mt-2 { - margin-top: var(--bui-space-2); - } - - .lg\:bui-mt-3 { - margin-top: var(--bui-space-3); - } - - .lg\:bui-mt-4 { - margin-top: var(--bui-space-4); - } - - .lg\:bui-mt-5 { - margin-top: var(--bui-space-5); - } - - .lg\:bui-mt-6 { - margin-top: var(--bui-space-6); - } - - .lg\:bui-mt-7 { - margin-top: var(--bui-space-7); - } - - .lg\:bui-mt-8 { - margin-top: var(--bui-space-8); - } - - .lg\:bui-mt-9 { - margin-top: var(--bui-space-9); - } - - .lg\:bui-mt-10 { - margin-top: var(--bui-space-10); - } - - .lg\:bui-mt-11 { - margin-top: var(--bui-space-11); - } - - .lg\:bui-mt-12 { - margin-top: var(--bui-space-12); - } - - .lg\:bui-mt-13 { - margin-top: var(--bui-space-13); - } - - .lg\:bui-mt-14 { - margin-top: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-mt { - margin-top: var(--pt-xl); - } - - .xl\:bui-mt-0\.5 { - margin-top: var(--bui-space-0_5); - } - - .xl\:bui-mt-1 { - margin-top: var(--bui-space-1); - } - - .xl\:bui-mt-1\.5 { - margin-top: var(--bui-space-1_5); - } - - .xl\:bui-mt-2 { - margin-top: var(--bui-space-2); - } - - .xl\:bui-mt-3 { - margin-top: var(--bui-space-3); - } - - .xl\:bui-mt-4 { - margin-top: var(--bui-space-4); - } - - .xl\:bui-mt-5 { - margin-top: var(--bui-space-5); - } - - .xl\:bui-mt-6 { - margin-top: var(--bui-space-6); - } - - .xl\:bui-mt-7 { - margin-top: var(--bui-space-7); - } - - .xl\:bui-mt-8 { - margin-top: var(--bui-space-8); - } - - .xl\:bui-mt-9 { - margin-top: var(--bui-space-9); - } - - .xl\:bui-mt-10 { - margin-top: var(--bui-space-10); - } - - .xl\:bui-mt-11 { - margin-top: var(--bui-space-11); - } - - .xl\:bui-mt-12 { - margin-top: var(--bui-space-12); - } - - .xl\:bui-mt-13 { - margin-top: var(--bui-space-13); - } - - .xl\:bui-mt-14 { - margin-top: var(--bui-space-14); - } -} - -.bui-mb { - margin-bottom: var(--mb); -} - -.bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); -} - -.bui-mb-1 { - margin-bottom: var(--bui-space-1); -} - -.bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); -} - -.bui-mb-2 { - margin-bottom: var(--bui-space-2); -} - -.bui-mb-3 { - margin-bottom: var(--bui-space-3); -} - -.bui-mb-4 { - margin-bottom: var(--bui-space-4); -} - -.bui-mb-5 { - margin-bottom: var(--bui-space-5); -} - -.bui-mb-6 { - margin-bottom: var(--bui-space-6); -} - -.bui-mb-7 { - margin-bottom: var(--bui-space-7); -} - -.bui-mb-8 { - margin-bottom: var(--bui-space-8); -} - -.bui-mb-9 { - margin-bottom: var(--bui-space-9); -} - -.bui-mb-10 { - margin-bottom: var(--bui-space-10); -} - -.bui-mb-11 { - margin-bottom: var(--bui-space-11); -} - -.bui-mb-12 { - margin-bottom: var(--bui-space-12); -} - -.bui-mb-13 { - margin-bottom: var(--bui-space-13); -} - -.bui-mb-14 { - margin-bottom: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-mb { - margin-bottom: var(--pb-xs); - } - - .xs\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); - } - - .xs\:bui-mb-1 { - margin-bottom: var(--bui-space-1); - } - - .xs\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); - } - - .xs\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } - - .xs\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } - - .xs\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } - - .xs\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } - - .xs\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } - - .xs\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } - - .xs\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } - - .xs\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } - - .xs\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } - - .xs\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } - - .xs\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } - - .xs\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } - - .xs\:bui-mb-14 { - margin-bottom: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-mb { - margin-bottom: var(--pb-sm); - } - - .sm\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); - } - - .sm\:bui-mb-1 { - margin-bottom: var(--bui-space-1); - } - - .sm\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); - } - - .sm\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } - - .sm\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } - - .sm\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } - - .sm\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } - - .sm\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } - - .sm\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } - - .sm\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } - - .sm\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } - - .sm\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } - - .sm\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } - - .sm\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } - - .sm\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } - - .sm\:bui-mb-14 { - margin-bottom: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-mb { - margin-bottom: var(--pb-md); - } - - .md\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); - } - - .md\:bui-mb-1 { - margin-bottom: var(--bui-space-1); - } - - .md\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); - } - - .md\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } - - .md\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } - - .md\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } - - .md\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } - - .md\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } - - .md\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } - - .md\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } - - .md\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } - - .md\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } - - .md\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } - - .md\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } - - .md\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } - - .md\:bui-mb-14 { - margin-bottom: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-mb { - margin-bottom: var(--pb-lg); - } - - .lg\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); - } - - .lg\:bui-mb-1 { - margin-bottom: var(--bui-space-1); - } - - .lg\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); - } - - .lg\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } - - .lg\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } - - .lg\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } - - .lg\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } - - .lg\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } - - .lg\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } - - .lg\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } - - .lg\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } - - .lg\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } - - .lg\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } - - .lg\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } - - .lg\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } - - .lg\:bui-mb-14 { - margin-bottom: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-mb { - margin-bottom: var(--pb-xl); - } - - .xl\:bui-mb-0\.5 { - margin-bottom: var(--bui-space-0_5); - } - - .xl\:bui-mb-1 { - margin-bottom: var(--bui-space-1); - } - - .xl\:bui-mb-1\.5 { - margin-bottom: var(--bui-space-1_5); - } - - .xl\:bui-mb-2 { - margin-bottom: var(--bui-space-2); - } - - .xl\:bui-mb-3 { - margin-bottom: var(--bui-space-3); - } - - .xl\:bui-mb-4 { - margin-bottom: var(--bui-space-4); - } - - .xl\:bui-mb-5 { - margin-bottom: var(--bui-space-5); - } - - .xl\:bui-mb-6 { - margin-bottom: var(--bui-space-6); - } - - .xl\:bui-mb-7 { - margin-bottom: var(--bui-space-7); - } - - .xl\:bui-mb-8 { - margin-bottom: var(--bui-space-8); - } - - .xl\:bui-mb-9 { - margin-bottom: var(--bui-space-9); - } - - .xl\:bui-mb-10 { - margin-bottom: var(--bui-space-10); - } - - .xl\:bui-mb-11 { - margin-bottom: var(--bui-space-11); - } - - .xl\:bui-mb-12 { - margin-bottom: var(--bui-space-12); - } - - .xl\:bui-mb-13 { - margin-bottom: var(--bui-space-13); - } - - .xl\:bui-mb-14 { - margin-bottom: var(--bui-space-14); - } -} - -.bui-my { - margin-top: var(--my); - margin-bottom: var(--my); -} - -.bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); -} - -.bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); -} - -.bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); -} - -.bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); -} - -.bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); -} - -.bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); -} - -.bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); -} - -.bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); -} - -.bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); -} - -.bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); -} - -.bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); -} - -.bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); -} - -.bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); -} - -.bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); -} - -.bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); -} - -.bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-my { - margin-top: var(--py-xs); - margin-bottom: var(--py-xs); - } - - .xs\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); - } - - .xs\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); - } - - .xs\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); - } - - .xs\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } - - .xs\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } - - .xs\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } - - .xs\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } - - .xs\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } - - .xs\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } - - .xs\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } - - .xs\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } - - .xs\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } - - .xs\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } - - .xs\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } - - .xs\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } - - .xs\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-my { - margin-top: var(--py-sm); - margin-bottom: var(--py-sm); - } - - .sm\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); - } - - .sm\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); - } - - .sm\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); - } - - .sm\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } - - .sm\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } - - .sm\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } - - .sm\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } - - .sm\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } - - .sm\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } - - .sm\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } - - .sm\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } - - .sm\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } - - .sm\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } - - .sm\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } - - .sm\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } - - .sm\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-my { - margin-top: var(--py-md); - margin-bottom: var(--py-md); - } - - .md\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); - } - - .md\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); - } - - .md\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); - } - - .md\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } - - .md\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } - - .md\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } - - .md\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } - - .md\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } - - .md\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } - - .md\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } - - .md\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } - - .md\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } - - .md\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } - - .md\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } - - .md\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } - - .md\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-my { - margin-top: var(--py-lg); - margin-bottom: var(--py-lg); - } - - .lg\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); - } - - .lg\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); - } - - .lg\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); - } - - .lg\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } - - .lg\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } - - .lg\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } - - .lg\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } - - .lg\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } - - .lg\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } - - .lg\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } - - .lg\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } - - .lg\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } - - .lg\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } - - .lg\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } - - .lg\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } - - .lg\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-my { - margin-top: var(--py-xl); - margin-bottom: var(--py-xl); - } - - .xl\:bui-my-0\.5 { - margin-top: var(--bui-space-0_5); - margin-bottom: var(--bui-space-0_5); - } - - .xl\:bui-my-1 { - margin-top: var(--bui-space-1); - margin-bottom: var(--bui-space-1); - } - - .xl\:bui-my-1\.5 { - margin-top: var(--bui-space-1_5); - margin-bottom: var(--bui-space-1_5); - } - - .xl\:bui-my-2 { - margin-top: var(--bui-space-2); - margin-bottom: var(--bui-space-2); - } - - .xl\:bui-my-3 { - margin-top: var(--bui-space-3); - margin-bottom: var(--bui-space-3); - } - - .xl\:bui-my-4 { - margin-top: var(--bui-space-4); - margin-bottom: var(--bui-space-4); - } - - .xl\:bui-my-5 { - margin-top: var(--bui-space-5); - margin-bottom: var(--bui-space-5); - } - - .xl\:bui-my-6 { - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - } - - .xl\:bui-my-7 { - margin-top: var(--bui-space-7); - margin-bottom: var(--bui-space-7); - } - - .xl\:bui-my-8 { - margin-top: var(--bui-space-8); - margin-bottom: var(--bui-space-8); - } - - .xl\:bui-my-9 { - margin-top: var(--bui-space-9); - margin-bottom: var(--bui-space-9); - } - - .xl\:bui-my-10 { - margin-top: var(--bui-space-10); - margin-bottom: var(--bui-space-10); - } - - .xl\:bui-my-11 { - margin-top: var(--bui-space-11); - margin-bottom: var(--bui-space-11); - } - - .xl\:bui-my-12 { - margin-top: var(--bui-space-12); - margin-bottom: var(--bui-space-12); - } - - .xl\:bui-my-13 { - margin-top: var(--bui-space-13); - margin-bottom: var(--bui-space-13); - } - - .xl\:bui-my-14 { - margin-top: var(--bui-space-14); - margin-bottom: var(--bui-space-14); - } -} - -.bui-mx { - margin-left: var(--mx); - margin-right: var(--mx); -} - -.bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); -} - -.bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); -} - -.bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); -} - -.bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); -} - -.bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); -} - -.bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); -} - -.bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); -} - -.bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); -} - -.bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); -} - -.bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); -} - -.bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); -} - -.bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); -} - -.bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); -} - -.bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); -} - -.bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); -} - -.bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-mx { - margin-left: var(--px-xs); - margin-right: var(--px-xs); - } - - .xs\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); - } - - .xs\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); - } - - .xs\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); - } - - .xs\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } - - .xs\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } - - .xs\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } - - .xs\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } - - .xs\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } - - .xs\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } - - .xs\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } - - .xs\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } - - .xs\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } - - .xs\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } - - .xs\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } - - .xs\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } - - .xs\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-mx { - margin-left: var(--px-sm); - margin-right: var(--px-sm); - } - - .sm\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); - } - - .sm\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); - } - - .sm\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); - } - - .sm\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } - - .sm\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } - - .sm\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } - - .sm\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } - - .sm\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } - - .sm\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } - - .sm\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } - - .sm\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } - - .sm\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } - - .sm\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } - - .sm\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } - - .sm\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } - - .sm\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-mx { - margin-left: var(--px-md); - margin-right: var(--px-md); - } - - .md\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); - } - - .md\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); - } - - .md\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); - } - - .md\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } - - .md\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } - - .md\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } - - .md\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } - - .md\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } - - .md\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } - - .md\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } - - .md\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } - - .md\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } - - .md\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } - - .md\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } - - .md\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } - - .md\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-mx { - margin-left: var(--px-lg); - margin-right: var(--px-lg); - } - - .lg\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); - } - - .lg\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); - } - - .lg\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); - } - - .lg\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } - - .lg\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } - - .lg\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } - - .lg\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } - - .lg\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } - - .lg\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } - - .lg\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } - - .lg\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } - - .lg\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } - - .lg\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } - - .lg\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } - - .lg\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } - - .lg\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-mx { - margin-left: var(--px-xl); - margin-right: var(--px-xl); - } - - .xl\:bui-mx-0\.5 { - margin-left: var(--bui-space-0_5); - margin-right: var(--bui-space-0_5); - } - - .xl\:bui-mx-1 { - margin-left: var(--bui-space-1); - margin-right: var(--bui-space-1); - } - - .xl\:bui-mx-1\.5 { - margin-left: var(--bui-space-1_5); - margin-right: var(--bui-space-1_5); - } - - .xl\:bui-mx-2 { - margin-left: var(--bui-space-2); - margin-right: var(--bui-space-2); - } - - .xl\:bui-mx-3 { - margin-left: var(--bui-space-3); - margin-right: var(--bui-space-3); - } - - .xl\:bui-mx-4 { - margin-left: var(--bui-space-4); - margin-right: var(--bui-space-4); - } - - .xl\:bui-mx-5 { - margin-left: var(--bui-space-5); - margin-right: var(--bui-space-5); - } - - .xl\:bui-mx-6 { - margin-left: var(--bui-space-6); - margin-right: var(--bui-space-6); - } - - .xl\:bui-mx-7 { - margin-left: var(--bui-space-7); - margin-right: var(--bui-space-7); - } - - .xl\:bui-mx-8 { - margin-left: var(--bui-space-8); - margin-right: var(--bui-space-8); - } - - .xl\:bui-mx-9 { - margin-left: var(--bui-space-9); - margin-right: var(--bui-space-9); - } - - .xl\:bui-mx-10 { - margin-left: var(--bui-space-10); - margin-right: var(--bui-space-10); - } - - .xl\:bui-mx-11 { - margin-left: var(--bui-space-11); - margin-right: var(--bui-space-11); - } - - .xl\:bui-mx-12 { - margin-left: var(--bui-space-12); - margin-right: var(--bui-space-12); - } - - .xl\:bui-mx-13 { - margin-left: var(--bui-space-13); - margin-right: var(--bui-space-13); - } - - .xl\:bui-mx-14 { - margin-left: var(--bui-space-14); - margin-right: var(--bui-space-14); - } -} - -.bui-display-none { - display: none; -} - -.bui-display-inline { - display: inline; -} - -.bui-display-inline-block { - display: inline-block; -} - -.bui-display-block { - display: block; -} - -@media (width >= 640px) { - .xs\:bui-display-none { - display: none; - } - - .xs\:bui-display-inline { - display: inline; - } - - .xs\:bui-display-inline-block { - display: inline-block; - } - - .xs\:bui-display-block { - display: block; - } -} - -@media (width >= 768px) { - .sm\:bui-display-none { - display: none; - } - - .sm\:bui-display-inline { - display: inline; - } - - .sm\:bui-display-inline-block { - display: inline-block; - } - - .sm\:bui-display-block { - display: block; - } -} - -@media (width >= 1024px) { - .md\:bui-display-none { - display: none; - } - - .md\:bui-display-inline { - display: inline; - } - - .md\:bui-display-inline-block { - display: inline-block; - } - - .md\:bui-display-block { - display: block; - } -} - -@media (width >= 1280px) { - .lg\:bui-display-none { - display: none; - } - - .lg\:bui-display-inline { - display: inline; - } - - .lg\:bui-display-inline-block { - display: inline-block; - } - - .lg\:bui-display-block { - display: block; - } -} - -@media (width >= 1536px) { - .xl\:bui-display-none { - display: none; - } - - .xl\:bui-display-inline { - display: inline; - } - - .xl\:bui-display-inline-block { - display: inline-block; - } - - .xl\:bui-display-block { - display: block; - } -} - -.bui-w { - width: var(--width); -} - -.bui-min-w { - min-width: var(--min-width); -} - -.bui-max-w { - max-width: var(--max-width); -} - -@media (width >= 640px) { - .xs\:bui-w { - width: var(--width); - } - - .xs\:bui-min-w { - min-width: var(--min-width); - } - - .xs\:bui-max-w { - max-width: var(--max-width); - } -} - -@media (width >= 768px) { - .sm\:bui-w { - width: var(--width); - } - - .sm\:bui-min-w { - min-width: var(--min-width); - } - - .sm\:bui-max-w { - max-width: var(--max-width); - } -} - -@media (width >= 1024px) { - .md\:bui-w { - width: var(--width); - } - - .md\:bui-min-w { - min-width: var(--min-width); - } - - .md\:bui-max-w { - max-width: var(--max-width); - } -} - -@media (width >= 1280px) { - .lg\:bui-w { - width: var(--width); - } - - .lg\:bui-min-w { - min-width: var(--min-width); - } - - .lg\:bui-max-w { - max-width: var(--max-width); - } -} - -@media (width >= 1536px) { - .xl\:bui-w { - width: var(--width); - } - - .xl\:bui-min-w { - min-width: var(--min-width); - } - - .xl\:bui-max-w { - max-width: var(--max-width); - } -} - -.bui-h { - height: var(--height); -} - -.bui-min-h { - min-height: var(--min-height); -} - -.bui-max-h { - max-height: var(--max-height); -} - -@media (width >= 640px) { - .xs\:bui-h { - height: var(--height); - } - - .xs\:bui-min-h { - min-height: var(--min-height); - } - - .xs\:bui-max-h { - max-height: var(--max-height); - } -} - -@media (width >= 768px) { - .sm\:bui-h { - height: var(--height); - } - - .sm\:bui-min-h { - min-height: var(--min-height); - } - - .sm\:bui-max-h { - max-height: var(--max-height); - } -} - -@media (width >= 1024px) { - .md\:bui-h { - height: var(--height); - } - - .md\:bui-min-h { - min-height: var(--min-height); - } - - .md\:bui-max-h { - max-height: var(--max-height); - } -} - -@media (width >= 1280px) { - .lg\:bui-h { - height: var(--height); - } - - .lg\:bui-min-h { - min-height: var(--min-height); - } - - .lg\:bui-max-h { - max-height: var(--max-height); - } -} - -@media (width >= 1536px) { - .xl\:bui-h { - height: var(--height); - } - - .xl\:bui-min-h { - min-height: var(--min-height); - } - - .xl\:bui-max-h { - max-height: var(--max-height); - } -} - -.bui-position-absolute { - position: absolute; -} - -.bui-position-fixed { - position: fixed; -} - -.bui-position-sticky { - position: sticky; -} - -.bui-position-relative { - position: relative; -} - -.bui-position-static { - position: static; -} - -@media (width >= 640px) { - .xs\:bui-position-absolute { - position: absolute; - } - - .xs\:bui-position-fixed { - position: fixed; - } - - .xs\:bui-position-sticky { - position: sticky; - } - - .xs\:bui-position-relative { - position: relative; - } - - .xs\:bui-position-static { - position: static; - } -} - -@media (width >= 768px) { - .sm\:bui-position-absolute { - position: absolute; - } - - .sm\:bui-position-fixed { - position: fixed; - } - - .sm\:bui-position-sticky { - position: sticky; - } - - .sm\:bui-position-relative { - position: relative; - } - - .sm\:bui-position-static { - position: static; - } -} - -@media (width >= 1024px) { - .md\:bui-position-absolute { - position: absolute; - } - - .md\:bui-position-fixed { - position: fixed; - } - - .md\:bui-position-sticky { - position: sticky; - } - - .md\:bui-position-relative { - position: relative; - } - - .md\:bui-position-static { - position: static; - } -} - -@media (width >= 1280px) { - .lg\:bui-position-absolute { - position: absolute; - } - - .lg\:bui-position-fixed { - position: fixed; - } - - .lg\:bui-position-sticky { - position: sticky; - } - - .lg\:bui-position-relative { - position: relative; - } - - .lg\:bui-position-static { - position: static; - } -} - -@media (width >= 1536px) { - .xl\:bui-position-absolute { - position: absolute; - } - - .xl\:bui-position-fixed { - position: fixed; - } - - .xl\:bui-position-sticky { - position: sticky; - } - - .xl\:bui-position-relative { - position: relative; - } - - .xl\:bui-position-static { - position: static; - } -} - -.bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); -} - -.bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); -} - -.bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); -} - -.bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); -} - -.bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); -} - -.bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); -} - -.bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); -} - -.bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); -} - -.bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); -} - -.bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); -} - -.bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); -} - -.bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); -} - -.bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); -} - -.bui-col-span-1 { - grid-column: span 1 / span 1; -} - -.bui-col-span-2 { - grid-column: span 2 / span 2; -} - -.bui-col-span-3 { - grid-column: span 3 / span 3; -} - -.bui-col-span-4 { - grid-column: span 4 / span 4; -} - -.bui-col-span-5 { - grid-column: span 5 / span 5; -} - -.bui-col-span-6 { - grid-column: span 6 / span 6; -} - -.bui-col-span-7 { - grid-column: span 7 / span 7; -} - -.bui-col-span-8 { - grid-column: span 8 / span 8; -} - -.bui-col-span-9 { - grid-column: span 9 / span 9; -} - -.bui-col-span-10 { - grid-column: span 10 / span 10; -} - -.bui-col-span-11 { - grid-column: span 11 / span 11; -} - -.bui-col-span-12 { - grid-column: span 12 / span 12; -} - -.bui-col-span-auto { - grid-column: span auto / span auto; -} - -.bui-col-start-1 { - grid-column-start: 1; -} - -.bui-col-start-2 { - grid-column-start: 2; -} - -.bui-col-start-3 { - grid-column-start: 3; -} - -.bui-col-start-4 { - grid-column-start: 4; -} - -.bui-col-start-5 { - grid-column-start: 5; -} - -.bui-col-start-6 { - grid-column-start: 6; -} - -.bui-col-start-7 { - grid-column-start: 7; -} - -.bui-col-start-8 { - grid-column-start: 8; -} - -.bui-col-start-9 { - grid-column-start: 9; -} - -.bui-col-start-10 { - grid-column-start: 10; -} - -.bui-col-start-11 { - grid-column-start: 11; -} - -.bui-col-start-12 { - grid-column-start: 12; -} - -.bui-col-start-13 { - grid-column-start: 13; -} - -.bui-col-start-auto { - grid-column-start: auto; -} - -.bui-col-end-1 { - grid-column-end: 1; -} - -.bui-col-end-2 { - grid-column-end: 2; -} - -.bui-col-end-3 { - grid-column-end: 3; -} - -.bui-col-end-4 { - grid-column-end: 4; -} - -.bui-col-end-5 { - grid-column-end: 5; -} - -.bui-col-end-6 { - grid-column-end: 6; -} - -.bui-col-end-7 { - grid-column-end: 7; -} - -.bui-col-end-8 { - grid-column-end: 8; -} - -.bui-col-end-9 { - grid-column-end: 9; -} - -.bui-col-end-10 { - grid-column-end: 10; -} - -.bui-col-end-11 { - grid-column-end: 11; -} - -.bui-col-end-12 { - grid-column-end: 12; -} - -.bui-col-end-13 { - grid-column-end: 13; -} - -.bui-col-end-auto { - grid-column-end: auto; -} - -.bui-row-span-1 { - grid-row: span 1 / span 1; -} - -.bui-row-span-2 { - grid-row: span 2 / span 2; -} - -.bui-row-span-3 { - grid-row: span 3 / span 3; -} - -.bui-row-span-4 { - grid-row: span 4 / span 4; -} - -.bui-row-span-5 { - grid-row: span 5 / span 5; -} - -.bui-row-span-6 { - grid-row: span 6 / span 6; -} - -.bui-row-span-7 { - grid-row: span 7 / span 7; -} - -.bui-row-span-8 { - grid-row: span 8 / span 8; -} - -.bui-row-span-9 { - grid-row: span 9 / span 9; -} - -.bui-row-span-10 { - grid-row: span 10 / span 10; -} - -.bui-row-span-11 { - grid-row: span 11 / span 11; -} - -.bui-row-span-12 { - grid-row: span 12 / span 12; -} - -.bui-row-span-auto { - grid-row: span auto / span auto; -} - -@media (width >= 640px) { - .xs\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .xs\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .xs\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .xs\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .xs\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .xs\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .xs\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .xs\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .xs\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .xs\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .xs\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .xs\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .xs\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .xs\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - - .xs\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - - .xs\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - - .xs\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - - .xs\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - - .xs\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - - .xs\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - - .xs\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - - .xs\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - - .xs\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - - .xs\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - - .xs\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - - .xs\:bui-col-span-auto { - grid-column: span auto / span auto; - } - - .xs\:bui-col-start-1 { - grid-column-start: 1; - } - - .xs\:bui-col-start-2 { - grid-column-start: 2; - } - - .xs\:bui-col-start-3 { - grid-column-start: 3; - } - - .xs\:bui-col-start-4 { - grid-column-start: 4; - } - - .xs\:bui-col-start-5 { - grid-column-start: 5; - } - - .xs\:bui-col-start-6 { - grid-column-start: 6; - } - - .xs\:bui-col-start-7 { - grid-column-start: 7; - } - - .xs\:bui-col-start-8 { - grid-column-start: 8; - } - - .xs\:bui-col-start-9 { - grid-column-start: 9; - } - - .xs\:bui-col-start-10 { - grid-column-start: 10; - } - - .xs\:bui-col-start-11 { - grid-column-start: 11; - } - - .xs\:bui-col-start-12 { - grid-column-start: 12; - } - - .xs\:bui-col-start-13 { - grid-column-start: 13; - } - - .xs\:bui-col-start-auto { - grid-column-start: auto; - } - - .xs\:bui-col-end-1 { - grid-column-end: 1; - } - - .xs\:bui-col-end-2 { - grid-column-end: 2; - } - - .xs\:bui-col-end-3 { - grid-column-end: 3; - } - - .xs\:bui-col-end-4 { - grid-column-end: 4; - } - - .xs\:bui-col-end-5 { - grid-column-end: 5; - } - - .xs\:bui-col-end-6 { - grid-column-end: 6; - } - - .xs\:bui-col-end-7 { - grid-column-end: 7; - } - - .xs\:bui-col-end-8 { - grid-column-end: 8; - } - - .xs\:bui-col-end-9 { - grid-column-end: 9; - } - - .xs\:bui-col-end-10 { - grid-column-end: 10; - } - - .xs\:bui-col-end-11 { - grid-column-end: 11; - } - - .xs\:bui-col-end-12 { - grid-column-end: 12; - } - - .xs\:bui-col-end-13 { - grid-column-end: 13; - } - - .xs\:bui-col-end-auto { - grid-column-end: auto; - } - - .xs\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - - .xs\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - - .xs\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - - .xs\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - - .xs\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - - .xs\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - - .xs\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - - .xs\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - - .xs\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - - .xs\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - - .xs\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - - .xs\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - - .xs\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} - -@media (width >= 768px) { - .sm\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .sm\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .sm\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .sm\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .sm\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .sm\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .sm\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .sm\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .sm\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .sm\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .sm\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .sm\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .sm\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .sm\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - - .sm\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - - .sm\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - - .sm\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - - .sm\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - - .sm\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - - .sm\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - - .sm\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - - .sm\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - - .sm\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - - .sm\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - - .sm\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - - .sm\:bui-col-span-auto { - grid-column: span auto / span auto; - } - - .sm\:bui-col-start-1 { - grid-column-start: 1; - } - - .sm\:bui-col-start-2 { - grid-column-start: 2; - } - - .sm\:bui-col-start-3 { - grid-column-start: 3; - } - - .sm\:bui-col-start-4 { - grid-column-start: 4; - } - - .sm\:bui-col-start-5 { - grid-column-start: 5; - } - - .sm\:bui-col-start-6 { - grid-column-start: 6; - } - - .sm\:bui-col-start-7 { - grid-column-start: 7; - } - - .sm\:bui-col-start-8 { - grid-column-start: 8; - } - - .sm\:bui-col-start-9 { - grid-column-start: 9; - } - - .sm\:bui-col-start-10 { - grid-column-start: 10; - } - - .sm\:bui-col-start-11 { - grid-column-start: 11; - } - - .sm\:bui-col-start-12 { - grid-column-start: 12; - } - - .sm\:bui-col-start-13 { - grid-column-start: 13; - } - - .sm\:bui-col-start-auto { - grid-column-start: auto; - } - - .sm\:bui-col-end-1 { - grid-column-end: 1; - } - - .sm\:bui-col-end-2 { - grid-column-end: 2; - } - - .sm\:bui-col-end-3 { - grid-column-end: 3; - } - - .sm\:bui-col-end-4 { - grid-column-end: 4; - } - - .sm\:bui-col-end-5 { - grid-column-end: 5; - } - - .sm\:bui-col-end-6 { - grid-column-end: 6; - } - - .sm\:bui-col-end-7 { - grid-column-end: 7; - } - - .sm\:bui-col-end-8 { - grid-column-end: 8; - } - - .sm\:bui-col-end-9 { - grid-column-end: 9; - } - - .sm\:bui-col-end-10 { - grid-column-end: 10; - } - - .sm\:bui-col-end-11 { - grid-column-end: 11; - } - - .sm\:bui-col-end-12 { - grid-column-end: 12; - } - - .sm\:bui-col-end-13 { - grid-column-end: 13; - } - - .sm\:bui-col-end-auto { - grid-column-end: auto; - } - - .sm\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - - .sm\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - - .sm\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - - .sm\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - - .sm\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - - .sm\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - - .sm\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - - .sm\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - - .sm\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - - .sm\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - - .sm\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - - .sm\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - - .sm\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} - -@media (width >= 1024px) { - .md\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .md\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .md\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .md\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .md\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .md\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .md\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .md\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .md\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .md\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .md\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .md\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .md\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .md\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - - .md\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - - .md\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - - .md\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - - .md\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - - .md\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - - .md\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - - .md\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - - .md\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - - .md\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - - .md\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - - .md\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - - .md\:bui-col-span-auto { - grid-column: span auto / span auto; - } - - .md\:bui-col-start-1 { - grid-column-start: 1; - } - - .md\:bui-col-start-2 { - grid-column-start: 2; - } - - .md\:bui-col-start-3 { - grid-column-start: 3; - } - - .md\:bui-col-start-4 { - grid-column-start: 4; - } - - .md\:bui-col-start-5 { - grid-column-start: 5; - } - - .md\:bui-col-start-6 { - grid-column-start: 6; - } - - .md\:bui-col-start-7 { - grid-column-start: 7; - } - - .md\:bui-col-start-8 { - grid-column-start: 8; - } - - .md\:bui-col-start-9 { - grid-column-start: 9; - } - - .md\:bui-col-start-10 { - grid-column-start: 10; - } - - .md\:bui-col-start-11 { - grid-column-start: 11; - } - - .md\:bui-col-start-12 { - grid-column-start: 12; - } - - .md\:bui-col-start-13 { - grid-column-start: 13; - } - - .md\:bui-col-start-auto { - grid-column-start: auto; - } - - .md\:bui-col-end-1 { - grid-column-end: 1; - } - - .md\:bui-col-end-2 { - grid-column-end: 2; - } - - .md\:bui-col-end-3 { - grid-column-end: 3; - } - - .md\:bui-col-end-4 { - grid-column-end: 4; - } - - .md\:bui-col-end-5 { - grid-column-end: 5; - } - - .md\:bui-col-end-6 { - grid-column-end: 6; - } - - .md\:bui-col-end-7 { - grid-column-end: 7; - } - - .md\:bui-col-end-8 { - grid-column-end: 8; - } - - .md\:bui-col-end-9 { - grid-column-end: 9; - } - - .md\:bui-col-end-10 { - grid-column-end: 10; - } - - .md\:bui-col-end-11 { - grid-column-end: 11; - } - - .md\:bui-col-end-12 { - grid-column-end: 12; - } - - .md\:bui-col-end-13 { - grid-column-end: 13; - } - - .md\:bui-col-end-auto { - grid-column-end: auto; - } - - .md\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - - .md\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - - .md\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - - .md\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - - .md\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - - .md\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - - .md\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - - .md\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - - .md\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - - .md\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - - .md\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - - .md\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - - .md\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} - -@media (width >= 1280px) { - .lg\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .lg\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .lg\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .lg\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .lg\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .lg\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .lg\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .lg\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .lg\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .lg\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .lg\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .lg\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .lg\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .lg\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - - .lg\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - - .lg\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - - .lg\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - - .lg\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - - .lg\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - - .lg\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - - .lg\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - - .lg\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - - .lg\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - - .lg\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - - .lg\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - - .lg\:bui-col-span-auto { - grid-column: span auto / span auto; - } - - .lg\:bui-col-start-1 { - grid-column-start: 1; - } - - .lg\:bui-col-start-2 { - grid-column-start: 2; - } - - .lg\:bui-col-start-3 { - grid-column-start: 3; - } - - .lg\:bui-col-start-4 { - grid-column-start: 4; - } - - .lg\:bui-col-start-5 { - grid-column-start: 5; - } - - .lg\:bui-col-start-6 { - grid-column-start: 6; - } - - .lg\:bui-col-start-7 { - grid-column-start: 7; - } - - .lg\:bui-col-start-8 { - grid-column-start: 8; - } - - .lg\:bui-col-start-9 { - grid-column-start: 9; - } - - .lg\:bui-col-start-10 { - grid-column-start: 10; - } - - .lg\:bui-col-start-11 { - grid-column-start: 11; - } - - .lg\:bui-col-start-12 { - grid-column-start: 12; - } - - .lg\:bui-col-start-13 { - grid-column-start: 13; - } - - .lg\:bui-col-start-auto { - grid-column-start: auto; - } - - .lg\:bui-col-end-1 { - grid-column-end: 1; - } - - .lg\:bui-col-end-2 { - grid-column-end: 2; - } - - .lg\:bui-col-end-3 { - grid-column-end: 3; - } - - .lg\:bui-col-end-4 { - grid-column-end: 4; - } - - .lg\:bui-col-end-5 { - grid-column-end: 5; - } - - .lg\:bui-col-end-6 { - grid-column-end: 6; - } - - .lg\:bui-col-end-7 { - grid-column-end: 7; - } - - .lg\:bui-col-end-8 { - grid-column-end: 8; - } - - .lg\:bui-col-end-9 { - grid-column-end: 9; - } - - .lg\:bui-col-end-10 { - grid-column-end: 10; - } - - .lg\:bui-col-end-11 { - grid-column-end: 11; - } - - .lg\:bui-col-end-12 { - grid-column-end: 12; - } - - .lg\:bui-col-end-13 { - grid-column-end: 13; - } - - .lg\:bui-col-end-auto { - grid-column-end: auto; - } - - .lg\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - - .lg\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - - .lg\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - - .lg\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - - .lg\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - - .lg\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - - .lg\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - - .lg\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - - .lg\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - - .lg\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - - .lg\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - - .lg\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - - .lg\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} - -@media (width >= 1536px) { - .xl\:bui-columns-1 { - grid-template-columns: repeat(1, minmax(0, 1fr)); - } - - .xl\:bui-columns-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); - } - - .xl\:bui-columns-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); - } - - .xl\:bui-columns-4 { - grid-template-columns: repeat(4, minmax(0, 1fr)); - } - - .xl\:bui-columns-5 { - grid-template-columns: repeat(5, minmax(0, 1fr)); - } - - .xl\:bui-columns-6 { - grid-template-columns: repeat(6, minmax(0, 1fr)); - } - - .xl\:bui-columns-7 { - grid-template-columns: repeat(7, minmax(0, 1fr)); - } - - .xl\:bui-columns-8 { - grid-template-columns: repeat(8, minmax(0, 1fr)); - } - - .xl\:bui-columns-9 { - grid-template-columns: repeat(9, minmax(0, 1fr)); - } - - .xl\:bui-columns-10 { - grid-template-columns: repeat(10, minmax(0, 1fr)); - } - - .xl\:bui-columns-11 { - grid-template-columns: repeat(11, minmax(0, 1fr)); - } - - .xl\:bui-columns-12 { - grid-template-columns: repeat(12, minmax(0, 1fr)); - } - - .xl\:bui-columns-auto { - grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); - } - - .xl\:bui-col-span-1 { - grid-column: span 1 / span 1; - } - - .xl\:bui-col-span-2 { - grid-column: span 2 / span 2; - } - - .xl\:bui-col-span-3 { - grid-column: span 3 / span 3; - } - - .xl\:bui-col-span-4 { - grid-column: span 4 / span 4; - } - - .xl\:bui-col-span-5 { - grid-column: span 5 / span 5; - } - - .xl\:bui-col-span-6 { - grid-column: span 6 / span 6; - } - - .xl\:bui-col-span-7 { - grid-column: span 7 / span 7; - } - - .xl\:bui-col-span-8 { - grid-column: span 8 / span 8; - } - - .xl\:bui-col-span-9 { - grid-column: span 9 / span 9; - } - - .xl\:bui-col-span-10 { - grid-column: span 10 / span 10; - } - - .xl\:bui-col-span-11 { - grid-column: span 11 / span 11; - } - - .xl\:bui-col-span-12 { - grid-column: span 12 / span 12; - } - - .xl\:bui-col-span-auto { - grid-column: span auto / span auto; - } - - .xl\:bui-col-start-1 { - grid-column-start: 1; - } - - .xl\:bui-col-start-2 { - grid-column-start: 2; - } - - .xl\:bui-col-start-3 { - grid-column-start: 3; - } - - .xl\:bui-col-start-4 { - grid-column-start: 4; - } - - .xl\:bui-col-start-5 { - grid-column-start: 5; - } - - .xl\:bui-col-start-6 { - grid-column-start: 6; - } - - .xl\:bui-col-start-7 { - grid-column-start: 7; - } - - .xl\:bui-col-start-8 { - grid-column-start: 8; - } - - .xl\:bui-col-start-9 { - grid-column-start: 9; - } - - .xl\:bui-col-start-10 { - grid-column-start: 10; - } - - .xl\:bui-col-start-11 { - grid-column-start: 11; - } - - .xl\:bui-col-start-12 { - grid-column-start: 12; - } - - .xl\:bui-col-start-13 { - grid-column-start: 13; - } - - .xl\:bui-col-start-auto { - grid-column-start: auto; - } - - .xl\:bui-col-end-1 { - grid-column-end: 1; - } - - .xl\:bui-col-end-2 { - grid-column-end: 2; - } - - .xl\:bui-col-end-3 { - grid-column-end: 3; - } - - .xl\:bui-col-end-4 { - grid-column-end: 4; - } - - .xl\:bui-col-end-5 { - grid-column-end: 5; - } - - .xl\:bui-col-end-6 { - grid-column-end: 6; - } - - .xl\:bui-col-end-7 { - grid-column-end: 7; - } - - .xl\:bui-col-end-8 { - grid-column-end: 8; - } - - .xl\:bui-col-end-9 { - grid-column-end: 9; - } - - .xl\:bui-col-end-10 { - grid-column-end: 10; - } - - .xl\:bui-col-end-11 { - grid-column-end: 11; - } - - .xl\:bui-col-end-12 { - grid-column-end: 12; - } - - .xl\:bui-col-end-13 { - grid-column-end: 13; - } - - .xl\:bui-col-end-auto { - grid-column-end: auto; - } - - .xl\:bui-row-span-1 { - grid-row: span 1 / span 1; - } - - .xl\:bui-row-span-2 { - grid-row: span 2 / span 2; - } - - .xl\:bui-row-span-3 { - grid-row: span 3 / span 3; - } - - .xl\:bui-row-span-4 { - grid-row: span 4 / span 4; - } - - .xl\:bui-row-span-5 { - grid-row: span 5 / span 5; - } - - .xl\:bui-row-span-6 { - grid-row: span 6 / span 6; - } - - .xl\:bui-row-span-7 { - grid-row: span 7 / span 7; - } - - .xl\:bui-row-span-8 { - grid-row: span 8 / span 8; - } - - .xl\:bui-row-span-9 { - grid-row: span 9 / span 9; - } - - .xl\:bui-row-span-10 { - grid-row: span 10 / span 10; - } - - .xl\:bui-row-span-11 { - grid-row: span 11 / span 11; - } - - .xl\:bui-row-span-12 { - grid-row: span 12 / span 12; - } - - .xl\:bui-row-span-auto { - grid-row: span auto / span auto; - } -} - -.bui-gap { - gap: var(--gap); -} - -.bui-gap-0\.5 { - gap: var(--bui-space-0_5); -} - -.bui-gap-1 { - gap: var(--bui-space-1); -} - -.bui-gap-1\.5 { - gap: var(--bui-space-1_5); -} - -.bui-gap-2 { - gap: var(--bui-space-2); -} - -.bui-gap-3 { - gap: var(--bui-space-3); -} - -.bui-gap-4 { - gap: var(--bui-space-4); -} - -.bui-gap-5 { - gap: var(--bui-space-5); -} - -.bui-gap-6 { - gap: var(--bui-space-6); -} - -.bui-gap-7 { - gap: var(--bui-space-7); -} - -.bui-gap-8 { - gap: var(--bui-space-8); -} - -.bui-gap-9 { - gap: var(--bui-space-9); -} - -.bui-gap-10 { - gap: var(--bui-space-10); -} - -.bui-gap-11 { - gap: var(--bui-space-11); -} - -.bui-gap-12 { - gap: var(--bui-space-12); -} - -.bui-gap-13 { - gap: var(--bui-space-13); -} - -.bui-gap-14 { - gap: var(--bui-space-14); -} - -@media (width >= 640px) { - .xs\:bui-gap { - gap: var(--gap-xs); - } - - .xs\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); - } - - .xs\:bui-gap-1 { - gap: var(--bui-space-1); - } - - .xs\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); - } - - .xs\:bui-gap-2 { - gap: var(--bui-space-2); - } - - .xs\:bui-gap-3 { - gap: var(--bui-space-3); - } - - .xs\:bui-gap-4 { - gap: var(--bui-space-4); - } - - .xs\:bui-gap-5 { - gap: var(--bui-space-5); - } - - .xs\:bui-gap-6 { - gap: var(--bui-space-6); - } - - .xs\:bui-gap-7 { - gap: var(--bui-space-7); - } - - .xs\:bui-gap-8 { - gap: var(--bui-space-8); - } - - .xs\:bui-gap-9 { - gap: var(--bui-space-9); - } - - .xs\:bui-gap-10 { - gap: var(--bui-space-10); - } - - .xs\:bui-gap-11 { - gap: var(--bui-space-11); - } - - .xs\:bui-gap-12 { - gap: var(--bui-space-12); - } - - .xs\:bui-gap-13 { - gap: var(--bui-space-13); - } - - .xs\:bui-gap-14 { - gap: var(--bui-space-14); - } -} - -@media (width >= 768px) { - .sm\:bui-gap { - gap: var(--gap-sm); - } - - .sm\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); - } - - .sm\:bui-gap-1 { - gap: var(--bui-space-1); - } - - .sm\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); - } - - .sm\:bui-gap-2 { - gap: var(--bui-space-2); - } - - .sm\:bui-gap-3 { - gap: var(--bui-space-3); - } - - .sm\:bui-gap-4 { - gap: var(--bui-space-4); - } - - .sm\:bui-gap-5 { - gap: var(--bui-space-5); - } - - .sm\:bui-gap-6 { - gap: var(--bui-space-6); - } - - .sm\:bui-gap-7 { - gap: var(--bui-space-7); - } - - .sm\:bui-gap-8 { - gap: var(--bui-space-8); - } - - .sm\:bui-gap-9 { - gap: var(--bui-space-9); - } - - .sm\:bui-gap-10 { - gap: var(--bui-space-10); - } - - .sm\:bui-gap-11 { - gap: var(--bui-space-11); - } - - .sm\:bui-gap-12 { - gap: var(--bui-space-12); - } - - .sm\:bui-gap-13 { - gap: var(--bui-space-13); - } - - .sm\:bui-gap-14 { - gap: var(--bui-space-14); - } -} - -@media (width >= 1024px) { - .md\:bui-gap { - gap: var(--gap-md); - } - - .md\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); - } - - .md\:bui-gap-1 { - gap: var(--bui-space-1); - } - - .md\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); - } - - .md\:bui-gap-2 { - gap: var(--bui-space-2); - } - - .md\:bui-gap-3 { - gap: var(--bui-space-3); - } - - .md\:bui-gap-4 { - gap: var(--bui-space-4); - } - - .md\:bui-gap-5 { - gap: var(--bui-space-5); - } - - .md\:bui-gap-6 { - gap: var(--bui-space-6); - } - - .md\:bui-gap-7 { - gap: var(--bui-space-7); - } - - .md\:bui-gap-8 { - gap: var(--bui-space-8); - } - - .md\:bui-gap-9 { - gap: var(--bui-space-9); - } - - .md\:bui-gap-10 { - gap: var(--bui-space-10); - } - - .md\:bui-gap-11 { - gap: var(--bui-space-11); - } - - .md\:bui-gap-12 { - gap: var(--bui-space-12); - } - - .md\:bui-gap-13 { - gap: var(--bui-space-13); - } - - .md\:bui-gap-14 { - gap: var(--bui-space-14); - } -} - -@media (width >= 1280px) { - .lg\:bui-gap { - gap: var(--gap-lg); + :where(a) { + color: inherit; + text-decoration: none; } - .lg\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); - } - - .lg\:bui-gap-1 { - gap: var(--bui-space-1); - } - - .lg\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); - } - - .lg\:bui-gap-2 { - gap: var(--bui-space-2); - } - - .lg\:bui-gap-3 { - gap: var(--bui-space-3); - } - - .lg\:bui-gap-4 { - gap: var(--bui-space-4); - } - - .lg\:bui-gap-5 { - gap: var(--bui-space-5); - } - - .lg\:bui-gap-6 { - gap: var(--bui-space-6); - } - - .lg\:bui-gap-7 { - gap: var(--bui-space-7); - } - - .lg\:bui-gap-8 { - gap: var(--bui-space-8); - } - - .lg\:bui-gap-9 { - gap: var(--bui-space-9); - } - - .lg\:bui-gap-10 { - gap: var(--bui-space-10); - } - - .lg\:bui-gap-11 { - gap: var(--bui-space-11); - } - - .lg\:bui-gap-12 { - gap: var(--bui-space-12); - } - - .lg\:bui-gap-13 { - gap: var(--bui-space-13); - } - - .lg\:bui-gap-14 { - gap: var(--bui-space-14); - } -} - -@media (width >= 1536px) { - .xl\:bui-gap { - gap: var(--gap-xl); - } - - .xl\:bui-gap-0\.5 { - gap: var(--bui-space-0_5); - } - - .xl\:bui-gap-1 { - gap: var(--bui-space-1); - } - - .xl\:bui-gap-1\.5 { - gap: var(--bui-space-1_5); - } - - .xl\:bui-gap-2 { - gap: var(--bui-space-2); - } - - .xl\:bui-gap-3 { - gap: var(--bui-space-3); - } - - .xl\:bui-gap-4 { - gap: var(--bui-space-4); - } - - .xl\:bui-gap-5 { - gap: var(--bui-space-5); - } - - .xl\:bui-gap-6 { - gap: var(--bui-space-6); - } - - .xl\:bui-gap-7 { - gap: var(--bui-space-7); - } - - .xl\:bui-gap-8 { - gap: var(--bui-space-8); - } - - .xl\:bui-gap-9 { - gap: var(--bui-space-9); - } - - .xl\:bui-gap-10 { - gap: var(--bui-space-10); - } - - .xl\:bui-gap-11 { - gap: var(--bui-space-11); - } - - .xl\:bui-gap-12 { - gap: var(--bui-space-12); - } - - .xl\:bui-gap-13 { - gap: var(--bui-space-13); - } - - .xl\:bui-gap-14 { - gap: var(--bui-space-14); - } -} - -.bui-align-start { - align-items: start; -} - -.bui-align-center { - align-items: center; -} - -.bui-align-end { - align-items: end; -} - -.bui-align-baseline { - align-items: baseline; -} - -.bui-align-stretch { - align-items: stretch; -} - -.bui-jc-start { - justify-content: start; -} - -.bui-jc-center { - justify-content: center; -} - -.bui-jc-end { - justify-content: end; -} - -.bui-jc-between { - justify-content: space-between; -} - -.bui-fd-row { - flex-direction: row; -} - -.bui-fd-column { - flex-direction: column; -} - -.bui-fd-row-reverse { - flex-direction: row-reverse; -} - -.bui-fd-column-reverse { - flex-direction: column-reverse; -} - -@media (width >= 640px) { - .xs\:bui-align-start { - align-items: start; - } - - .xs\:bui-align-center { - align-items: center; - } - - .xs\:bui-align-end { - align-items: end; - } - - .xs\:bui-align-stretch { - align-items: stretch; - } - - .xs\:bui-jc-start { - justify-content: start; - } - - .xs\:bui-jc-center { - justify-content: center; - } - - .xs\:bui-jc-end { - justify-content: end; - } - - .xs\:bui-jc-between { - justify-content: space-between; - } - - .xs\:bui-fd-row { - flex-direction: row; - } - - .xs\:bui-fd-column { - flex-direction: column; - } - - .xs\:bui-fd-row-reverse { - flex-direction: row-reverse; - } - - .xs\:bui-fd-column-reverse { - flex-direction: column-reverse; - } -} - -@media (width >= 768px) { - .sm\:bui-align-start { - align-items: start; - } - - .sm\:bui-align-center { - align-items: center; - } - - .sm\:bui-align-end { - align-items: end; - } - - .sm\:bui-align-stretch { - align-items: stretch; - } - - .sm\:bui-jc-start { - justify-content: start; - } - - .sm\:bui-jc-center { - justify-content: center; - } - - .sm\:bui-jc-end { - justify-content: end; - } - - .sm\:bui-jc-between { - justify-content: space-between; - } - - .sm\:bui-fd-row { - flex-direction: row; - } - - .sm\:bui-fd-column { - flex-direction: column; - } - - .sm\:bui-fd-row-reverse { - flex-direction: row-reverse; - } - - .sm\:bui-fd-column-reverse { - flex-direction: column-reverse; - } -} - -@media (width >= 1024px) { - .md\:bui-align-start { - align-items: start; - } - - .md\:bui-align-center { - align-items: center; - } - - .md\:bui-align-end { - align-items: end; - } - - .md\:bui-align-stretch { - align-items: stretch; - } - - .md\:bui-jc-start { - justify-content: start; - } - - .md\:bui-jc-center { - justify-content: center; - } - - .md\:bui-jc-end { - justify-content: end; - } - - .md\:bui-jc-between { - justify-content: space-between; - } - - .md\:bui-fd-row { - flex-direction: row; - } - - .md\:bui-fd-column { - flex-direction: column; - } - - .md\:bui-fd-row-reverse { - flex-direction: row-reverse; - } - - .md\:bui-fd-column-reverse { - flex-direction: column-reverse; - } -} - -@media (width >= 1280px) { - .lg\:bui-align-start { - align-items: start; - } - - .lg\:bui-align-center { - align-items: center; - } - - .lg\:bui-align-end { - align-items: end; - } - - .lg\:bui-align-stretch { - align-items: stretch; - } - - .lg\:bui-jc-start { - justify-content: start; - } - - .lg\:bui-jc-center { - justify-content: center; - } - - .lg\:bui-jc-end { - justify-content: end; - } - - .lg\:bui-jc-between { - justify-content: space-between; - } - - .lg\:bui-fd-row { - flex-direction: row; - } - - .lg\:bui-fd-column { - flex-direction: column; - } - - .lg\:bui-fd-row-reverse { - flex-direction: row-reverse; - } - - .lg\:bui-fd-column-reverse { - flex-direction: column-reverse; - } -} - -@media (width >= 1536px) { - .xl\:bui-align-start { - align-items: start; - } - - .xl\:bui-align-center { - align-items: center; - } - - .xl\:bui-align-end { - align-items: end; - } - - .xl\:bui-align-stretch { - align-items: stretch; - } - - .xl\:bui-jc-start { - justify-content: start; - } - - .xl\:bui-jc-center { - justify-content: center; - } - - .xl\:bui-jc-end { - justify-content: end; - } - - .xl\:bui-jc-between { - justify-content: space-between; - } - - .xl\:bui-fd-row { - flex-direction: row; - } - - .xl\:bui-fd-column { - flex-direction: column; - } - - .xl\:bui-fd-row-reverse { - flex-direction: row-reverse; - } - - .xl\:bui-fd-column-reverse { - flex-direction: column-reverse; - } -} - -:where(a) { - color: inherit; - text-decoration: none; -} - -@keyframes pulse { - 50% { - opacity: .5; - } -} - -body { - background-color: var(--bui-bg); -} - -:root { - --bui-font-regular: system-ui; - --bui-font-monospace: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace; - --bui-font-weight-regular: 400; - --bui-font-weight-bold: 600; - --bui-font-size-1: .625rem; - --bui-font-size-2: .75rem; - --bui-font-size-3: .875rem; - --bui-font-size-4: 1rem; - --bui-font-size-5: 1.25rem; - --bui-font-size-6: 1.5rem; - --bui-font-size-7: 2rem; - --bui-font-size-8: 3rem; - --bui-font-size-9: 4rem; - --bui-font-size-10: 5.75rem; - --bui-space: .25rem; - --bui-space-0_5: calc(var(--bui-space) * .5); - --bui-space-1: var(--bui-space); - --bui-space-1_5: calc(var(--bui-space) * 1.5); - --bui-space-2: calc(var(--bui-space) * 2); - --bui-space-3: calc(var(--bui-space) * 3); - --bui-space-4: calc(var(--bui-space) * 4); - --bui-space-5: calc(var(--bui-space) * 5); - --bui-space-6: calc(var(--bui-space) * 6); - --bui-space-7: calc(var(--bui-space) * 7); - --bui-space-8: calc(var(--bui-space) * 8); - --bui-space-9: calc(var(--bui-space) * 9); - --bui-space-10: calc(var(--bui-space) * 10); - --bui-space-11: calc(var(--bui-space) * 11); - --bui-space-12: calc(var(--bui-space) * 12); - --bui-space-13: calc(var(--bui-space) * 13); - --bui-space-14: calc(var(--bui-space) * 14); - --bui-radius-1: calc(.125rem); - --bui-radius-2: calc(.25rem); - --bui-radius-3: calc(.5rem); - --bui-radius-4: calc(.75rem); - --bui-radius-5: calc(1rem); - --bui-radius-6: calc(1.25rem); - --bui-radius-full: 9999px; - --bui-black: #000; - --bui-white: #fff; - --bui-gray-1: #f8f8f8; - --bui-gray-2: #ececec; - --bui-gray-3: #d9d9d9; - --bui-gray-4: #c1c1c1; - --bui-gray-5: #9e9e9e; - --bui-gray-6: #8c8c8c; - --bui-gray-7: #757575; - --bui-gray-8: #595959; - --bui-bg: var(--bui-gray-1); - --bui-bg-surface-1: var(--bui-white); - --bui-bg-surface-2: var(--bui-gray-2); - --bui-bg-solid: #1f5493; - --bui-bg-solid-hover: #163a66; - --bui-bg-solid-pressed: #0f2b4e; - --bui-bg-solid-disabled: #ebebeb; - --bui-bg-tint: transparent; - --bui-bg-tint-hover: #1f549366; - --bui-bg-tint-pressed: #1f549399; - --bui-bg-tint-disabled: #ebebeb; - --bui-bg-danger: #feebe7; - --bui-bg-warning: #fff2b2; - --bui-bg-success: #e6f6eb; - --bui-fg-primary: var(--bui-black); - --bui-fg-secondary: var(--bui-gray-7); - --bui-fg-link: #1f5493; - --bui-fg-link-hover: #1f2d5c; - --bui-fg-disabled: #9e9e9e; - --bui-fg-solid: var(--bui-white); - --bui-fg-solid-disabled: #9c9c9c; - --bui-fg-tint: #1f5493; - --bui-fg-tint-disabled: var(--bui-gray-5); - --bui-fg-danger: #e22b2b; - --bui-fg-warning: #e36d05; - --bui-fg-success: #1db954; - --bui-border: #0000001a; - --bui-border-hover: #0003; - --bui-border-pressed: #0006; - --bui-border-disabled: #0000001a; - --bui-border-danger: #f87a7a; - --bui-border-warning: #e36d05; - --bui-border-success: #53db83; - --bui-ring: #1f5493; - --bui-scrollbar: #a0a0a03b; - --bui-scrollbar-thumb: #a0a0a0; - --bui-animate-pulse: pulse 2s cubic-bezier(.4, 0, .6, 1) infinite; -} - -[data-theme-mode="dark"] { - --bui-gray-1: #191919; - --bui-gray-2: #242424; - --bui-gray-3: #373737; - --bui-gray-4: #464646; - --bui-gray-5: #575757; - --bui-gray-6: #7b7b7b; - --bui-gray-7: #9e9e9e; - --bui-gray-8: #b4b4b4; - --bui-bg: #333; - --bui-bg-surface-1: #424242; - --bui-bg-surface-2: var(--bui-gray-2); - --bui-bg-solid: #9cc9ff; - --bui-bg-solid-hover: #83b9fd; - --bui-bg-solid-pressed: #83b9fd; - --bui-bg-solid-disabled: #222; - --bui-bg-tint: transparent; - --bui-bg-tint-hover: #9cc9ff1f; - --bui-bg-tint-pressed: #9cc9ff29; - --bui-bg-tint-disabled: transparent; - --bui-bg-danger: #3b1219; - --bui-bg-warning: #302008; - --bui-bg-success: #132d21; - --bui-fg-primary: var(--bui-white); - --bui-fg-secondary: var(--bui-gray-7); - --bui-fg-link: #9cc9ff; - --bui-fg-link-hover: #7eb5f7; - --bui-fg-disabled: var(--bui-gray-7); - --bui-fg-solid: #101821; - --bui-fg-solid-disabled: var(--bui-gray-5); - --bui-fg-tint: #9cc9ff; - --bui-fg-tint-disabled: var(--bui-gray-5); - --bui-fg-danger: #e22b2b; - --bui-fg-warning: #e36d05; - --bui-fg-success: #1db954; - --bui-border: #ffffff1f; - --bui-border-hover: #fff6; - --bui-border-pressed: #ffffff80; - --bui-border-disabled: #fff3; - --bui-border-danger: #f87a7a; - --bui-border-warning: #e36d05; - --bui-border-success: #53db83; - --bui-ring: #1f5493; - --bui-scrollbar: #3636363a; - --bui-scrollbar-thumb: #575757; -} - -.bui-AvatarRoot { - vertical-align: middle; - user-select: none; - color: var(--bui-fg-primary); - background-color: var(--bui-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; -} - -.bui-AvatarRoot[data-size="small"] { - width: 1.5rem; - height: 1.5rem; -} - -.bui-AvatarRoot[data-size="medium"] { - width: 2rem; - height: 2rem; -} - -.bui-AvatarRoot[data-size="large"] { - width: 3rem; - height: 3rem; -} - -.bui-AvatarImage { - object-fit: cover; - width: 100%; - height: 100%; -} - -.bui-AvatarFallback { - width: 100%; - height: 100%; - font-size: var(--bui-font-size-3); - font-weight: var(--bui-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--bui-border); - border-radius: var(--bui-radius-full); - justify-content: center; - align-items: center; - display: flex; -} - -.bui-Box { - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); -} - -.bui-Button { - user-select: none; - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-bold); - cursor: pointer; - border-radius: var(--bui-radius-2); - justify-content: center; - align-items: center; - gap: var(--bui-space-1_5); - border: none; - flex-shrink: 0; - padding: 0; - display: inline-flex; - - &[data-disabled="true"] { - cursor: not-allowed; - } -} - -.bui-Button[data-variant="primary"] { - background-color: var(--bui-bg-solid); - color: var(--bui-fg-solid); - - &:hover { - background-color: var(--bui-bg-solid-hover); - transition: background-color .15s; - } - - &:active { - background-color: var(--bui-bg-solid-pressed); - } - - &:focus-visible { - outline: 2px solid var(--bui-ring); - outline-offset: 2px; - } - - &[data-disabled="true"] { - background-color: var(--bui-bg-solid-disabled); - color: var(--bui-fg-solid-disabled); - } -} - -.bui-Button[data-variant="secondary"] { - background-color: var(--bui-bg-surface-1); - box-shadow: inset 0 0 0 1px var(--bui-border); - color: var(--bui-fg-primary); - - &:hover { - box-shadow: inset 0 0 0 1px var(--bui-border-hover); - transition: box-shadow .15s; - } - - &:active { - box-shadow: inset 0 0 0 1px var(--bui-border-pressed); - } - - &:focus-visible { - box-shadow: inset 0 0 0 2px var(--bui-ring); - outline: none; - transition: none; - } - - &[data-disabled="true"] { - box-shadow: inset 0 0 0 1px var(--bui-border-disabled); - color: var(--bui-fg-disabled); - } -} - -.bui-Button[data-variant="tertiary"] { - color: var(--bui-fg-primary); - background-color: #0000; - - &:hover { - background-color: var(--bui-bg-surface-1); - transition: background-color .2s; - } - - &:active { - background-color: var(--bui-bg-surface-2); - } - - &:focus-visible { - box-shadow: inset 0 0 0 2px var(--bui-ring); - outline: none; - transition: none; - } - - &[data-disabled="true"] { - color: var(--bui-fg-disabled); - background-color: #0000; - } -} - -.bui-Button[data-size="medium"] { - font-size: var(--bui-font-size-4); - padding: 0 var(--bui-space-3); - height: 2.5rem; -} - -.bui-Button[data-size="small"] { - font-size: var(--bui-font-size-3); - padding: 0 var(--bui-space-2); - height: 2rem; -} - -.bui-Button[data-size="small"] svg { - width: 1rem; - height: 1rem; -} - -.bui-Button[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; -} - -.bui-ButtonIcon { - justify-content: center; - align-items: center; -} - -.bui-ButtonIcon[data-size="small"] { - width: 2rem; - padding: 0; -} - -.bui-ButtonIcon[data-size="medium"] { - width: 2.5rem; - padding: 0; -} - -.bui-Card { - gap: var(--bui-space-3); - background-color: var(--bui-bg-surface-1); - border-radius: var(--bui-radius-3); - padding-block: var(--bui-space-3); - color: var(--bui-fg-primary); - border: 1px solid var(--bui-border); - flex-direction: column; - width: 100%; - min-height: 0; - display: flex; - overflow: hidden; -} - -.bui-CardBody { - flex: 1; - min-height: 0; - overflow: auto; -} - -.bui-CardHeader, .bui-CardFooter { - padding-inline: var(--bui-space-3); -} - -.bui-CheckboxRoot { - width: 1rem; - height: 1rem; - box-shadow: inset 0 0 0 1px var(--bui-border); - cursor: pointer; - background-color: var(--bui-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; -} - -.bui-CheckboxRoot:focus-visible { - outline: 2px solid var(--bui-ring); - outline-offset: 2px; - transition: none; -} - -.bui-CheckboxRoot[data-checked] { - background-color: var(--bui-bg-solid); - box-shadow: none; - color: var(--bui-fg-solid); -} - -.bui-CheckboxLabel { - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - user-select: none; - flex-direction: row; - display: flex; - - &:hover { - & .bui-CheckboxRoot:not([data-checked]) { - box-shadow: inset 0 0 0 1px var(--bui-border-hover); + @keyframes pulse { + 50% { + opacity: .5; } } -} -.bui-CheckboxIndicator { - color: var(--bui-fg-solid); - justify-content: center; - align-items: center; - display: flex; -} - -.bui-CollapsiblePanel { - height: var(--collapsible-panel-height); - transition: all .15s ease-out; - display: flex; - overflow: hidden; - - &[data-starting-style], &[data-ending-style] { - height: 0; - } -} - -.bui-Container { - max-width: 120rem; - padding-inline: var(--bui-space-4); - margin-inline: auto; - transition: padding .2s ease-in-out; -} - -@media (width >= 640px) { - .bui-Container { - padding-inline: var(--bui-space-5); - } -} - -.bui-FieldError { - color: var(--bui-fg-danger); - font-size: var(--bui-font-size-2); - font-weight: var(--bui-font-weight-regular); - margin-top: var(--bui-space-2); - display: inline-block; -} - -.bui-FieldLabelWrapper { - margin-bottom: var(--bui-space-3); - gap: var(--bui-space-1); - flex-direction: column; - display: flex; -} - -.bui-FieldLabel { - color: var(--bui-fg-primary); - cursor: pointer; - font-weight: var(--bui-font-weight-regular); - font-size: var(--bui-font-size-2); - margin-right: auto; -} - -.bui-FieldSecondaryLabel { - color: var(--bui-fg-secondary); - font-weight: var(--bui-font-weight-regular); - margin-left: var(--bui-space-1); -} - -.bui-FieldDescription { - font-weight: var(--bui-font-weight-regular); - font-size: var(--bui-font-size-2); - color: var(--bui-fg-secondary); - margin: 0; -} - -.bui-Flex { - min-width: 0; - display: flex; -} - -.bui-Grid { - display: grid; -} - -.bui-HeaderToolbar { - margin-bottom: var(--bui-space-6); - - &:before { - content: ""; + body { background-color: var(--bui-bg); - z-index: 0; - height: 16px; - position: absolute; - top: 0; - left: 0; - right: 0; - } - - &[data-has-tabs="true"] { - margin-bottom: 0; } } -.bui-HeaderToolbarWrapper { - z-index: 1; - background-color: var(--bui-bg-surface-1); - padding-inline: var(--bui-space-5); - border-bottom: 1px solid var(--bui-border); - color: var(--bui-fg-primary); - flex-direction: row; - justify-content: space-between; - align-items: center; - height: 52px; - display: flex; - position: relative; -} +@layer components { + .bui-AvatarRoot { + vertical-align: middle; + user-select: none; + color: var(--bui-fg-primary); + background-color: var(--bui-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; + } -.bui-HeaderToolbarContent { - align-items: center; - gap: var(--bui-space-2); - flex-direction: row; - display: flex; -} + .bui-AvatarRoot[data-size="small"] { + width: 1.5rem; + height: 1.5rem; + } -.bui-HeaderToolbarName { - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-3); - font-weight: var(--bui-font-weight-regular); - flex-direction: row; - flex-shrink: 0; - display: flex; -} + .bui-AvatarRoot[data-size="medium"] { + width: 2rem; + height: 2rem; + } -.bui-HeaderToolbarIcon { - width: 16px; - height: 16px; - color: var(--bui-fg-primary); + .bui-AvatarRoot[data-size="large"] { + width: 3rem; + height: 3rem; + } - & svg { + .bui-AvatarImage { + object-fit: cover; width: 100%; height: 100%; } -} -.bui-HeaderToolbarControls { - right: var(--bui-space-5); - align-items: center; - gap: var(--bui-space-2); - flex-direction: row; - display: flex; - position: absolute; - top: 50%; - transform: translateY(-50%); -} - -.bui-HeaderTabsWrapper { - margin-bottom: var(--bui-space-4); - padding-inline: var(--bui-space-3); - border-bottom: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); -} - -.bui-HeaderPage { - gap: var(--bui-space-1); - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); - flex-direction: column; - display: flex; -} - -.bui-HeaderPageContent { - flex-direction: row; - justify-content: space-between; - display: flex; -} - -.bui-HeaderPageTabsWrapper { - margin-left: -8px; -} - -.bui-HeaderPageControls, .bui-HeaderPageBreadcrumbs { - align-items: center; - gap: var(--bui-space-2); - flex-direction: row; - display: flex; -} - -.bui-Icon { - width: 1rem; - height: 1rem; -} - -.bui-Link { - font-family: var(--bui-font-regular); - cursor: pointer; - margin: 0; - padding: 0; - text-decoration-line: none; - display: inline-block; - - &: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, currentColor 30%, transparent); - } -} - -.bui-MenuPopover { - border: 1px solid var(--bui-border); - border-radius: var(--bui-radius-2); - background: var(--bui-bg-surface-1); - color: var(--bui-fg-primary); - outline: none; - flex-direction: column; - min-height: 0; - transition: transform .2s, opacity .2s; - display: flex; - overflow: hidden; - - &[data-entering], &[data-exiting] { - transform: var(--origin); - opacity: 0; + .bui-AvatarFallback { + width: 100%; + height: 100%; + font-size: var(--bui-font-size-3); + font-weight: var(--bui-font-weight-regular); + box-shadow: inset 0 0 0 1px var(--bui-border); + border-radius: var(--bui-radius-full); + justify-content: center; + align-items: center; + display: flex; } - &[data-placement="top"] { - --origin: translateY(8px); - } - - &[data-placement="bottom"] { - --origin: translateY(-8px); - } - - &[data-placement="right"] { - --origin: translateX(-8px); - } - - &[data-placement="left"] { - --origin: translateX(8px); - } -} - -.bui-MenuContent { - max-height: inherit; - box-sizing: border-box; - padding: var(--bui-space-1); - outline: none; - min-width: 150px; - overflow: auto; -} - -.bui-MenuPopover .bui-ScrollAreaRoot { - flex-direction: column; - flex: 1; - height: 100%; - min-height: 0; - display: flex; -} - -.bui-MenuPopover .bui-ScrollAreaScrollbar { - margin-inline: var(--bui-space-1_5); -} - -.bui-MenuItem { - height: 2rem; - padding-inline: var(--bui-space-2); - border-radius: var(--bui-radius-2); - cursor: default; - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-3); - justify-content: space-between; - align-items: center; - gap: var(--bui-space-6); - outline: none; - display: flex; - - &[data-focused], &[data-open] { - background: var(--bui-bg-surface-2); + .bui-Box { + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); color: var(--bui-fg-primary); } - &[data-color="danger"] { + .bui-Button { + user-select: none; + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-bold); + cursor: pointer; + border-radius: var(--bui-radius-2); + justify-content: center; + align-items: center; + gap: var(--bui-space-1_5); + border: none; + flex-shrink: 0; + padding: 0; + display: inline-flex; + + &[data-disabled="true"] { + cursor: not-allowed; + } + } + + .bui-Button[data-variant="primary"] { + background-color: var(--bui-bg-solid); + color: var(--bui-fg-solid); + + &:hover { + background-color: var(--bui-bg-solid-hover); + transition: background-color .15s; + } + + &:active { + background-color: var(--bui-bg-solid-pressed); + } + + &:focus-visible { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } + + &[data-disabled="true"] { + background-color: var(--bui-bg-solid-disabled); + color: var(--bui-fg-solid-disabled); + } + } + + .bui-Button[data-variant="secondary"] { + background-color: var(--bui-bg-surface-1); + box-shadow: inset 0 0 0 1px var(--bui-border); + color: var(--bui-fg-primary); + + &:hover { + box-shadow: inset 0 0 0 1px var(--bui-border-hover); + transition: box-shadow .15s; + } + + &:active { + box-shadow: inset 0 0 0 1px var(--bui-border-pressed); + } + + &:focus-visible { + box-shadow: inset 0 0 0 2px var(--bui-ring); + outline: none; + transition: none; + } + + &[data-disabled="true"] { + box-shadow: inset 0 0 0 1px var(--bui-border-disabled); + color: var(--bui-fg-disabled); + } + } + + .bui-Button[data-variant="tertiary"] { + color: var(--bui-fg-primary); + background-color: #0000; + + &:hover { + background-color: var(--bui-bg-surface-1); + transition: background-color .2s; + } + + &:active { + background-color: var(--bui-bg-surface-2); + } + + &:focus-visible { + box-shadow: inset 0 0 0 2px var(--bui-ring); + outline: none; + transition: none; + } + + &[data-disabled="true"] { + color: var(--bui-fg-disabled); + background-color: #0000; + } + } + + .bui-Button[data-size="medium"] { + font-size: var(--bui-font-size-4); + padding: 0 var(--bui-space-3); + height: 2.5rem; + } + + .bui-Button[data-size="small"] { + font-size: var(--bui-font-size-3); + padding: 0 var(--bui-space-2); + height: 2rem; + } + + .bui-Button[data-size="small"] svg { + width: 1rem; + height: 1rem; + } + + .bui-Button[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; + } + + .bui-ButtonIcon { + justify-content: center; + align-items: center; + } + + .bui-ButtonIcon[data-size="small"] { + width: 2rem; + padding: 0; + } + + .bui-ButtonIcon[data-size="medium"] { + width: 2.5rem; + padding: 0; + } + + .bui-Card { + gap: var(--bui-space-3); + background-color: var(--bui-bg-surface-1); + border-radius: var(--bui-radius-3); + padding-block: var(--bui-space-3); + color: var(--bui-fg-primary); + border: 1px solid var(--bui-border); + flex-direction: column; + width: 100%; + min-height: 0; + display: flex; + overflow: hidden; + } + + .bui-CardBody { + flex: 1; + min-height: 0; + overflow: auto; + } + + .bui-CardHeader, .bui-CardFooter { + padding-inline: var(--bui-space-3); + } + + .bui-CheckboxRoot { + width: 1rem; + height: 1rem; + box-shadow: inset 0 0 0 1px var(--bui-border); + cursor: pointer; + background-color: var(--bui-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; + } + + .bui-CheckboxRoot:focus-visible { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + transition: none; + } + + .bui-CheckboxRoot[data-checked] { + background-color: var(--bui-bg-solid); + box-shadow: none; + color: var(--bui-fg-solid); + } + + .bui-CheckboxLabel { + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + user-select: none; + flex-direction: row; + display: flex; + + &:hover { + & .bui-CheckboxRoot:not([data-checked]) { + box-shadow: inset 0 0 0 1px var(--bui-border-hover); + } + } + } + + .bui-CheckboxIndicator { + color: var(--bui-fg-solid); + justify-content: center; + align-items: center; + display: flex; + } + + .bui-CollapsiblePanel { + height: var(--collapsible-panel-height); + transition: all .15s ease-out; + display: flex; + overflow: hidden; + + &[data-starting-style], &[data-ending-style] { + height: 0; + } + } + + .bui-Container { + max-width: 120rem; + padding-inline: var(--bui-space-4); + margin-inline: auto; + transition: padding .2s ease-in-out; + } + + @media (width >= 640px) { + .bui-Container { + padding-inline: var(--bui-space-5); + } + } + + .bui-FieldError { + color: var(--bui-fg-danger); + font-size: var(--bui-font-size-2); + font-weight: var(--bui-font-weight-regular); + margin-top: var(--bui-space-2); + display: inline-block; + } + + .bui-FieldLabelWrapper { + margin-bottom: var(--bui-space-3); + gap: var(--bui-space-1); + flex-direction: column; + display: flex; + } + + .bui-FieldLabel { + color: var(--bui-fg-primary); + cursor: pointer; + font-weight: var(--bui-font-weight-regular); + font-size: var(--bui-font-size-2); + margin-right: auto; + } + + .bui-FieldSecondaryLabel { + color: var(--bui-fg-secondary); + font-weight: var(--bui-font-weight-regular); + margin-left: var(--bui-space-1); + } + + .bui-FieldDescription { + font-weight: var(--bui-font-weight-regular); + font-size: var(--bui-font-size-2); + color: var(--bui-fg-secondary); + margin: 0; + } + + .bui-Flex { + min-width: 0; + display: flex; + } + + .bui-Grid { + display: grid; + } + + .bui-HeaderToolbar { + margin-bottom: var(--bui-space-6); + + &:before { + content: ""; + background-color: var(--bui-bg); + z-index: 0; + height: 16px; + position: absolute; + top: 0; + left: 0; + right: 0; + } + + &[data-has-tabs="true"] { + margin-bottom: 0; + } + } + + .bui-HeaderToolbarWrapper { + z-index: 1; + background-color: var(--bui-bg-surface-1); + padding-inline: var(--bui-space-5); + border-bottom: 1px solid var(--bui-border); + color: var(--bui-fg-primary); + flex-direction: row; + justify-content: space-between; + align-items: center; + height: 52px; + display: flex; + position: relative; + } + + .bui-HeaderToolbarContent { + align-items: center; + gap: var(--bui-space-2); + flex-direction: row; + display: flex; + } + + .bui-HeaderToolbarName { + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-3); + font-weight: var(--bui-font-weight-regular); + flex-direction: row; + flex-shrink: 0; + display: flex; + } + + .bui-HeaderToolbarIcon { + width: 16px; + height: 16px; + color: var(--bui-fg-primary); + + & svg { + width: 100%; + height: 100%; + } + } + + .bui-HeaderToolbarControls { + right: var(--bui-space-5); + align-items: center; + gap: var(--bui-space-2); + flex-direction: row; + display: flex; + position: absolute; + top: 50%; + transform: translateY(-50%); + } + + .bui-HeaderTabsWrapper { + margin-bottom: var(--bui-space-4); + padding-inline: var(--bui-space-3); + border-bottom: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + } + + .bui-HeaderPage { + gap: var(--bui-space-1); + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + flex-direction: column; + display: flex; + } + + .bui-HeaderPageContent { + flex-direction: row; + justify-content: space-between; + display: flex; + } + + .bui-HeaderPageTabsWrapper { + margin-left: -8px; + } + + .bui-HeaderPageControls, .bui-HeaderPageBreadcrumbs { + align-items: center; + gap: var(--bui-space-2); + flex-direction: row; + display: flex; + } + + .bui-Icon { + width: 1rem; + height: 1rem; + } + + .bui-Link { + font-family: var(--bui-font-regular); + cursor: pointer; + margin: 0; + padding: 0; + text-decoration-line: none; + display: inline-block; + + &: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, currentColor 30%, transparent); + } + } + + .bui-MenuPopover { + border: 1px solid var(--bui-border); + border-radius: var(--bui-radius-2); + background: var(--bui-bg-surface-1); + color: var(--bui-fg-primary); + outline: none; + flex-direction: column; + min-height: 0; + transition: transform .2s, opacity .2s; + display: flex; + overflow: hidden; + + &[data-entering], &[data-exiting] { + transform: var(--origin); + opacity: 0; + } + + &[data-placement="top"] { + --origin: translateY(8px); + } + + &[data-placement="bottom"] { + --origin: translateY(-8px); + } + + &[data-placement="right"] { + --origin: translateX(-8px); + } + + &[data-placement="left"] { + --origin: translateX(8px); + } + } + + .bui-MenuContent { + max-height: inherit; + box-sizing: border-box; + padding: var(--bui-space-1); + outline: none; + min-width: 150px; + overflow: auto; + } + + .bui-MenuPopover .bui-ScrollAreaRoot { + flex-direction: column; + flex: 1; + height: 100%; + min-height: 0; + display: flex; + } + + .bui-MenuPopover .bui-ScrollAreaScrollbar { + margin-inline: var(--bui-space-1_5); + } + + .bui-MenuItem { + height: 2rem; + padding-inline: var(--bui-space-2); + border-radius: var(--bui-radius-2); + cursor: default; + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-3); + justify-content: space-between; + align-items: center; + gap: var(--bui-space-6); + outline: none; + display: flex; + + &[data-focused], &[data-open] { + background: var(--bui-bg-surface-2); + color: var(--bui-fg-primary); + } + + &[data-color="danger"] { + color: var(--bui-fg-danger); + } + + &[data-color="danger"][data-focused] { + background: var(--bui-bg-danger); + color: var(--bui-fg-danger); + } + + &[data-has-submenu] { + & > .bui-MenuItemArrow { + display: block; + } + } + } + + .bui-MenuItemListBox { + height: 2rem; + padding-inline: var(--bui-space-2); + border-radius: var(--bui-radius-2); + cursor: default; + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-3); + justify-content: space-between; + align-items: center; + gap: var(--bui-space-6); + outline: none; + display: flex; + + &:hover { + background: var(--bui-bg-surface-2); + color: var(--bui-fg-primary); + } + + &[data-selected] .bui-MenuItemListBoxCheck { + & > svg { + opacity: 1; + color: var(--bui-fg-primary); + } + } + } + + .bui-MenuItemListBoxCheck { + justify-content: center; + align-items: center; + width: 1rem; + height: 1rem; + display: flex; + + & > svg { + opacity: 0; + width: 1rem; + height: 1rem; + } + } + + .bui-MenuItemContent { + align-items: center; + gap: var(--bui-space-2); + display: flex; + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuItemArrow { + width: 1rem; + height: 1rem; + display: none; + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuSection { + &:first-child .bui-MenuSectionHeader { + padding-top: 0; + } + } + + .bui-MenuSectionHeader { + height: 2rem; + padding-top: var(--bui-space-3); + padding-left: var(--bui-space-2); + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-1); + letter-spacing: .05rem; + text-transform: uppercase; + align-items: center; + font-weight: bold; + display: flex; + } + + .bui-MenuSeparator { + background: var(--bui-border); + height: 1px; + margin-inline: var(--bui-space-1_5); + margin-block: var(--bui-space-1); + } + + .bui-MenuSearchField { + font-family: var(--bui-font-regular); + flex-shrink: 0; + width: 100%; + position: relative; + + &[data-empty] { + & .bui-MenuSearchFieldClear { + display: none; + } + } + } + + .bui-MenuSearchFieldInput { + padding: 0 var(--bui-space-3); + border: none; + border-bottom: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + width: 100%; + height: 2rem; + cursor: inherit; + outline: none; + align-items: center; + display: flex; + + &::-webkit-search-cancel-button, &::-webkit-search-decoration { + -webkit-appearance: none; + } + } + + .bui-MenuSearchFieldClear { + right: var(--bui-space-2); + cursor: pointer; + color: var(--bui-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; + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuEmptyState { + padding: var(--bui-space-1); + color: var(--bui-fg-secondary); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + } + + .bui-Popover { + background-color: var(--bui-bg-surface-1); + border: 1px solid var(--bui-border); + border-radius: var(--bui-radius-3); + padding-block: var(--bui-space-1); + margin-right: 12px; + overflow: scroll; + box-shadow: 0 4px 12px #0000001a; + } + + .bui-RadioGroup { + color: var(--bui-fg-primary); + flex-direction: column; + display: flex; + } + + .bui-RadioGroup[data-orientation="horizontal"] .bui-RadioGroupContent { + gap: var(--bui-space-4); + flex-direction: row; + } + + .bui-RadioGroupContent { + gap: var(--bui-space-2); + flex-direction: column; + display: flex; + } + + .bui-Radio { + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-2); + color: var(--bui-fg-primary); + forced-color-adjust: none; + display: flex; + position: relative; + + &:before { + content: ""; + box-sizing: border-box; + border: .125rem solid var(--bui-border); + background: var(--bui-gray-1); + border-radius: var(--bui-radius-full); + width: 1rem; + height: 1rem; + transition: all .2s; + display: block; + } + + &[data-pressed]:before { + border-color: var(--bui-border); + } + + &[data-selected] { + &:before { + border-color: var(--bui-bg-solid); + border-width: .25rem; + } + + &[data-pressed]:before { + border-color: var(--bui-bg-solid); + } + } + + &[data-focus-visible]:before { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } + + &[data-disabled] { + cursor: not-allowed; + color: var(--bui-fg-disabled); + + &:before { + border-color: var(--bui-border-disabled); + background: var(--bui-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--bui-border-disabled); + } + } + + &[data-invalid]:before, &[data-invalid][data-selected]:before { + border-color: var(--bui-border-danger); + } + + &[data-disabled][data-invalid] { + color: var(--bui-fg-disabled); + + &:before { + border-color: var(--bui-border-disabled); + background: var(--bui-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--bui-border-disabled); + } + } + } + + .bui-Table { + caption-side: bottom; + border-collapse: collapse; + width: 100%; + } + + .bui-TableHeader { + border-bottom: 1px solid var(--bui-border); + transition: color .2s ease-in-out; + } + + .bui-TableHead { + text-align: left; + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + color: var(--bui-fg-primary); + } + + .bui-TableHeadSortButton { + cursor: pointer; + user-select: none; + align-items: center; + gap: var(--bui-space-1); + display: inline-flex; + + &:hover svg { + opacity: .5; + } + + & svg { + opacity: 0; + transition: opacity .1s ease-in-out, transform .1s ease-in-out; + } + + &[data-sort-order="asc"] svg { + opacity: 1; + transform: rotate(0); + } + + &[data-sort-order="desc"] svg { + opacity: 1; + transform: rotate(180deg); + } + } + + .bui-TableBody { + color: var(--bui-fg-primary); + } + + .bui-TableRow { + border-bottom: 1px solid var(--bui-border); + transition: color .2s ease-in-out; + + &[data-react-aria-pressable="true"] { + cursor: pointer; + } + } + + .bui-TableBody .bui-TableRow:hover { + background-color: var(--bui-gray-2); + } + + .bui-TableCell { + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + } + + .bui-TableCellContentWrapper { + align-items: center; + gap: var(--bui-space-2); + flex-direction: row; + display: inline-flex; + } + + .bui-TableCellIcon, .bui-TableCellIcon svg { + color: var(--bui-fg-primary); + align-items: center; + display: inline-flex; + } + + .bui-TableCellContent { + gap: var(--bui-space-0_5); + flex-direction: column; + display: flex; + } + + .bui-TableCellProfile { + gap: var(--bui-space-2); + flex-direction: row; + align-items: center; + display: flex; + } + + .bui-TableCellProfileAvatar { + vertical-align: middle; + user-select: none; + color: var(--bui-fg-primary); + background-color: var(--bui-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; + } + + .bui-TableCellProfileAvatarImage { + object-fit: cover; + width: 100%; + height: 100%; + } + + .bui-TableCellProfileAvatarFallback { + width: 100%; + height: 100%; + font-size: var(--bui-font-size-2); + font-weight: var(--bui-font-weight-regular); + box-shadow: inset 0 0 0 1px var(--bui-border); + border-radius: var(--bui-radius-full); + justify-content: center; + align-items: center; + display: flex; + } + + .bui-DataTablePagination { + padding-top: var(--bui-space-5); + justify-content: space-between; + align-items: center; + display: flex; + } + + .bui-DataTablePagination--left { + justify-content: space-between; + align-items: center; + display: flex; + } + + .bui-DataTablePagination--right { + justify-content: space-between; + align-items: center; + gap: var(--bui-space-2); + display: flex; + } + + .bui-DataTablePagination--select { + min-width: 10.5rem; + } + + .bui-Tabs { + --active-tab-left: 0px; + --active-tab-right: 0px; + --active-tab-top: 0px; + --active-tab-bottom: 0px; + --active-tab-width: 0px; + --active-tab-height: 0px; + --active-transition-duration: 0s; + --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; + } + + .bui-TabList { + flex-direction: row; + display: flex; + } + + .bui-TabListWrapper { + position: relative; + } + + .bui-Tab { + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-secondary); + cursor: pointer; + z-index: 2; + height: 36px; + padding-inline: var(--bui-space-2); + justify-content: center; + align-items: center; + display: flex; + position: relative; + + &[data-selected="true"] { + color: var(--bui-fg-primary); + } + } + + .bui-TabActive { + content: ""; + left: calc(var(--active-tab-left) + var(--bui-space-2)); + width: calc(var(--active-tab-width) - var(--bui-space-4)); + background-color: var(--bui-fg-primary); + height: 1px; + transition: left var(--active-transition-duration) ease-out, opacity .15s ease-out, width var(--active-transition-duration) ease-out; + opacity: 1; + border-radius: 4px; + position: absolute; + bottom: -1px; + } + + .bui-TabHovered { + 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(--bui-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; + } + + .bui-TabPanel { + padding-inline: var(--bui-space-2); + padding-top: var(--bui-space-4); + } + + .bui-TagList { + gap: var(--bui-space-2); + flex-wrap: wrap; + display: flex; + } + + .bui-Tag { + color: var(--bui-fg-primary); + background-color: var(--bui-gray-2); + border-radius: var(--bui-radius-2); + font-weight: var(--bui-font-weight-regular); + justify-content: center; + align-items: center; + gap: var(--bui-space-1); + box-sizing: border-box; + transition-property: background-color, box-shadow, color; + transition-duration: .2s; + transition-timing-function: ease-in-out; + display: flex; + } + + .bui-Tag[data-size="small"] { + height: 26px; + padding: 0 var(--bui-space-2); + font-size: var(--bui-font-size-1); + } + + .bui-Tag[data-size="medium"] { + height: 32px; + padding: 0 var(--bui-space-2); + font-size: var(--bui-font-size-2); + } + + .bui-Tag[data-hovered] { + background-color: var(--bui-gray-3); + cursor: pointer; + } + + .bui-Tag[data-focus-visible] { + outline: 2px solid var(--bui-ring); + outline-offset: 1px; + } + + .bui-Tag[data-selected] { + box-shadow: inset 0 0 0 1px var(--bui-gray-8); + } + + .bui-Tag[data-disabled] { + color: var(--bui-fg-disabled); + cursor: not-allowed; + } + + .bui-TagRemoveButton { + cursor: pointer; + color: var(--bui-fg-primary); + background-color: #0000; + border: none; + width: 1rem; + height: 1rem; + margin: 0; + padding: 0; + } + + .bui-TagIcon { + justify-content: center; + align-items: center; + transition: color .2s ease-in-out; + display: flex; + + & svg { + width: 1rem; + height: 1rem; + } + } + + .bui-Text { + font-family: var(--bui-font-regular); + margin: 0; + padding: 0; + } + + .bui-Text[data-variant="title-large"] { + font-size: var(--bui-font-size-8); + line-height: 140%; + } + + .bui-Text[data-variant="title-medium"] { + font-size: var(--bui-font-size-7); + line-height: 140%; + } + + .bui-Text[data-variant="title-small"] { + font-size: var(--bui-font-size-6); + line-height: 140%; + } + + .bui-Text[data-variant="title-x-small"] { + font-size: var(--bui-font-size-5); + line-height: 140%; + } + + .bui-Text[data-variant="body-large"] { + font-size: var(--bui-font-size-4); + line-height: 140%; + } + + .bui-Text[data-variant="body-medium"] { + font-size: var(--bui-font-size-3); + line-height: 140%; + } + + .bui-Text[data-variant="body-small"] { + font-size: var(--bui-font-size-2); + line-height: 140%; + } + + .bui-Text[data-variant="body-x-small"] { + font-size: var(--bui-font-size-1); + line-height: 140%; + } + + .bui-Text[data-weight="regular"] { + font-weight: var(--bui-font-weight-regular); + } + + .bui-Text[data-weight="bold"] { + font-weight: var(--bui-font-weight-bold); + } + + .bui-Text[data-color="primary"] { + color: var(--bui-fg-primary); + } + + .bui-Text[data-color="secondary"] { + color: var(--bui-fg-secondary); + } + + .bui-Text[data-color="danger"] { color: var(--bui-fg-danger); } - &[data-color="danger"][data-focused] { - background: var(--bui-bg-danger); - color: var(--bui-fg-danger); + .bui-Text[data-color="warning"] { + color: var(--bui-fg-warning); } - &[data-has-submenu] { - & > .bui-MenuItemArrow { + .bui-Text[data-color="success"] { + color: var(--bui-fg-success); + } + + .bui-Text[data-truncate] { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + + .bui-Text[data-as="span"], .bui-Text[data-as="label"], .bui-Text[data-as="strong"], .bui-Text[data-as="em"], .bui-Text[data-as="small"] { + display: inline-block; + } + + .bui-TextField { + font-family: var(--bui-font-regular); + flex-direction: column; + flex-shrink: 0; + width: 100%; + display: flex; + } + + .bui-InputWrapper { + position: relative; + + &[data-size="small"] .bui-Input { + height: 2rem; + } + + &[data-size="medium"] .bui-Input { + height: 2.5rem; + } + + &[data-size="small"] .bui-Input[data-icon] { + padding-left: var(--bui-space-8); + } + + &[data-size="medium"] .bui-Input[data-icon] { + padding-left: var(--bui-space-9); + } + } + + .bui-InputIcon { + left: var(--bui-space-3); + margin-right: var(--bui-space-1); + color: var(--bui-fg-primary); + pointer-events: none; + flex-shrink: 0; + transition: left .2s ease-in-out; + 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; + } + } + + .bui-Input { + padding: 0 var(--bui-space-3); + border-radius: var(--bui-radius-2); + border: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-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(--bui-fg-secondary); + } + + &[data-focused] { + outline-color: var(--bui-border-pressed); + outline-width: 0; + } + + &[data-hovered] { + border-color: var(--bui-border-hover); + } + + &[data-focused] { + border-color: var(--bui-border-pressed); + outline-width: 0; + } + + &[data-invalid] { + border-color: var(--bui-fg-danger); + } + + &[data-disabled] { + opacity: .5; + cursor: not-allowed; + border: 1px solid var(--bui-border-disabled); + } + } + + .bui-PasswordField { + font-family: var(--bui-font-regular); + --bui-passwordmanager-icon-width: var(--bui-space-1); + flex-direction: column; + flex-shrink: 0; + width: 100%; + display: flex; + } + + .bui-InputVisibility { + right: var(--bui-passwordmanager-icon-width); + cursor: pointer; + color: var(--bui-fg-primary); + background-color: #0000; + border: none; + justify-content: center; + align-items: center; + margin: 0; + padding: 0; + display: flex; + position: absolute; + top: 0; + bottom: 0; + + &[data-size="small"] { + width: 2rem; + height: 2rem; + } + + &[data-size="small"] svg { + width: 1rem; + height: 1rem; + } + + &[data-size="medium"] { + width: 2.5rem; + height: 2.5rem; + } + + &[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; + } + } + + .bui-PasswordField .bui-InputWrapper[data-size="small"] .bui-Input { + padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); + } + + .bui-PasswordField .bui-InputWrapper[data-size="medium"] .bui-Input { + padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); + } + + .bui-SearchField { + flex: 1 0; + + &[data-empty] { + & .bui-InputClear { + display: none; + } + } + + &[data-start-collapsed="true"] { + flex: 0 auto; + padding: 0; + transition: flex-basis .3s ease-in-out; + + &[data-collapsed="true"] { + flex-basis: 200px; + } + + &[data-collapsed="false"] { + cursor: pointer; + + &[data-size="medium"] { + flex-basis: 2.5rem; + height: 2.5rem; + } + + &[data-size="small"] { + flex-basis: 2rem; + height: 2rem; + } + + &[data-size="medium"] .bui-Input { + &::placeholder { + opacity: 0; + } + } + + &[data-size="small"] .bui-Input { + &::placeholder { + opacity: 0; + } + } + + & .bui-InputWrapper { + & .bui-Input[data-icon] { + padding-right: 0; + } + } + } + } + } + + .bui-SearchField .bui-Input { + transition: padding .3s ease-in-out, border-color .2s ease-in-out, outline-color .2s ease-in-out; + + &[data-hovered] { + border-color: var(--bui-border-hover); + } + + &[data-focused] { + border-color: var(--bui-border-pressed); + outline-width: 0; + } + } + + .bui-SearchField .bui-InputWrapper { + & .bui-Input[data-icon] { + padding-right: var(--bui-space-6); + } + } + + .bui-SearchField .bui-InputIcon { + justify-content: center; + display: flex; + left: 0; + + &[data-size="small"] { + width: var(--bui-space-8); + } + + &[data-size="medium"] { + width: var(--bui-space-10); + } + } + + .bui-InputClear { + cursor: pointer; + color: var(--bui-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; + } + + .bui-InputClear:hover { + color: var(--bui-fg-primary); + } + + .bui-InputClear[data-size="small"] { + width: 2rem; + height: 2rem; + } + + .bui-InputClear[data-size="medium"] { + width: 2.5rem; + height: 2.5rem; + } + + .bui-InputClear svg { + width: 1rem; + height: 1rem; + } + + .bui-Skeleton { + animation: var(--bui-animate-pulse); + background-color: var(--bui-bg-surface-2); + border-radius: var(--bui-radius-2); + } + + .bui-Skeleton[data-rounded="true"] { + border-radius: var(--bui-radius-full); + } + + .bui-Tooltip { + background: var(--bui-bg-surface-1); + border: 1px solid var(--bui-gray-3); + forced-color-adjust: none; + padding: var(--bui-space-2) var(--bui-space-3); + max-width: 240px; + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + color: var(--bui-fg-primary); + border-radius: 4px; + outline: none; + transition: transform .2s, opacity .2s; + transform: translate3d(0, 0, 0); + box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a; + + &[data-entering], &[data-exiting] { + transform: var(--origin); + opacity: 0; + } + + --tooltip-offset: var(--bui-space-3); + + &[data-placement="top"] { + margin-bottom: var(--tooltip-offset); + --origin: translateY(4px); + } + + &[data-placement="right"] { + margin-left: var(--tooltip-offset); + --origin: translateX(-4px); + } + + &[data-placement="bottom"] { + margin-top: var(--tooltip-offset); + --origin: translateY(-4px); + } + + &[data-placement="left"] { + margin-right: var(--tooltip-offset); + --origin: translateX(4px); + } + } + + .bui-TooltipArrow { + & svg { + display: block; + + & path:first-child { + fill: var(--bui-bg-surface-1); + } + + & path:nth-child(2) { + fill: var(--bui-gray-3); + } + + --tooltip-arrow-overlap: -2px; + } + + &[data-placement="top"] svg { + margin-top: var(--tooltip-arrow-overlap); + } + + &[data-placement="bottom"] svg { + margin-bottom: var(--tooltip-arrow-overlap); + transform: rotate(180deg); + } + + &[data-placement="right"] svg { + margin-right: var(--tooltip-arrow-overlap); + transform: rotate(90deg); + } + + &[data-placement="left"] svg { + margin-left: var(--tooltip-arrow-overlap); + transform: rotate(-90deg); + } + } + + [data-theme="dark"] { + & .bui-Tooltip { + background: var(--bui-bg-surface-2); + box-shadow: none; + border: 1px solid var(--bui-gray-4); + } + + & .bui-TooltipArrow { + & svg path:first-child { + fill: var(--bui-bg-surface-2); + } + + & svg path:nth-child(2) { + fill: var(--bui-gray-4); + } + } + } + + .bui-ScrollAreaRoot { + box-sizing: border-box; + width: 100%; + } + + .bui-ScrollAreaViewport { + overscroll-behavior: contain; + height: 100%; + } + + .bui-ScrollAreaContent { + padding-block: .75rem; + flex-direction: column; + gap: 1rem; + padding-left: 1rem; + padding-right: 1.5rem; + display: flex; + } + + .bui-ScrollAreaScrollbar { + background-color: var(--bui-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; + } + } + + .bui-ScrollAreaThumb { + border-radius: inherit; + background-color: var(--bui-scrollbar-thumb); + width: 100%; + } + + .bui-Select[data-invalid] { + & .bui-SelectTrigger { + border-color: var(--bui-fg-danger); + } + } + + .bui-SelectTrigger { + box-sizing: border-box; + border-radius: var(--bui-radius-3); + border: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + cursor: pointer; + justify-content: space-between; + align-items: center; + gap: var(--bui-space-2); + width: 100%; + display: flex; + + & svg { + color: var(--bui-fg-secondary); + flex-shrink: 0; + } + + &[data-size="small"] { + height: 2rem; + padding-inline: var(--bui-space-3); + } + + &[data-size="medium"] { + height: 3rem; + padding-inline: var(--bui-space-4); + } + + &[data-size="small"] svg { + width: 1rem; + height: 1rem; + } + + &[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; + } + + &::placeholder { + color: var(--bui-fg-secondary); + } + + &:hover { + border-color: var(--bui-border-hover); + transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; + } + + &:focus-visible { + border-color: var(--bui-border-pressed); + outline: 0; + } + + &[data-invalid] { + border-color: var(--bui-fg-danger); + } + + &[data-invalid]:hover, &[data-invalid]:focus-visible { + border-width: 2px; + } + + &[disabled] { + cursor: not-allowed; + border-color: var(--bui-border-disabled); + color: var(--bui-fg-disabled); + } + + &[disabled] .bui-SelectValue { + color: var(--bui-fg-disabled); + } + + &[data-popup-open] .bui-SelectIcon { + transform: rotate(180deg); + } + } + + .bui-SelectValue { + text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + text-align: left; + overflow: hidden; + + & .bui-SelectItemIndicator { + display: none; + } + + &[disabled] { + color: var(--bui-fg-disabled); + } + } + + .bui-SelectItem { + width: var(--anchor-width); + padding-block: var(--bui-space-2); + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-4); + color: var(--bui-fg-primary); + border-radius: var(--bui-radius-3); + cursor: pointer; + user-select: none; + font-size: var(--bui-font-size-3); + align-items: center; + gap: var(--bui-space-1); + outline: none; + grid-template-columns: 1rem 1fr; + grid-template-areas: "icon text"; + display: grid; + position: relative; + + &[data-focused] { + z-index: 0; + color: var(--bui-fg-primary); + position: relative; + } + + &[data-focused]:before { + content: ""; + z-index: -1; + background-color: var(--bui-bg-tint-hover); + border-radius: .25rem; + position: absolute; + inset-block: 0; + inset-inline: .25rem; + } + + &[data-disabled] { + cursor: not-allowed; + color: var(--bui-fg-disabled); + } + + &[data-selected] .bui-SelectItemIndicator { + opacity: 1; + } + } + + .bui-SelectItemIndicator { + opacity: 0; + grid-area: icon; + justify-content: center; + align-items: center; + transition: opacity .2s ease-in-out; + display: flex; + } + + .bui-SelectItemLabel { + flex: 1; + grid-area: text; + } + + .bui-Switch { + align-items: center; + gap: var(--bui-space-3); + font-size: var(--bui-font-size-3); + color: var(--bui-fg-primary); + cursor: pointer; + display: flex; + position: relative; + + &[data-pressed] .bui-SwitchIndicator { + &:before { + background: var(--bui-fg-solid); + } + } + + &[data-selected] { + & .bui-SwitchIndicator { + background: var(--bui-bg-solid); + + &:before { + background: var(--bui-fg-solid); + transform: translateX(100%); + } + } + + &[data-pressed] { + & .indicator { + background: var(--bui-gray-3); + } + } + } + + &[data-focus-visible] .bui-SwitchIndicator { + outline-offset: 2px; + outline: 2px solid; + } + } + + .bui-SwitchIndicator { + background: var(--bui-gray-3); + border: 2px; + border-radius: 1.143rem; + width: 2rem; + height: 1.143rem; + transition: all .2s; + + &:before { + content: ""; + background: var(--bui-fg-solid); + border-radius: 16px; + width: .857rem; + height: .857rem; + margin: .143rem; + transition: all .2s; display: block; } } } -.bui-MenuItemListBox { - height: 2rem; - padding-inline: var(--bui-space-2); - border-radius: var(--bui-radius-2); - cursor: default; - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-3); - justify-content: space-between; - align-items: center; - gap: var(--bui-space-6); - outline: none; - display: flex; - - &:hover { - background: var(--bui-bg-surface-2); - color: var(--bui-fg-primary); +@layer utilities { + .bui-p { + padding: var(--p); } - &[data-selected] .bui-MenuItemListBoxCheck { - & > svg { - opacity: 1; - color: var(--bui-fg-primary); - } - } -} - -.bui-MenuItemListBoxCheck { - justify-content: center; - align-items: center; - width: 1rem; - height: 1rem; - display: flex; - - & > svg { - opacity: 0; - width: 1rem; - height: 1rem; - } -} - -.bui-MenuItemContent { - align-items: center; - gap: var(--bui-space-2); - display: flex; - - & > svg { - width: 1rem; - height: 1rem; - } -} - -.bui-MenuItemArrow { - width: 1rem; - height: 1rem; - display: none; - - & > svg { - width: 1rem; - height: 1rem; - } -} - -.bui-MenuSection { - &:first-child .bui-MenuSectionHeader { - padding-top: 0; - } -} - -.bui-MenuSectionHeader { - height: 2rem; - padding-top: var(--bui-space-3); - padding-left: var(--bui-space-2); - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-1); - letter-spacing: .05rem; - text-transform: uppercase; - align-items: center; - font-weight: bold; - display: flex; -} - -.bui-MenuSeparator { - background: var(--bui-border); - height: 1px; - margin-inline: var(--bui-space-1_5); - margin-block: var(--bui-space-1); -} - -.bui-MenuSearchField { - font-family: var(--bui-font-regular); - flex-shrink: 0; - width: 100%; - position: relative; - - &[data-empty] { - & .bui-MenuSearchFieldClear { - display: none; - } - } -} - -.bui-MenuSearchFieldInput { - padding: 0 var(--bui-space-3); - border: none; - border-bottom: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - width: 100%; - height: 2rem; - cursor: inherit; - outline: none; - align-items: center; - display: flex; - - &::-webkit-search-cancel-button, &::-webkit-search-decoration { - -webkit-appearance: none; - } -} - -.bui-MenuSearchFieldClear { - right: var(--bui-space-2); - cursor: pointer; - color: var(--bui-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; - - & > svg { - width: 1rem; - height: 1rem; - } -} - -.bui-MenuEmptyState { - padding: var(--bui-space-1); - color: var(--bui-fg-secondary); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); -} - -.bui-Popover { - background-color: var(--bui-bg-surface-1); - border: 1px solid var(--bui-border); - border-radius: var(--bui-radius-3); - padding-block: var(--bui-space-1); - margin-right: 12px; - overflow: scroll; - box-shadow: 0 4px 12px #0000001a; -} - -.bui-RadioGroup { - color: var(--bui-fg-primary); - flex-direction: column; - display: flex; -} - -.bui-RadioGroup[data-orientation="horizontal"] .bui-RadioGroupContent { - gap: var(--bui-space-4); - flex-direction: row; -} - -.bui-RadioGroupContent { - gap: var(--bui-space-2); - flex-direction: column; - display: flex; -} - -.bui-Radio { - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-2); - color: var(--bui-fg-primary); - forced-color-adjust: none; - display: flex; - position: relative; - - &:before { - content: ""; - box-sizing: border-box; - border: .125rem solid var(--bui-border); - background: var(--bui-gray-1); - border-radius: var(--bui-radius-full); - width: 1rem; - height: 1rem; - transition: all .2s; - display: block; + .bui-p-0\.5 { + padding: var(--bui-space-0_5); } - &[data-pressed]:before { - border-color: var(--bui-border); + .bui-p-1 { + padding: var(--bui-space-1); } - &[data-selected] { - &:before { - border-color: var(--bui-bg-solid); - border-width: .25rem; + .bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .bui-p-2 { + padding: var(--bui-space-2); + } + + .bui-p-3 { + padding: var(--bui-space-3); + } + + .bui-p-4 { + padding: var(--bui-space-4); + } + + .bui-p-5 { + padding: var(--bui-space-5); + } + + .bui-p-6 { + padding: var(--bui-space-6); + } + + .bui-p-7 { + padding: var(--bui-space-7); + } + + .bui-p-8 { + padding: var(--bui-space-8); + } + + .bui-p-9 { + padding: var(--bui-space-9); + } + + .bui-p-10 { + padding: var(--bui-space-10); + } + + .bui-p-11 { + padding: var(--bui-space-11); + } + + .bui-p-12 { + padding: var(--bui-space-12); + } + + .bui-p-13 { + padding: var(--bui-space-13); + } + + .bui-p-14 { + padding: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-p { + padding: var(--p-xs); } - &[data-pressed]:before { - border-color: var(--bui-bg-solid); + .xs\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } + + .xs\:bui-p-1 { + padding: var(--bui-space-1); + } + + .xs\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .xs\:bui-p-2 { + padding: var(--bui-space-2); + } + + .xs\:bui-p-3 { + padding: var(--bui-space-3); + } + + .xs\:bui-p-4 { + padding: var(--bui-space-4); + } + + .xs\:bui-p-5 { + padding: var(--bui-space-5); + } + + .xs\:bui-p-6 { + padding: var(--bui-space-6); + } + + .xs\:bui-p-7 { + padding: var(--bui-space-7); + } + + .xs\:bui-p-8 { + padding: var(--bui-space-8); + } + + .xs\:bui-p-9 { + padding: var(--bui-space-9); + } + + .xs\:bui-p-10 { + padding: var(--bui-space-10); + } + + .xs\:bui-p-11 { + padding: var(--bui-space-11); + } + + .xs\:bui-p-12 { + padding: var(--bui-space-12); + } + + .xs\:bui-p-13 { + padding: var(--bui-space-13); + } + + .xs\:bui-p-14 { + padding: var(--bui-space-14); } } - &[data-focus-visible]:before { - outline: 2px solid var(--bui-ring); - outline-offset: 2px; - } - - &[data-disabled] { - cursor: not-allowed; - color: var(--bui-fg-disabled); - - &:before { - border-color: var(--bui-border-disabled); - background: var(--bui-bg-disabled); + @media (width >= 768px) { + .sm\:bui-p { + padding: var(--p-sm); } - &[data-selected]:before { - border-color: var(--bui-border-disabled); + .sm\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } + + .sm\:bui-p-1 { + padding: var(--bui-space-1); + } + + .sm\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .sm\:bui-p-2 { + padding: var(--bui-space-2); + } + + .sm\:bui-p-3 { + padding: var(--bui-space-3); + } + + .sm\:bui-p-4 { + padding: var(--bui-space-4); + } + + .sm\:bui-p-5 { + padding: var(--bui-space-5); + } + + .sm\:bui-p-6 { + padding: var(--bui-space-6); + } + + .sm\:bui-p-7 { + padding: var(--bui-space-7); + } + + .sm\:bui-p-8 { + padding: var(--bui-space-8); + } + + .sm\:bui-p-9 { + padding: var(--bui-space-9); + } + + .sm\:bui-p-10 { + padding: var(--bui-space-10); + } + + .sm\:bui-p-11 { + padding: var(--bui-space-11); + } + + .sm\:bui-p-12 { + padding: var(--bui-space-12); + } + + .sm\:bui-p-13 { + padding: var(--bui-space-13); + } + + .sm\:bui-p-14 { + padding: var(--bui-space-14); } } - &[data-invalid]:before, &[data-invalid][data-selected]:before { - border-color: var(--bui-border-danger); - } - - &[data-disabled][data-invalid] { - color: var(--bui-fg-disabled); - - &:before { - border-color: var(--bui-border-disabled); - background: var(--bui-bg-disabled); + @media (width >= 1024px) { + .md\:bui-p { + padding: var(--p-md); } - &[data-selected]:before { - border-color: var(--bui-border-disabled); + .md\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } + + .md\:bui-p-1 { + padding: var(--bui-space-1); + } + + .md\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .md\:bui-p-2 { + padding: var(--bui-space-2); + } + + .md\:bui-p-3 { + padding: var(--bui-space-3); + } + + .md\:bui-p-4 { + padding: var(--bui-space-4); + } + + .md\:bui-p-5 { + padding: var(--bui-space-5); + } + + .md\:bui-p-6 { + padding: var(--bui-space-6); + } + + .md\:bui-p-7 { + padding: var(--bui-space-7); + } + + .md\:bui-p-8 { + padding: var(--bui-space-8); + } + + .md\:bui-p-9 { + padding: var(--bui-space-9); + } + + .md\:bui-p-10 { + padding: var(--bui-space-10); + } + + .md\:bui-p-11 { + padding: var(--bui-space-11); + } + + .md\:bui-p-12 { + padding: var(--bui-space-12); + } + + .md\:bui-p-13 { + padding: var(--bui-space-13); + } + + .md\:bui-p-14 { + padding: var(--bui-space-14); } } -} -.bui-Table { - caption-side: bottom; - border-collapse: collapse; - width: 100%; -} + @media (width >= 1280px) { + .lg\:bui-p { + padding: var(--p-lg); + } -.bui-TableHeader { - border-bottom: 1px solid var(--bui-border); - transition: color .2s ease-in-out; -} + .lg\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } -.bui-TableHead { - text-align: left; - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); - color: var(--bui-fg-primary); -} + .lg\:bui-p-1 { + padding: var(--bui-space-1); + } -.bui-TableHeadSortButton { - cursor: pointer; - user-select: none; - align-items: center; - gap: var(--bui-space-1); - display: inline-flex; + .lg\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } - &:hover svg { - opacity: .5; + .lg\:bui-p-2 { + padding: var(--bui-space-2); + } + + .lg\:bui-p-3 { + padding: var(--bui-space-3); + } + + .lg\:bui-p-4 { + padding: var(--bui-space-4); + } + + .lg\:bui-p-5 { + padding: var(--bui-space-5); + } + + .lg\:bui-p-6 { + padding: var(--bui-space-6); + } + + .lg\:bui-p-7 { + padding: var(--bui-space-7); + } + + .lg\:bui-p-8 { + padding: var(--bui-space-8); + } + + .lg\:bui-p-9 { + padding: var(--bui-space-9); + } + + .lg\:bui-p-10 { + padding: var(--bui-space-10); + } + + .lg\:bui-p-11 { + padding: var(--bui-space-11); + } + + .lg\:bui-p-12 { + padding: var(--bui-space-12); + } + + .lg\:bui-p-13 { + padding: var(--bui-space-13); + } + + .lg\:bui-p-14 { + padding: var(--bui-space-14); + } } - & svg { - opacity: 0; - transition: opacity .1s ease-in-out, transform .1s ease-in-out; + @media (width >= 1536px) { + .xl\:bui-p { + padding: var(--p-xl); + } + + .xl\:bui-p-0\.5 { + padding: var(--bui-space-0_5); + } + + .xl\:bui-p-1 { + padding: var(--bui-space-1); + } + + .xl\:bui-p-1\.5 { + padding: var(--bui-space-1_5); + } + + .xl\:bui-p-2 { + padding: var(--bui-space-2); + } + + .xl\:bui-p-3 { + padding: var(--bui-space-3); + } + + .xl\:bui-p-4 { + padding: var(--bui-space-4); + } + + .xl\:bui-p-5 { + padding: var(--bui-space-5); + } + + .xl\:bui-p-6 { + padding: var(--bui-space-6); + } + + .xl\:bui-p-7 { + padding: var(--bui-space-7); + } + + .xl\:bui-p-8 { + padding: var(--bui-space-8); + } + + .xl\:bui-p-9 { + padding: var(--bui-space-9); + } + + .xl\:bui-p-10 { + padding: var(--bui-space-10); + } + + .xl\:bui-p-11 { + padding: var(--bui-space-11); + } + + .xl\:bui-p-12 { + padding: var(--bui-space-12); + } + + .xl\:bui-p-13 { + padding: var(--bui-space-13); + } + + .xl\:bui-p-14 { + padding: var(--bui-space-14); + } } - &[data-sort-order="asc"] svg { - opacity: 1; - transform: rotate(0); + .bui-pl { + padding-left: var(--pl); } - &[data-sort-order="desc"] svg { - opacity: 1; - transform: rotate(180deg); - } -} - -.bui-TableBody { - color: var(--bui-fg-primary); -} - -.bui-TableRow { - border-bottom: 1px solid var(--bui-border); - transition: color .2s ease-in-out; - - &[data-react-aria-pressable="true"] { - cursor: pointer; - } -} - -.bui-TableBody .bui-TableRow:hover { - background-color: var(--bui-gray-2); -} - -.bui-TableCell { - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); -} - -.bui-TableCellContentWrapper { - align-items: center; - gap: var(--bui-space-2); - flex-direction: row; - display: inline-flex; -} - -.bui-TableCellIcon, .bui-TableCellIcon svg { - color: var(--bui-fg-primary); - align-items: center; - display: inline-flex; -} - -.bui-TableCellContent { - gap: var(--bui-space-0_5); - flex-direction: column; - display: flex; -} - -.bui-TableCellProfile { - gap: var(--bui-space-2); - flex-direction: row; - align-items: center; - display: flex; -} - -.bui-TableCellProfileAvatar { - vertical-align: middle; - user-select: none; - color: var(--bui-fg-primary); - background-color: var(--bui-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; -} - -.bui-TableCellProfileAvatarImage { - object-fit: cover; - width: 100%; - height: 100%; -} - -.bui-TableCellProfileAvatarFallback { - width: 100%; - height: 100%; - font-size: var(--bui-font-size-2); - font-weight: var(--bui-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--bui-border); - border-radius: var(--bui-radius-full); - justify-content: center; - align-items: center; - display: flex; -} - -.bui-DataTablePagination { - padding-top: var(--bui-space-5); - justify-content: space-between; - align-items: center; - display: flex; -} - -.bui-DataTablePagination--left { - justify-content: space-between; - align-items: center; - display: flex; -} - -.bui-DataTablePagination--right { - justify-content: space-between; - align-items: center; - gap: var(--bui-space-2); - display: flex; -} - -.bui-DataTablePagination--select { - min-width: 10.5rem; -} - -.bui-Tabs { - --active-tab-left: 0px; - --active-tab-right: 0px; - --active-tab-top: 0px; - --active-tab-bottom: 0px; - --active-tab-width: 0px; - --active-tab-height: 0px; - --active-transition-duration: 0s; - --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; -} - -.bui-TabList { - flex-direction: row; - display: flex; -} - -.bui-TabListWrapper { - position: relative; -} - -.bui-Tab { - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-secondary); - cursor: pointer; - z-index: 2; - height: 36px; - padding-inline: var(--bui-space-2); - justify-content: center; - align-items: center; - display: flex; - position: relative; - - &[data-selected="true"] { - color: var(--bui-fg-primary); - } -} - -.bui-TabActive { - content: ""; - left: calc(var(--active-tab-left) + var(--bui-space-2)); - width: calc(var(--active-tab-width) - var(--bui-space-4)); - background-color: var(--bui-fg-primary); - height: 1px; - transition: left var(--active-transition-duration) ease-out, opacity .15s ease-out, width var(--active-transition-duration) ease-out; - opacity: 1; - border-radius: 4px; - position: absolute; - bottom: -1px; -} - -.bui-TabHovered { - 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(--bui-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; -} - -.bui-TabPanel { - padding-inline: var(--bui-space-2); - padding-top: var(--bui-space-4); -} - -.bui-TagList { - gap: var(--bui-space-2); - flex-wrap: wrap; - display: flex; -} - -.bui-Tag { - color: var(--bui-fg-primary); - background-color: var(--bui-gray-2); - border-radius: var(--bui-radius-2); - font-weight: var(--bui-font-weight-regular); - justify-content: center; - align-items: center; - gap: var(--bui-space-1); - box-sizing: border-box; - transition-property: background-color, box-shadow, color; - transition-duration: .2s; - transition-timing-function: ease-in-out; - display: flex; -} - -.bui-Tag[data-size="small"] { - height: 26px; - padding: 0 var(--bui-space-2); - font-size: var(--bui-font-size-1); -} - -.bui-Tag[data-size="medium"] { - height: 32px; - padding: 0 var(--bui-space-2); - font-size: var(--bui-font-size-2); -} - -.bui-Tag[data-hovered] { - background-color: var(--bui-gray-3); - cursor: pointer; -} - -.bui-Tag[data-focus-visible] { - outline: 2px solid var(--bui-ring); - outline-offset: 1px; -} - -.bui-Tag[data-selected] { - box-shadow: inset 0 0 0 1px var(--bui-gray-8); -} - -.bui-Tag[data-disabled] { - color: var(--bui-fg-disabled); - cursor: not-allowed; -} - -.bui-TagRemoveButton { - cursor: pointer; - color: var(--bui-fg-primary); - background-color: #0000; - border: none; - width: 1rem; - height: 1rem; - margin: 0; - padding: 0; -} - -.bui-TagIcon { - justify-content: center; - align-items: center; - transition: color .2s ease-in-out; - display: flex; - - & svg { - width: 1rem; - height: 1rem; - } -} - -.bui-Text { - font-family: var(--bui-font-regular); - margin: 0; - padding: 0; -} - -.bui-Text[data-variant="title-large"] { - font-size: var(--bui-font-size-8); - line-height: 140%; -} - -.bui-Text[data-variant="title-medium"] { - font-size: var(--bui-font-size-7); - line-height: 140%; -} - -.bui-Text[data-variant="title-small"] { - font-size: var(--bui-font-size-6); - line-height: 140%; -} - -.bui-Text[data-variant="title-x-small"] { - font-size: var(--bui-font-size-5); - line-height: 140%; -} - -.bui-Text[data-variant="body-large"] { - font-size: var(--bui-font-size-4); - line-height: 140%; -} - -.bui-Text[data-variant="body-medium"] { - font-size: var(--bui-font-size-3); - line-height: 140%; -} - -.bui-Text[data-variant="body-small"] { - font-size: var(--bui-font-size-2); - line-height: 140%; -} - -.bui-Text[data-variant="body-x-small"] { - font-size: var(--bui-font-size-1); - line-height: 140%; -} - -.bui-Text[data-weight="regular"] { - font-weight: var(--bui-font-weight-regular); -} - -.bui-Text[data-weight="bold"] { - font-weight: var(--bui-font-weight-bold); -} - -.bui-Text[data-color="primary"] { - color: var(--bui-fg-primary); -} - -.bui-Text[data-color="secondary"] { - color: var(--bui-fg-secondary); -} - -.bui-Text[data-color="danger"] { - color: var(--bui-fg-danger); -} - -.bui-Text[data-color="warning"] { - color: var(--bui-fg-warning); -} - -.bui-Text[data-color="success"] { - color: var(--bui-fg-success); -} - -.bui-Text[data-truncate] { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; -} - -.bui-Text[data-as="span"], .bui-Text[data-as="label"], .bui-Text[data-as="strong"], .bui-Text[data-as="em"], .bui-Text[data-as="small"] { - display: inline-block; -} - -.bui-TextField { - font-family: var(--bui-font-regular); - flex-direction: column; - flex-shrink: 0; - width: 100%; - display: flex; -} - -.bui-InputWrapper { - position: relative; - - &[data-size="small"] .bui-Input { - height: 2rem; + .bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); } - &[data-size="medium"] .bui-Input { - height: 2.5rem; + .bui-pl-1 { + padding-left: var(--bui-space-1); } - &[data-size="small"] .bui-Input[data-icon] { + .bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } + + .bui-pl-2 { + padding-left: var(--bui-space-2); + } + + .bui-pl-3 { + padding-left: var(--bui-space-3); + } + + .bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .bui-pl-8 { padding-left: var(--bui-space-8); } - &[data-size="medium"] .bui-Input[data-icon] { + .bui-pl-9 { padding-left: var(--bui-space-9); } -} -.bui-InputIcon { - left: var(--bui-space-3); - margin-right: var(--bui-space-1); - color: var(--bui-fg-primary); - pointer-events: none; - flex-shrink: 0; - transition: left .2s ease-in-out; - position: absolute; - top: 50%; - transform: translateY(-50%); - - &[data-size="small"], &[data-size="small"] svg { - width: 1rem; - height: 1rem; + .bui-pl-10 { + padding-left: var(--bui-space-10); } - &[data-size="medium"], &[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; - } -} - -.bui-Input { - padding: 0 var(--bui-space-3); - border-radius: var(--bui-radius-2); - border: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-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; + .bui-pl-11 { + padding-left: var(--bui-space-11); } - &::placeholder { - color: var(--bui-fg-secondary); + .bui-pl-12 { + padding-left: var(--bui-space-12); } - &[data-focused] { - outline-color: var(--bui-border-pressed); - outline-width: 0; + .bui-pl-13 { + padding-left: var(--bui-space-13); } - &[data-hovered] { - border-color: var(--bui-border-hover); + .bui-pl-14 { + padding-left: var(--bui-space-14); } - &[data-focused] { - border-color: var(--bui-border-pressed); - outline-width: 0; - } + @media (width >= 640px) { + .xs\:bui-pl { + padding-left: var(--pl-xs); + } - &[data-invalid] { - border-color: var(--bui-fg-danger); - } + .xs\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } - &[data-disabled] { - opacity: .5; - cursor: not-allowed; - border: 1px solid var(--bui-border-disabled); - } -} + .xs\:bui-pl-1 { + padding-left: var(--bui-space-1); + } -.bui-PasswordField { - font-family: var(--bui-font-regular); - --bui-passwordmanager-icon-width: var(--bui-space-1); - flex-direction: column; - flex-shrink: 0; - width: 100%; - display: flex; -} + .xs\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } -.bui-InputVisibility { - right: var(--bui-passwordmanager-icon-width); - cursor: pointer; - color: var(--bui-fg-primary); - background-color: #0000; - border: none; - justify-content: center; - align-items: center; - margin: 0; - padding: 0; - display: flex; - position: absolute; - top: 0; - bottom: 0; + .xs\:bui-pl-2 { + padding-left: var(--bui-space-2); + } - &[data-size="small"] { - width: 2rem; - height: 2rem; - } + .xs\:bui-pl-3 { + padding-left: var(--bui-space-3); + } - &[data-size="small"] svg { - width: 1rem; - height: 1rem; - } + .xs\:bui-pl-4 { + padding-left: var(--bui-space-4); + } - &[data-size="medium"] { - width: 2.5rem; - height: 2.5rem; - } + .xs\:bui-pl-5 { + padding-left: var(--bui-space-5); + } - &[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; - } -} + .xs\:bui-pl-6 { + padding-left: var(--bui-space-6); + } -.bui-PasswordField .bui-InputWrapper[data-size="small"] .bui-Input { - padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); -} + .xs\:bui-pl-7 { + padding-left: var(--bui-space-7); + } -.bui-PasswordField .bui-InputWrapper[data-size="medium"] .bui-Input { - padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); -} + .xs\:bui-pl-8 { + padding-left: var(--bui-space-8); + } -.bui-SearchField { - flex: 1 0; + .xs\:bui-pl-9 { + padding-left: var(--bui-space-9); + } - &[data-empty] { - & .bui-InputClear { - display: none; + .xs\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .xs\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .xs\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .xs\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .xs\:bui-pl-14 { + padding-left: var(--bui-space-14); } } - &[data-start-collapsed="true"] { - flex: 0 auto; - padding: 0; - transition: flex-basis .3s ease-in-out; - - &[data-collapsed="true"] { - flex-basis: 200px; + @media (width >= 768px) { + .sm\:bui-pl { + padding-left: var(--pl-sm); } - &[data-collapsed="false"] { - cursor: pointer; + .sm\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } - &[data-size="medium"] { - flex-basis: 2.5rem; - height: 2.5rem; - } + .sm\:bui-pl-1 { + padding-left: var(--bui-space-1); + } - &[data-size="small"] { - flex-basis: 2rem; - height: 2rem; - } + .sm\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } - &[data-size="medium"] .bui-Input { - &::placeholder { - opacity: 0; - } - } + .sm\:bui-pl-2 { + padding-left: var(--bui-space-2); + } - &[data-size="small"] .bui-Input { - &::placeholder { - opacity: 0; - } - } + .sm\:bui-pl-3 { + padding-left: var(--bui-space-3); + } - & .bui-InputWrapper { - & .bui-Input[data-icon] { - padding-right: 0; - } - } + .sm\:bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .sm\:bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .sm\:bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .sm\:bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .sm\:bui-pl-8 { + padding-left: var(--bui-space-8); + } + + .sm\:bui-pl-9 { + padding-left: var(--bui-space-9); + } + + .sm\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .sm\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .sm\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .sm\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .sm\:bui-pl-14 { + padding-left: var(--bui-space-14); } } -} -.bui-SearchField .bui-Input { - transition: padding .3s ease-in-out, border-color .2s ease-in-out, outline-color .2s ease-in-out; + @media (width >= 1024px) { + .md\:bui-pl { + padding-left: var(--pl-md); + } - &[data-hovered] { - border-color: var(--bui-border-hover); + .md\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } + + .md\:bui-pl-1 { + padding-left: var(--bui-space-1); + } + + .md\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } + + .md\:bui-pl-2 { + padding-left: var(--bui-space-2); + } + + .md\:bui-pl-3 { + padding-left: var(--bui-space-3); + } + + .md\:bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .md\:bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .md\:bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .md\:bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .md\:bui-pl-8 { + padding-left: var(--bui-space-8); + } + + .md\:bui-pl-9 { + padding-left: var(--bui-space-9); + } + + .md\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .md\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .md\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .md\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .md\:bui-pl-14 { + padding-left: var(--bui-space-14); + } } - &[data-focused] { - border-color: var(--bui-border-pressed); - outline-width: 0; - } -} + @media (width >= 1280px) { + .lg\:bui-pl { + padding-left: var(--pl-lg); + } -.bui-SearchField .bui-InputWrapper { - & .bui-Input[data-icon] { + .lg\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } + + .lg\:bui-pl-1 { + padding-left: var(--bui-space-1); + } + + .lg\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } + + .lg\:bui-pl-2 { + padding-left: var(--bui-space-2); + } + + .lg\:bui-pl-3 { + padding-left: var(--bui-space-3); + } + + .lg\:bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .lg\:bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .lg\:bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .lg\:bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .lg\:bui-pl-8 { + padding-left: var(--bui-space-8); + } + + .lg\:bui-pl-9 { + padding-left: var(--bui-space-9); + } + + .lg\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .lg\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .lg\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .lg\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .lg\:bui-pl-14 { + padding-left: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-pl { + padding-left: var(--pl-xl); + } + + .xl\:bui-pl-0\.5 { + padding-left: var(--bui-space-0_5); + } + + .xl\:bui-pl-1 { + padding-left: var(--bui-space-1); + } + + .xl\:bui-pl-1\.5 { + padding-left: var(--bui-space-1_5); + } + + .xl\:bui-pl-2 { + padding-left: var(--bui-space-2); + } + + .xl\:bui-pl-3 { + padding-left: var(--bui-space-3); + } + + .xl\:bui-pl-4 { + padding-left: var(--bui-space-4); + } + + .xl\:bui-pl-5 { + padding-left: var(--bui-space-5); + } + + .xl\:bui-pl-6 { + padding-left: var(--bui-space-6); + } + + .xl\:bui-pl-7 { + padding-left: var(--bui-space-7); + } + + .xl\:bui-pl-8 { + padding-left: var(--bui-space-8); + } + + .xl\:bui-pl-9 { + padding-left: var(--bui-space-9); + } + + .xl\:bui-pl-10 { + padding-left: var(--bui-space-10); + } + + .xl\:bui-pl-11 { + padding-left: var(--bui-space-11); + } + + .xl\:bui-pl-12 { + padding-left: var(--bui-space-12); + } + + .xl\:bui-pl-13 { + padding-left: var(--bui-space-13); + } + + .xl\:bui-pl-14 { + padding-left: var(--bui-space-14); + } + } + + .bui-pr { + padding-right: var(--pr); + } + + .bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } + + .bui-pr-1 { + padding-right: var(--bui-space-1); + } + + .bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } + + .bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .bui-pr-6 { padding-right: var(--bui-space-6); } -} -.bui-SearchField .bui-InputIcon { - justify-content: center; - display: flex; - left: 0; - - &[data-size="small"] { - width: var(--bui-space-8); + .bui-pr-7 { + padding-right: var(--bui-space-7); } - &[data-size="medium"] { - width: var(--bui-space-10); - } -} - -.bui-InputClear { - cursor: pointer; - color: var(--bui-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; -} - -.bui-InputClear:hover { - color: var(--bui-fg-primary); -} - -.bui-InputClear[data-size="small"] { - width: 2rem; - height: 2rem; -} - -.bui-InputClear[data-size="medium"] { - width: 2.5rem; - height: 2.5rem; -} - -.bui-InputClear svg { - width: 1rem; - height: 1rem; -} - -.bui-Skeleton { - animation: var(--bui-animate-pulse); - background-color: var(--bui-bg-surface-2); - border-radius: var(--bui-radius-2); -} - -.bui-Skeleton[data-rounded="true"] { - border-radius: var(--bui-radius-full); -} - -.bui-Tooltip { - background: var(--bui-bg-surface-1); - border: 1px solid var(--bui-gray-3); - forced-color-adjust: none; - padding: var(--bui-space-2) var(--bui-space-3); - max-width: 240px; - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - color: var(--bui-fg-primary); - border-radius: 4px; - outline: none; - transition: transform .2s, opacity .2s; - transform: translate3d(0, 0, 0); - box-shadow: 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a; - - &[data-entering], &[data-exiting] { - transform: var(--origin); - opacity: 0; + .bui-pr-8 { + padding-right: var(--bui-space-8); } - --tooltip-offset: var(--bui-space-3); - - &[data-placement="top"] { - margin-bottom: var(--tooltip-offset); - --origin: translateY(4px); + .bui-pr-9 { + padding-right: var(--bui-space-9); } - &[data-placement="right"] { - margin-left: var(--tooltip-offset); - --origin: translateX(-4px); + .bui-pr-10 { + padding-right: var(--bui-space-10); } - &[data-placement="bottom"] { - margin-top: var(--tooltip-offset); - --origin: translateY(-4px); + .bui-pr-11 { + padding-right: var(--bui-space-11); } - &[data-placement="left"] { - margin-right: var(--tooltip-offset); - --origin: translateX(4px); + .bui-pr-12 { + padding-right: var(--bui-space-12); } -} -.bui-TooltipArrow { - & svg { - display: block; + .bui-pr-13 { + padding-right: var(--bui-space-13); + } - & path:first-child { - fill: var(--bui-bg-surface-1); + .bui-pr-14 { + padding-right: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-pr { + padding-right: var(--pr-xs); } - & path:nth-child(2) { - fill: var(--bui-gray-3); + .xs\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); } - --tooltip-arrow-overlap: -2px; - } - - &[data-placement="top"] svg { - margin-top: var(--tooltip-arrow-overlap); - } - - &[data-placement="bottom"] svg { - margin-bottom: var(--tooltip-arrow-overlap); - transform: rotate(180deg); - } - - &[data-placement="right"] svg { - margin-right: var(--tooltip-arrow-overlap); - transform: rotate(90deg); - } - - &[data-placement="left"] svg { - margin-left: var(--tooltip-arrow-overlap); - transform: rotate(-90deg); - } -} - -[data-theme="dark"] { - & .bui-Tooltip { - background: var(--bui-bg-surface-2); - box-shadow: none; - border: 1px solid var(--bui-gray-4); - } - - & .bui-TooltipArrow { - & svg path:first-child { - fill: var(--bui-bg-surface-2); + .xs\:bui-pr-1 { + padding-right: var(--bui-space-1); } - & svg path:nth-child(2) { - fill: var(--bui-gray-4); + .xs\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } + + .xs\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .xs\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .xs\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .xs\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .xs\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .xs\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .xs\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .xs\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .xs\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .xs\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .xs\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .xs\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .xs\:bui-pr-14 { + padding-right: var(--bui-space-14); } } -} -.bui-ScrollAreaRoot { - box-sizing: border-box; - width: 100%; -} + @media (width >= 768px) { + .sm\:bui-pr { + padding-right: var(--pr-sm); + } -.bui-ScrollAreaViewport { - overscroll-behavior: contain; - height: 100%; -} + .sm\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } -.bui-ScrollAreaContent { - padding-block: .75rem; - flex-direction: column; - gap: 1rem; - padding-left: 1rem; - padding-right: 1.5rem; - display: flex; -} + .sm\:bui-pr-1 { + padding-right: var(--bui-space-1); + } -.bui-ScrollAreaScrollbar { - background-color: var(--bui-scrollbar); - opacity: 0; - border-radius: .375rem; - justify-content: center; - width: .25rem; - margin: .5rem; - transition: opacity .15s .3s; - display: flex; + .sm\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } - &[data-hovering], &[data-scrolling] { - opacity: 1; - transition-duration: 75ms; - transition-delay: 0s; + .sm\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .sm\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .sm\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .sm\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .sm\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .sm\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .sm\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .sm\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .sm\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .sm\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .sm\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .sm\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .sm\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } - &:before { - content: ""; - width: 1.25rem; - height: 100%; - position: absolute; - } -} + @media (width >= 1024px) { + .md\:bui-pr { + padding-right: var(--pr-md); + } -.bui-ScrollAreaThumb { - border-radius: inherit; - background-color: var(--bui-scrollbar-thumb); - width: 100%; -} + .md\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } -.bui-Select[data-invalid] { - & .bui-SelectTrigger { - border-color: var(--bui-fg-danger); - } -} + .md\:bui-pr-1 { + padding-right: var(--bui-space-1); + } -.bui-SelectTrigger { - box-sizing: border-box; - border-radius: var(--bui-radius-3); - border: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - cursor: pointer; - justify-content: space-between; - align-items: center; - gap: var(--bui-space-2); - width: 100%; - display: flex; + .md\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } - & svg { - color: var(--bui-fg-secondary); - flex-shrink: 0; + .md\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .md\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .md\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .md\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .md\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .md\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .md\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .md\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .md\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .md\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .md\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .md\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .md\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } - &[data-size="small"] { - height: 2rem; - padding-inline: var(--bui-space-3); + @media (width >= 1280px) { + .lg\:bui-pr { + padding-right: var(--pr-lg); + } + + .lg\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } + + .lg\:bui-pr-1 { + padding-right: var(--bui-space-1); + } + + .lg\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } + + .lg\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .lg\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .lg\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .lg\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .lg\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .lg\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .lg\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .lg\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .lg\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .lg\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .lg\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .lg\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .lg\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } - &[data-size="medium"] { - height: 3rem; - padding-inline: var(--bui-space-4); + @media (width >= 1536px) { + .xl\:bui-pr { + padding-right: var(--pr-xl); + } + + .xl\:bui-pr-0\.5 { + padding-right: var(--bui-space-0_5); + } + + .xl\:bui-pr-1 { + padding-right: var(--bui-space-1); + } + + .xl\:bui-pr-1\.5 { + padding-right: var(--bui-space-1_5); + } + + .xl\:bui-pr-2 { + padding-right: var(--bui-space-2); + } + + .xl\:bui-pr-3 { + padding-right: var(--bui-space-3); + } + + .xl\:bui-pr-4 { + padding-right: var(--bui-space-4); + } + + .xl\:bui-pr-5 { + padding-right: var(--bui-space-5); + } + + .xl\:bui-pr-6 { + padding-right: var(--bui-space-6); + } + + .xl\:bui-pr-7 { + padding-right: var(--bui-space-7); + } + + .xl\:bui-pr-8 { + padding-right: var(--bui-space-8); + } + + .xl\:bui-pr-9 { + padding-right: var(--bui-space-9); + } + + .xl\:bui-pr-10 { + padding-right: var(--bui-space-10); + } + + .xl\:bui-pr-11 { + padding-right: var(--bui-space-11); + } + + .xl\:bui-pr-12 { + padding-right: var(--bui-space-12); + } + + .xl\:bui-pr-13 { + padding-right: var(--bui-space-13); + } + + .xl\:bui-pr-14 { + padding-right: var(--bui-space-14); + } } - &[data-size="small"] svg { - width: 1rem; - height: 1rem; + .bui-pt { + padding-top: var(--pt); } - &[data-size="medium"] svg { - width: 1.25rem; - height: 1.25rem; + .bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); } - &::placeholder { - color: var(--bui-fg-secondary); + .bui-pt-1 { + padding-top: var(--bui-space-1); } - &:hover { - border-color: var(--bui-border-hover); - transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; + .bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); } - &:focus-visible { - border-color: var(--bui-border-pressed); - outline: 0; + .bui-pt-2 { + padding-top: var(--bui-space-2); } - &[data-invalid] { - border-color: var(--bui-fg-danger); + .bui-pt-3 { + padding-top: var(--bui-space-3); } - &[data-invalid]:hover, &[data-invalid]:focus-visible { - border-width: 2px; + .bui-pt-4 { + padding-top: var(--bui-space-4); } - &[disabled] { - cursor: not-allowed; - border-color: var(--bui-border-disabled); - color: var(--bui-fg-disabled); + .bui-pt-5 { + padding-top: var(--bui-space-5); } - &[disabled] .bui-SelectValue { - color: var(--bui-fg-disabled); + .bui-pt-6 { + padding-top: var(--bui-space-6); } - &[data-popup-open] .bui-SelectIcon { - transform: rotate(180deg); + .bui-pt-7 { + padding-top: var(--bui-space-7); } -} -.bui-SelectValue { - text-overflow: ellipsis; - white-space: nowrap; - width: 100%; - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - text-align: left; - overflow: hidden; + .bui-pt-8 { + padding-top: var(--bui-space-8); + } - & .bui-SelectItemIndicator { + .bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .bui-pt-14 { + padding-top: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-pt { + padding-top: var(--pt-xs); + } + + .xs\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .xs\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .xs\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .xs\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .xs\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .xs\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .xs\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .xs\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .xs\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .xs\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .xs\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .xs\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .xs\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .xs\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .xs\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .xs\:bui-pt-14 { + padding-top: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-pt { + padding-top: var(--pt-sm); + } + + .sm\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .sm\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .sm\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .sm\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .sm\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .sm\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .sm\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .sm\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .sm\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .sm\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .sm\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .sm\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .sm\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .sm\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .sm\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .sm\:bui-pt-14 { + padding-top: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-pt { + padding-top: var(--pt-md); + } + + .md\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .md\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .md\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .md\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .md\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .md\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .md\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .md\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .md\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .md\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .md\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .md\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .md\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .md\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .md\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .md\:bui-pt-14 { + padding-top: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-pt { + padding-top: var(--pt-lg); + } + + .lg\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .lg\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .lg\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .lg\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .lg\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .lg\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .lg\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .lg\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .lg\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .lg\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .lg\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .lg\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .lg\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .lg\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .lg\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .lg\:bui-pt-14 { + padding-top: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-pt { + padding-top: var(--pt-xl); + } + + .xl\:bui-pt-0\.5 { + padding-top: var(--bui-space-0_5); + } + + .xl\:bui-pt-1 { + padding-top: var(--bui-space-1); + } + + .xl\:bui-pt-1\.5 { + padding-top: var(--bui-space-1_5); + } + + .xl\:bui-pt-2 { + padding-top: var(--bui-space-2); + } + + .xl\:bui-pt-3 { + padding-top: var(--bui-space-3); + } + + .xl\:bui-pt-4 { + padding-top: var(--bui-space-4); + } + + .xl\:bui-pt-5 { + padding-top: var(--bui-space-5); + } + + .xl\:bui-pt-6 { + padding-top: var(--bui-space-6); + } + + .xl\:bui-pt-7 { + padding-top: var(--bui-space-7); + } + + .xl\:bui-pt-8 { + padding-top: var(--bui-space-8); + } + + .xl\:bui-pt-9 { + padding-top: var(--bui-space-9); + } + + .xl\:bui-pt-10 { + padding-top: var(--bui-space-10); + } + + .xl\:bui-pt-11 { + padding-top: var(--bui-space-11); + } + + .xl\:bui-pt-12 { + padding-top: var(--bui-space-12); + } + + .xl\:bui-pt-13 { + padding-top: var(--bui-space-13); + } + + .xl\:bui-pt-14 { + padding-top: var(--bui-space-14); + } + } + + .bui-pb { + padding-bottom: var(--pb); + } + + .bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .bui-pb-14 { + padding-bottom: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-pb { + padding-bottom: var(--pb-xs); + } + + .xs\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .xs\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .xs\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .xs\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .xs\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .xs\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .xs\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .xs\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .xs\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .xs\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .xs\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .xs\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .xs\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .xs\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .xs\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .xs\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-pb { + padding-bottom: var(--pb-sm); + } + + .sm\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .sm\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .sm\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .sm\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .sm\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .sm\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .sm\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .sm\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .sm\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .sm\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .sm\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .sm\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .sm\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .sm\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .sm\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .sm\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-pb { + padding-bottom: var(--pb-md); + } + + .md\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .md\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .md\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .md\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .md\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .md\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .md\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .md\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .md\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .md\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .md\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .md\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .md\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .md\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .md\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .md\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-pb { + padding-bottom: var(--pb-lg); + } + + .lg\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .lg\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .lg\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .lg\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .lg\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .lg\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .lg\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .lg\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .lg\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .lg\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .lg\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .lg\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .lg\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .lg\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .lg\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .lg\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-pb { + padding-bottom: var(--pb-xl); + } + + .xl\:bui-pb-0\.5 { + padding-bottom: var(--bui-space-0_5); + } + + .xl\:bui-pb-1 { + padding-bottom: var(--bui-space-1); + } + + .xl\:bui-pb-1\.5 { + padding-bottom: var(--bui-space-1_5); + } + + .xl\:bui-pb-2 { + padding-bottom: var(--bui-space-2); + } + + .xl\:bui-pb-3 { + padding-bottom: var(--bui-space-3); + } + + .xl\:bui-pb-4 { + padding-bottom: var(--bui-space-4); + } + + .xl\:bui-pb-5 { + padding-bottom: var(--bui-space-5); + } + + .xl\:bui-pb-6 { + padding-bottom: var(--bui-space-6); + } + + .xl\:bui-pb-7 { + padding-bottom: var(--bui-space-7); + } + + .xl\:bui-pb-8 { + padding-bottom: var(--bui-space-8); + } + + .xl\:bui-pb-9 { + padding-bottom: var(--bui-space-9); + } + + .xl\:bui-pb-10 { + padding-bottom: var(--bui-space-10); + } + + .xl\:bui-pb-11 { + padding-bottom: var(--bui-space-11); + } + + .xl\:bui-pb-12 { + padding-bottom: var(--bui-space-12); + } + + .xl\:bui-pb-13 { + padding-bottom: var(--bui-space-13); + } + + .xl\:bui-pb-14 { + padding-bottom: var(--bui-space-14); + } + } + + .bui-py { + padding-top: var(--py); + padding-bottom: var(--py); + } + + .bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-py { + padding-top: var(--py-xs); + padding-bottom: var(--py-xs); + } + + .xs\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .xs\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .xs\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .xs\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .xs\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .xs\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .xs\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .xs\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .xs\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .xs\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .xs\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .xs\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .xs\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .xs\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .xs\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .xs\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-py { + padding-top: var(--py-sm); + padding-bottom: var(--py-sm); + } + + .sm\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .sm\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .sm\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .sm\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .sm\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .sm\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .sm\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .sm\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .sm\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .sm\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .sm\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .sm\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .sm\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .sm\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .sm\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .sm\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-py { + padding-top: var(--py-md); + padding-bottom: var(--py-md); + } + + .md\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .md\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .md\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .md\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .md\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .md\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .md\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .md\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .md\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .md\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .md\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .md\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .md\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .md\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .md\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .md\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-py { + padding-top: var(--py-lg); + padding-bottom: var(--py-lg); + } + + .lg\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .lg\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .lg\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .lg\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .lg\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .lg\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .lg\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .lg\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .lg\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .lg\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .lg\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .lg\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .lg\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .lg\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .lg\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .lg\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-py { + padding-top: var(--py-xl); + padding-bottom: var(--py-xl); + } + + .xl\:bui-py-0\.5 { + padding-top: var(--bui-space-0_5); + padding-bottom: var(--bui-space-0_5); + } + + .xl\:bui-py-1 { + padding-top: var(--bui-space-1); + padding-bottom: var(--bui-space-1); + } + + .xl\:bui-py-1\.5 { + padding-top: var(--bui-space-1_5); + padding-bottom: var(--bui-space-1_5); + } + + .xl\:bui-py-2 { + padding-top: var(--bui-space-2); + padding-bottom: var(--bui-space-2); + } + + .xl\:bui-py-3 { + padding-top: var(--bui-space-3); + padding-bottom: var(--bui-space-3); + } + + .xl\:bui-py-4 { + padding-top: var(--bui-space-4); + padding-bottom: var(--bui-space-4); + } + + .xl\:bui-py-5 { + padding-top: var(--bui-space-5); + padding-bottom: var(--bui-space-5); + } + + .xl\:bui-py-6 { + padding-top: var(--bui-space-6); + padding-bottom: var(--bui-space-6); + } + + .xl\:bui-py-7 { + padding-top: var(--bui-space-7); + padding-bottom: var(--bui-space-7); + } + + .xl\:bui-py-8 { + padding-top: var(--bui-space-8); + padding-bottom: var(--bui-space-8); + } + + .xl\:bui-py-9 { + padding-top: var(--bui-space-9); + padding-bottom: var(--bui-space-9); + } + + .xl\:bui-py-10 { + padding-top: var(--bui-space-10); + padding-bottom: var(--bui-space-10); + } + + .xl\:bui-py-11 { + padding-top: var(--bui-space-11); + padding-bottom: var(--bui-space-11); + } + + .xl\:bui-py-12 { + padding-top: var(--bui-space-12); + padding-bottom: var(--bui-space-12); + } + + .xl\:bui-py-13 { + padding-top: var(--bui-space-13); + padding-bottom: var(--bui-space-13); + } + + .xl\:bui-py-14 { + padding-top: var(--bui-space-14); + padding-bottom: var(--bui-space-14); + } + } + + .bui-px { + padding-left: var(--px); + padding-right: var(--px); + } + + .bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-px { + padding-left: var(--px-xs); + padding-right: var(--px-xs); + } + + .xs\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .xs\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .xs\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .xs\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .xs\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .xs\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .xs\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .xs\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .xs\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .xs\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .xs\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .xs\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .xs\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .xs\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .xs\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .xs\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-px { + padding-left: var(--px-sm); + padding-right: var(--px-sm); + } + + .sm\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .sm\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .sm\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .sm\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .sm\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .sm\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .sm\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .sm\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .sm\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .sm\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .sm\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .sm\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .sm\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .sm\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .sm\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .sm\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-px { + padding-left: var(--px-md); + padding-right: var(--px-md); + } + + .md\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .md\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .md\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .md\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .md\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .md\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .md\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .md\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .md\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .md\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .md\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .md\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .md\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .md\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .md\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .md\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-px { + padding-left: var(--px-lg); + padding-right: var(--px-lg); + } + + .lg\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .lg\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .lg\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .lg\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .lg\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .lg\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .lg\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .lg\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .lg\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .lg\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .lg\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .lg\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .lg\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .lg\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .lg\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .lg\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-px { + padding-left: var(--px-xl); + padding-right: var(--px-xl); + } + + .xl\:bui-px-0\.5 { + padding-left: var(--bui-space-0_5); + padding-right: var(--bui-space-0_5); + } + + .xl\:bui-px-1 { + padding-left: var(--bui-space-1); + padding-right: var(--bui-space-1); + } + + .xl\:bui-px-1\.5 { + padding-left: var(--bui-space-1_5); + padding-right: var(--bui-space-1_5); + } + + .xl\:bui-px-2 { + padding-left: var(--bui-space-2); + padding-right: var(--bui-space-2); + } + + .xl\:bui-px-3 { + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-3); + } + + .xl\:bui-px-4 { + padding-left: var(--bui-space-4); + padding-right: var(--bui-space-4); + } + + .xl\:bui-px-5 { + padding-left: var(--bui-space-5); + padding-right: var(--bui-space-5); + } + + .xl\:bui-px-6 { + padding-left: var(--bui-space-6); + padding-right: var(--bui-space-6); + } + + .xl\:bui-px-7 { + padding-left: var(--bui-space-7); + padding-right: var(--bui-space-7); + } + + .xl\:bui-px-8 { + padding-left: var(--bui-space-8); + padding-right: var(--bui-space-8); + } + + .xl\:bui-px-9 { + padding-left: var(--bui-space-9); + padding-right: var(--bui-space-9); + } + + .xl\:bui-px-10 { + padding-left: var(--bui-space-10); + padding-right: var(--bui-space-10); + } + + .xl\:bui-px-11 { + padding-left: var(--bui-space-11); + padding-right: var(--bui-space-11); + } + + .xl\:bui-px-12 { + padding-left: var(--bui-space-12); + padding-right: var(--bui-space-12); + } + + .xl\:bui-px-13 { + padding-left: var(--bui-space-13); + padding-right: var(--bui-space-13); + } + + .xl\:bui-px-14 { + padding-left: var(--bui-space-14); + padding-right: var(--bui-space-14); + } + } + + .bui-m { + margin: var(--m); + } + + .bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .bui-m-1 { + margin: var(--bui-space-1); + } + + .bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .bui-m-2 { + margin: var(--bui-space-2); + } + + .bui-m-3 { + margin: var(--bui-space-3); + } + + .bui-m-4 { + margin: var(--bui-space-4); + } + + .bui-m-5 { + margin: var(--bui-space-5); + } + + .bui-m-6 { + margin: var(--bui-space-6); + } + + .bui-m-7 { + margin: var(--bui-space-7); + } + + .bui-m-8 { + margin: var(--bui-space-8); + } + + .bui-m-9 { + margin: var(--bui-space-9); + } + + .bui-m-10 { + margin: var(--bui-space-10); + } + + .bui-m-11 { + margin: var(--bui-space-11); + } + + .bui-m-12 { + margin: var(--bui-space-12); + } + + .bui-m-13 { + margin: var(--bui-space-13); + } + + .bui-m-14 { + margin: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-m { + margin: var(--p-xs); + } + + .xs\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .xs\:bui-m-1 { + margin: var(--bui-space-1); + } + + .xs\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .xs\:bui-m-2 { + margin: var(--bui-space-2); + } + + .xs\:bui-m-3 { + margin: var(--bui-space-3); + } + + .xs\:bui-m-4 { + margin: var(--bui-space-4); + } + + .xs\:bui-m-5 { + margin: var(--bui-space-5); + } + + .xs\:bui-m-6 { + margin: var(--bui-space-6); + } + + .xs\:bui-m-7 { + margin: var(--bui-space-7); + } + + .xs\:bui-m-8 { + margin: var(--bui-space-8); + } + + .xs\:bui-m-9 { + margin: var(--bui-space-9); + } + + .xs\:bui-m-10 { + margin: var(--bui-space-10); + } + + .xs\:bui-m-11 { + margin: var(--bui-space-11); + } + + .xs\:bui-m-12 { + margin: var(--bui-space-12); + } + + .xs\:bui-m-13 { + margin: var(--bui-space-13); + } + + .xs\:bui-m-14 { + margin: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-m { + margin: var(--p-sm); + } + + .sm\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .sm\:bui-m-1 { + margin: var(--bui-space-1); + } + + .sm\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .sm\:bui-m-2 { + margin: var(--bui-space-2); + } + + .sm\:bui-m-3 { + margin: var(--bui-space-3); + } + + .sm\:bui-m-4 { + margin: var(--bui-space-4); + } + + .sm\:bui-m-5 { + margin: var(--bui-space-5); + } + + .sm\:bui-m-6 { + margin: var(--bui-space-6); + } + + .sm\:bui-m-7 { + margin: var(--bui-space-7); + } + + .sm\:bui-m-8 { + margin: var(--bui-space-8); + } + + .sm\:bui-m-9 { + margin: var(--bui-space-9); + } + + .sm\:bui-m-10 { + margin: var(--bui-space-10); + } + + .sm\:bui-m-11 { + margin: var(--bui-space-11); + } + + .sm\:bui-m-12 { + margin: var(--bui-space-12); + } + + .sm\:bui-m-13 { + margin: var(--bui-space-13); + } + + .sm\:bui-m-14 { + margin: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-m { + margin: var(--p-md); + } + + .md\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .md\:bui-m-1 { + margin: var(--bui-space-1); + } + + .md\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .md\:bui-m-2 { + margin: var(--bui-space-2); + } + + .md\:bui-m-3 { + margin: var(--bui-space-3); + } + + .md\:bui-m-4 { + margin: var(--bui-space-4); + } + + .md\:bui-m-5 { + margin: var(--bui-space-5); + } + + .md\:bui-m-6 { + margin: var(--bui-space-6); + } + + .md\:bui-m-7 { + margin: var(--bui-space-7); + } + + .md\:bui-m-8 { + margin: var(--bui-space-8); + } + + .md\:bui-m-9 { + margin: var(--bui-space-9); + } + + .md\:bui-m-10 { + margin: var(--bui-space-10); + } + + .md\:bui-m-11 { + margin: var(--bui-space-11); + } + + .md\:bui-m-12 { + margin: var(--bui-space-12); + } + + .md\:bui-m-13 { + margin: var(--bui-space-13); + } + + .md\:bui-m-14 { + margin: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-m { + margin: var(--p-lg); + } + + .lg\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .lg\:bui-m-1 { + margin: var(--bui-space-1); + } + + .lg\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .lg\:bui-m-2 { + margin: var(--bui-space-2); + } + + .lg\:bui-m-3 { + margin: var(--bui-space-3); + } + + .lg\:bui-m-4 { + margin: var(--bui-space-4); + } + + .lg\:bui-m-5 { + margin: var(--bui-space-5); + } + + .lg\:bui-m-6 { + margin: var(--bui-space-6); + } + + .lg\:bui-m-7 { + margin: var(--bui-space-7); + } + + .lg\:bui-m-8 { + margin: var(--bui-space-8); + } + + .lg\:bui-m-9 { + margin: var(--bui-space-9); + } + + .lg\:bui-m-10 { + margin: var(--bui-space-10); + } + + .lg\:bui-m-11 { + margin: var(--bui-space-11); + } + + .lg\:bui-m-12 { + margin: var(--bui-space-12); + } + + .lg\:bui-m-13 { + margin: var(--bui-space-13); + } + + .lg\:bui-m-14 { + margin: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-m { + margin: var(--p-xl); + } + + .xl\:bui-m-0\.5 { + margin: var(--bui-space-0_5); + } + + .xl\:bui-m-1 { + margin: var(--bui-space-1); + } + + .xl\:bui-m-1\.5 { + margin: var(--bui-space-1_5); + } + + .xl\:bui-m-2 { + margin: var(--bui-space-2); + } + + .xl\:bui-m-3 { + margin: var(--bui-space-3); + } + + .xl\:bui-m-4 { + margin: var(--bui-space-4); + } + + .xl\:bui-m-5 { + margin: var(--bui-space-5); + } + + .xl\:bui-m-6 { + margin: var(--bui-space-6); + } + + .xl\:bui-m-7 { + margin: var(--bui-space-7); + } + + .xl\:bui-m-8 { + margin: var(--bui-space-8); + } + + .xl\:bui-m-9 { + margin: var(--bui-space-9); + } + + .xl\:bui-m-10 { + margin: var(--bui-space-10); + } + + .xl\:bui-m-11 { + margin: var(--bui-space-11); + } + + .xl\:bui-m-12 { + margin: var(--bui-space-12); + } + + .xl\:bui-m-13 { + margin: var(--bui-space-13); + } + + .xl\:bui-m-14 { + margin: var(--bui-space-14); + } + } + + .bui-ml { + margin-left: var(--ml); + } + + .bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .bui-ml-14 { + margin-left: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-ml { + margin-left: var(--pl-xs); + } + + .xs\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .xs\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .xs\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .xs\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .xs\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .xs\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .xs\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .xs\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .xs\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .xs\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .xs\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .xs\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .xs\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .xs\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .xs\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .xs\:bui-ml-14 { + margin-left: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-ml { + margin-left: var(--pl-sm); + } + + .sm\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .sm\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .sm\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .sm\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .sm\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .sm\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .sm\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .sm\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .sm\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .sm\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .sm\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .sm\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .sm\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .sm\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .sm\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .sm\:bui-ml-14 { + margin-left: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-ml { + margin-left: var(--pl-md); + } + + .md\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .md\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .md\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .md\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .md\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .md\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .md\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .md\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .md\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .md\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .md\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .md\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .md\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .md\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .md\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .md\:bui-ml-14 { + margin-left: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-ml { + margin-left: var(--pl-lg); + } + + .lg\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .lg\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .lg\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .lg\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .lg\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .lg\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .lg\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .lg\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .lg\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .lg\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .lg\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .lg\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .lg\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .lg\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .lg\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .lg\:bui-ml-14 { + margin-left: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-ml { + margin-left: var(--pl-xl); + } + + .xl\:bui-ml-0\.5 { + margin-left: var(--bui-space-0_5); + } + + .xl\:bui-ml-1 { + margin-left: var(--bui-space-1); + } + + .xl\:bui-ml-1\.5 { + margin-left: var(--bui-space-1_5); + } + + .xl\:bui-ml-2 { + margin-left: var(--bui-space-2); + } + + .xl\:bui-ml-3 { + margin-left: var(--bui-space-3); + } + + .xl\:bui-ml-4 { + margin-left: var(--bui-space-4); + } + + .xl\:bui-ml-5 { + margin-left: var(--bui-space-5); + } + + .xl\:bui-ml-6 { + margin-left: var(--bui-space-6); + } + + .xl\:bui-ml-7 { + margin-left: var(--bui-space-7); + } + + .xl\:bui-ml-8 { + margin-left: var(--bui-space-8); + } + + .xl\:bui-ml-9 { + margin-left: var(--bui-space-9); + } + + .xl\:bui-ml-10 { + margin-left: var(--bui-space-10); + } + + .xl\:bui-ml-11 { + margin-left: var(--bui-space-11); + } + + .xl\:bui-ml-12 { + margin-left: var(--bui-space-12); + } + + .xl\:bui-ml-13 { + margin-left: var(--bui-space-13); + } + + .xl\:bui-ml-14 { + margin-left: var(--bui-space-14); + } + } + + .bui-mr { + margin-right: var(--mr); + } + + .bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .bui-mr-14 { + margin-right: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-mr { + margin-right: var(--pr-xs); + } + + .xs\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .xs\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .xs\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .xs\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .xs\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .xs\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .xs\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .xs\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .xs\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .xs\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .xs\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .xs\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .xs\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .xs\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .xs\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .xs\:bui-mr-14 { + margin-right: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-mr { + margin-right: var(--pr-sm); + } + + .sm\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .sm\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .sm\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .sm\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .sm\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .sm\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .sm\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .sm\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .sm\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .sm\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .sm\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .sm\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .sm\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .sm\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .sm\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .sm\:bui-mr-14 { + margin-right: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-mr { + margin-right: var(--pr-md); + } + + .md\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .md\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .md\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .md\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .md\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .md\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .md\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .md\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .md\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .md\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .md\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .md\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .md\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .md\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .md\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .md\:bui-mr-14 { + margin-right: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-mr { + margin-right: var(--pr-lg); + } + + .lg\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .lg\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .lg\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .lg\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .lg\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .lg\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .lg\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .lg\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .lg\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .lg\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .lg\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .lg\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .lg\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .lg\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .lg\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .lg\:bui-mr-14 { + margin-right: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-mr { + margin-right: var(--pr-xl); + } + + .xl\:bui-mr-0\.5 { + margin-right: var(--bui-space-0_5); + } + + .xl\:bui-mr-1 { + margin-right: var(--bui-space-1); + } + + .xl\:bui-mr-1\.5 { + margin-right: var(--bui-space-1_5); + } + + .xl\:bui-mr-2 { + margin-right: var(--bui-space-2); + } + + .xl\:bui-mr-3 { + margin-right: var(--bui-space-3); + } + + .xl\:bui-mr-4 { + margin-right: var(--bui-space-4); + } + + .xl\:bui-mr-5 { + margin-right: var(--bui-space-5); + } + + .xl\:bui-mr-6 { + margin-right: var(--bui-space-6); + } + + .xl\:bui-mr-7 { + margin-right: var(--bui-space-7); + } + + .xl\:bui-mr-8 { + margin-right: var(--bui-space-8); + } + + .xl\:bui-mr-9 { + margin-right: var(--bui-space-9); + } + + .xl\:bui-mr-10 { + margin-right: var(--bui-space-10); + } + + .xl\:bui-mr-11 { + margin-right: var(--bui-space-11); + } + + .xl\:bui-mr-12 { + margin-right: var(--bui-space-12); + } + + .xl\:bui-mr-13 { + margin-right: var(--bui-space-13); + } + + .xl\:bui-mr-14 { + margin-right: var(--bui-space-14); + } + } + + .bui-mt { + margin-top: var(--mt); + } + + .bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .bui-mt-14 { + margin-top: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-mt { + margin-top: var(--pt-xs); + } + + .xs\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .xs\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .xs\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .xs\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .xs\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .xs\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .xs\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .xs\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .xs\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .xs\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .xs\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .xs\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .xs\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .xs\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .xs\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .xs\:bui-mt-14 { + margin-top: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-mt { + margin-top: var(--pt-sm); + } + + .sm\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .sm\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .sm\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .sm\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .sm\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .sm\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .sm\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .sm\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .sm\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .sm\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .sm\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .sm\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .sm\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .sm\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .sm\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .sm\:bui-mt-14 { + margin-top: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-mt { + margin-top: var(--pt-md); + } + + .md\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .md\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .md\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .md\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .md\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .md\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .md\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .md\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .md\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .md\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .md\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .md\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .md\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .md\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .md\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .md\:bui-mt-14 { + margin-top: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-mt { + margin-top: var(--pt-lg); + } + + .lg\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .lg\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .lg\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .lg\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .lg\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .lg\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .lg\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .lg\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .lg\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .lg\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .lg\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .lg\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .lg\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .lg\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .lg\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .lg\:bui-mt-14 { + margin-top: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-mt { + margin-top: var(--pt-xl); + } + + .xl\:bui-mt-0\.5 { + margin-top: var(--bui-space-0_5); + } + + .xl\:bui-mt-1 { + margin-top: var(--bui-space-1); + } + + .xl\:bui-mt-1\.5 { + margin-top: var(--bui-space-1_5); + } + + .xl\:bui-mt-2 { + margin-top: var(--bui-space-2); + } + + .xl\:bui-mt-3 { + margin-top: var(--bui-space-3); + } + + .xl\:bui-mt-4 { + margin-top: var(--bui-space-4); + } + + .xl\:bui-mt-5 { + margin-top: var(--bui-space-5); + } + + .xl\:bui-mt-6 { + margin-top: var(--bui-space-6); + } + + .xl\:bui-mt-7 { + margin-top: var(--bui-space-7); + } + + .xl\:bui-mt-8 { + margin-top: var(--bui-space-8); + } + + .xl\:bui-mt-9 { + margin-top: var(--bui-space-9); + } + + .xl\:bui-mt-10 { + margin-top: var(--bui-space-10); + } + + .xl\:bui-mt-11 { + margin-top: var(--bui-space-11); + } + + .xl\:bui-mt-12 { + margin-top: var(--bui-space-12); + } + + .xl\:bui-mt-13 { + margin-top: var(--bui-space-13); + } + + .xl\:bui-mt-14 { + margin-top: var(--bui-space-14); + } + } + + .bui-mb { + margin-bottom: var(--mb); + } + + .bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .bui-mb-14 { + margin-bottom: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-mb { + margin-bottom: var(--pb-xs); + } + + .xs\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .xs\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .xs\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .xs\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .xs\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .xs\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .xs\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .xs\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .xs\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .xs\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .xs\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .xs\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .xs\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .xs\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .xs\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .xs\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-mb { + margin-bottom: var(--pb-sm); + } + + .sm\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .sm\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .sm\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .sm\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .sm\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .sm\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .sm\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .sm\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .sm\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .sm\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .sm\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .sm\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .sm\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .sm\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .sm\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .sm\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-mb { + margin-bottom: var(--pb-md); + } + + .md\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .md\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .md\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .md\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .md\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .md\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .md\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .md\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .md\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .md\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .md\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .md\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .md\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .md\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .md\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .md\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-mb { + margin-bottom: var(--pb-lg); + } + + .lg\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .lg\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .lg\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .lg\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .lg\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .lg\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .lg\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .lg\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .lg\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .lg\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .lg\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .lg\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .lg\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .lg\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .lg\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .lg\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-mb { + margin-bottom: var(--pb-xl); + } + + .xl\:bui-mb-0\.5 { + margin-bottom: var(--bui-space-0_5); + } + + .xl\:bui-mb-1 { + margin-bottom: var(--bui-space-1); + } + + .xl\:bui-mb-1\.5 { + margin-bottom: var(--bui-space-1_5); + } + + .xl\:bui-mb-2 { + margin-bottom: var(--bui-space-2); + } + + .xl\:bui-mb-3 { + margin-bottom: var(--bui-space-3); + } + + .xl\:bui-mb-4 { + margin-bottom: var(--bui-space-4); + } + + .xl\:bui-mb-5 { + margin-bottom: var(--bui-space-5); + } + + .xl\:bui-mb-6 { + margin-bottom: var(--bui-space-6); + } + + .xl\:bui-mb-7 { + margin-bottom: var(--bui-space-7); + } + + .xl\:bui-mb-8 { + margin-bottom: var(--bui-space-8); + } + + .xl\:bui-mb-9 { + margin-bottom: var(--bui-space-9); + } + + .xl\:bui-mb-10 { + margin-bottom: var(--bui-space-10); + } + + .xl\:bui-mb-11 { + margin-bottom: var(--bui-space-11); + } + + .xl\:bui-mb-12 { + margin-bottom: var(--bui-space-12); + } + + .xl\:bui-mb-13 { + margin-bottom: var(--bui-space-13); + } + + .xl\:bui-mb-14 { + margin-bottom: var(--bui-space-14); + } + } + + .bui-my { + margin-top: var(--my); + margin-bottom: var(--my); + } + + .bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-my { + margin-top: var(--py-xs); + margin-bottom: var(--py-xs); + } + + .xs\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .xs\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .xs\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .xs\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .xs\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .xs\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .xs\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .xs\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .xs\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .xs\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .xs\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .xs\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .xs\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .xs\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .xs\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .xs\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-my { + margin-top: var(--py-sm); + margin-bottom: var(--py-sm); + } + + .sm\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .sm\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .sm\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .sm\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .sm\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .sm\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .sm\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .sm\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .sm\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .sm\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .sm\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .sm\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .sm\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .sm\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .sm\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .sm\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-my { + margin-top: var(--py-md); + margin-bottom: var(--py-md); + } + + .md\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .md\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .md\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .md\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .md\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .md\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .md\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .md\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .md\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .md\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .md\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .md\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .md\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .md\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .md\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .md\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-my { + margin-top: var(--py-lg); + margin-bottom: var(--py-lg); + } + + .lg\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .lg\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .lg\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .lg\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .lg\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .lg\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .lg\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .lg\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .lg\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .lg\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .lg\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .lg\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .lg\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .lg\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .lg\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .lg\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-my { + margin-top: var(--py-xl); + margin-bottom: var(--py-xl); + } + + .xl\:bui-my-0\.5 { + margin-top: var(--bui-space-0_5); + margin-bottom: var(--bui-space-0_5); + } + + .xl\:bui-my-1 { + margin-top: var(--bui-space-1); + margin-bottom: var(--bui-space-1); + } + + .xl\:bui-my-1\.5 { + margin-top: var(--bui-space-1_5); + margin-bottom: var(--bui-space-1_5); + } + + .xl\:bui-my-2 { + margin-top: var(--bui-space-2); + margin-bottom: var(--bui-space-2); + } + + .xl\:bui-my-3 { + margin-top: var(--bui-space-3); + margin-bottom: var(--bui-space-3); + } + + .xl\:bui-my-4 { + margin-top: var(--bui-space-4); + margin-bottom: var(--bui-space-4); + } + + .xl\:bui-my-5 { + margin-top: var(--bui-space-5); + margin-bottom: var(--bui-space-5); + } + + .xl\:bui-my-6 { + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } + + .xl\:bui-my-7 { + margin-top: var(--bui-space-7); + margin-bottom: var(--bui-space-7); + } + + .xl\:bui-my-8 { + margin-top: var(--bui-space-8); + margin-bottom: var(--bui-space-8); + } + + .xl\:bui-my-9 { + margin-top: var(--bui-space-9); + margin-bottom: var(--bui-space-9); + } + + .xl\:bui-my-10 { + margin-top: var(--bui-space-10); + margin-bottom: var(--bui-space-10); + } + + .xl\:bui-my-11 { + margin-top: var(--bui-space-11); + margin-bottom: var(--bui-space-11); + } + + .xl\:bui-my-12 { + margin-top: var(--bui-space-12); + margin-bottom: var(--bui-space-12); + } + + .xl\:bui-my-13 { + margin-top: var(--bui-space-13); + margin-bottom: var(--bui-space-13); + } + + .xl\:bui-my-14 { + margin-top: var(--bui-space-14); + margin-bottom: var(--bui-space-14); + } + } + + .bui-mx { + margin-left: var(--mx); + margin-right: var(--mx); + } + + .bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-mx { + margin-left: var(--px-xs); + margin-right: var(--px-xs); + } + + .xs\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .xs\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .xs\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .xs\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .xs\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .xs\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .xs\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .xs\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .xs\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .xs\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .xs\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .xs\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .xs\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .xs\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .xs\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .xs\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-mx { + margin-left: var(--px-sm); + margin-right: var(--px-sm); + } + + .sm\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .sm\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .sm\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .sm\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .sm\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .sm\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .sm\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .sm\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .sm\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .sm\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .sm\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .sm\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .sm\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .sm\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .sm\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .sm\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-mx { + margin-left: var(--px-md); + margin-right: var(--px-md); + } + + .md\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .md\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .md\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .md\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .md\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .md\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .md\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .md\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .md\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .md\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .md\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .md\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .md\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .md\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .md\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .md\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-mx { + margin-left: var(--px-lg); + margin-right: var(--px-lg); + } + + .lg\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .lg\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .lg\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .lg\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .lg\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .lg\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .lg\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .lg\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .lg\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .lg\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .lg\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .lg\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .lg\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .lg\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .lg\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .lg\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-mx { + margin-left: var(--px-xl); + margin-right: var(--px-xl); + } + + .xl\:bui-mx-0\.5 { + margin-left: var(--bui-space-0_5); + margin-right: var(--bui-space-0_5); + } + + .xl\:bui-mx-1 { + margin-left: var(--bui-space-1); + margin-right: var(--bui-space-1); + } + + .xl\:bui-mx-1\.5 { + margin-left: var(--bui-space-1_5); + margin-right: var(--bui-space-1_5); + } + + .xl\:bui-mx-2 { + margin-left: var(--bui-space-2); + margin-right: var(--bui-space-2); + } + + .xl\:bui-mx-3 { + margin-left: var(--bui-space-3); + margin-right: var(--bui-space-3); + } + + .xl\:bui-mx-4 { + margin-left: var(--bui-space-4); + margin-right: var(--bui-space-4); + } + + .xl\:bui-mx-5 { + margin-left: var(--bui-space-5); + margin-right: var(--bui-space-5); + } + + .xl\:bui-mx-6 { + margin-left: var(--bui-space-6); + margin-right: var(--bui-space-6); + } + + .xl\:bui-mx-7 { + margin-left: var(--bui-space-7); + margin-right: var(--bui-space-7); + } + + .xl\:bui-mx-8 { + margin-left: var(--bui-space-8); + margin-right: var(--bui-space-8); + } + + .xl\:bui-mx-9 { + margin-left: var(--bui-space-9); + margin-right: var(--bui-space-9); + } + + .xl\:bui-mx-10 { + margin-left: var(--bui-space-10); + margin-right: var(--bui-space-10); + } + + .xl\:bui-mx-11 { + margin-left: var(--bui-space-11); + margin-right: var(--bui-space-11); + } + + .xl\:bui-mx-12 { + margin-left: var(--bui-space-12); + margin-right: var(--bui-space-12); + } + + .xl\:bui-mx-13 { + margin-left: var(--bui-space-13); + margin-right: var(--bui-space-13); + } + + .xl\:bui-mx-14 { + margin-left: var(--bui-space-14); + margin-right: var(--bui-space-14); + } + } + + .bui-display-none { display: none; } - &[disabled] { - color: var(--bui-fg-disabled); + .bui-display-inline { + display: inline; } -} -.bui-SelectItem { - width: var(--anchor-width); - padding-block: var(--bui-space-2); - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-4); - color: var(--bui-fg-primary); - border-radius: var(--bui-radius-3); - cursor: pointer; - user-select: none; - font-size: var(--bui-font-size-3); - align-items: center; - gap: var(--bui-space-1); - outline: none; - grid-template-columns: 1rem 1fr; - grid-template-areas: "icon text"; - display: grid; - position: relative; + .bui-display-inline-block { + display: inline-block; + } - &[data-focused] { - z-index: 0; - color: var(--bui-fg-primary); + .bui-display-block { + display: block; + } + + @media (width >= 640px) { + .xs\:bui-display-none { + display: none; + } + + .xs\:bui-display-inline { + display: inline; + } + + .xs\:bui-display-inline-block { + display: inline-block; + } + + .xs\:bui-display-block { + display: block; + } + } + + @media (width >= 768px) { + .sm\:bui-display-none { + display: none; + } + + .sm\:bui-display-inline { + display: inline; + } + + .sm\:bui-display-inline-block { + display: inline-block; + } + + .sm\:bui-display-block { + display: block; + } + } + + @media (width >= 1024px) { + .md\:bui-display-none { + display: none; + } + + .md\:bui-display-inline { + display: inline; + } + + .md\:bui-display-inline-block { + display: inline-block; + } + + .md\:bui-display-block { + display: block; + } + } + + @media (width >= 1280px) { + .lg\:bui-display-none { + display: none; + } + + .lg\:bui-display-inline { + display: inline; + } + + .lg\:bui-display-inline-block { + display: inline-block; + } + + .lg\:bui-display-block { + display: block; + } + } + + @media (width >= 1536px) { + .xl\:bui-display-none { + display: none; + } + + .xl\:bui-display-inline { + display: inline; + } + + .xl\:bui-display-inline-block { + display: inline-block; + } + + .xl\:bui-display-block { + display: block; + } + } + + .bui-w { + width: var(--width); + } + + .bui-min-w { + min-width: var(--min-width); + } + + .bui-max-w { + max-width: var(--max-width); + } + + @media (width >= 640px) { + .xs\:bui-w { + width: var(--width); + } + + .xs\:bui-min-w { + min-width: var(--min-width); + } + + .xs\:bui-max-w { + max-width: var(--max-width); + } + } + + @media (width >= 768px) { + .sm\:bui-w { + width: var(--width); + } + + .sm\:bui-min-w { + min-width: var(--min-width); + } + + .sm\:bui-max-w { + max-width: var(--max-width); + } + } + + @media (width >= 1024px) { + .md\:bui-w { + width: var(--width); + } + + .md\:bui-min-w { + min-width: var(--min-width); + } + + .md\:bui-max-w { + max-width: var(--max-width); + } + } + + @media (width >= 1280px) { + .lg\:bui-w { + width: var(--width); + } + + .lg\:bui-min-w { + min-width: var(--min-width); + } + + .lg\:bui-max-w { + max-width: var(--max-width); + } + } + + @media (width >= 1536px) { + .xl\:bui-w { + width: var(--width); + } + + .xl\:bui-min-w { + min-width: var(--min-width); + } + + .xl\:bui-max-w { + max-width: var(--max-width); + } + } + + .bui-h { + height: var(--height); + } + + .bui-min-h { + min-height: var(--min-height); + } + + .bui-max-h { + max-height: var(--max-height); + } + + @media (width >= 640px) { + .xs\:bui-h { + height: var(--height); + } + + .xs\:bui-min-h { + min-height: var(--min-height); + } + + .xs\:bui-max-h { + max-height: var(--max-height); + } + } + + @media (width >= 768px) { + .sm\:bui-h { + height: var(--height); + } + + .sm\:bui-min-h { + min-height: var(--min-height); + } + + .sm\:bui-max-h { + max-height: var(--max-height); + } + } + + @media (width >= 1024px) { + .md\:bui-h { + height: var(--height); + } + + .md\:bui-min-h { + min-height: var(--min-height); + } + + .md\:bui-max-h { + max-height: var(--max-height); + } + } + + @media (width >= 1280px) { + .lg\:bui-h { + height: var(--height); + } + + .lg\:bui-min-h { + min-height: var(--min-height); + } + + .lg\:bui-max-h { + max-height: var(--max-height); + } + } + + @media (width >= 1536px) { + .xl\:bui-h { + height: var(--height); + } + + .xl\:bui-min-h { + min-height: var(--min-height); + } + + .xl\:bui-max-h { + max-height: var(--max-height); + } + } + + .bui-position-absolute { + position: absolute; + } + + .bui-position-fixed { + position: fixed; + } + + .bui-position-sticky { + position: sticky; + } + + .bui-position-relative { position: relative; } - &[data-focused]:before { - content: ""; - z-index: -1; - background-color: var(--bui-bg-tint-hover); - border-radius: .25rem; - position: absolute; - inset-block: 0; - inset-inline: .25rem; + .bui-position-static { + position: static; } - &[data-disabled] { - cursor: not-allowed; - color: var(--bui-fg-disabled); - } + @media (width >= 640px) { + .xs\:bui-position-absolute { + position: absolute; + } - &[data-selected] .bui-SelectItemIndicator { - opacity: 1; - } -} + .xs\:bui-position-fixed { + position: fixed; + } -.bui-SelectItemIndicator { - opacity: 0; - grid-area: icon; - justify-content: center; - align-items: center; - transition: opacity .2s ease-in-out; - display: flex; -} + .xs\:bui-position-sticky { + position: sticky; + } -.bui-SelectItemLabel { - flex: 1; - grid-area: text; -} + .xs\:bui-position-relative { + position: relative; + } -.bui-Switch { - align-items: center; - gap: var(--bui-space-3); - font-size: var(--bui-font-size-3); - color: var(--bui-fg-primary); - cursor: pointer; - display: flex; - position: relative; - - &[data-pressed] .bui-SwitchIndicator { - &:before { - background: var(--bui-fg-solid); + .xs\:bui-position-static { + position: static; } } - &[data-selected] { - & .bui-SwitchIndicator { - background: var(--bui-bg-solid); - - &:before { - background: var(--bui-fg-solid); - transform: translateX(100%); - } + @media (width >= 768px) { + .sm\:bui-position-absolute { + position: absolute; } - &[data-pressed] { - & .indicator { - background: var(--bui-gray-3); - } + .sm\:bui-position-fixed { + position: fixed; + } + + .sm\:bui-position-sticky { + position: sticky; + } + + .sm\:bui-position-relative { + position: relative; + } + + .sm\:bui-position-static { + position: static; } } - &[data-focus-visible] .bui-SwitchIndicator { - outline-offset: 2px; - outline: 2px solid; + @media (width >= 1024px) { + .md\:bui-position-absolute { + position: absolute; + } + + .md\:bui-position-fixed { + position: fixed; + } + + .md\:bui-position-sticky { + position: sticky; + } + + .md\:bui-position-relative { + position: relative; + } + + .md\:bui-position-static { + position: static; + } + } + + @media (width >= 1280px) { + .lg\:bui-position-absolute { + position: absolute; + } + + .lg\:bui-position-fixed { + position: fixed; + } + + .lg\:bui-position-sticky { + position: sticky; + } + + .lg\:bui-position-relative { + position: relative; + } + + .lg\:bui-position-static { + position: static; + } + } + + @media (width >= 1536px) { + .xl\:bui-position-absolute { + position: absolute; + } + + .xl\:bui-position-fixed { + position: fixed; + } + + .xl\:bui-position-sticky { + position: sticky; + } + + .xl\:bui-position-relative { + position: relative; + } + + .xl\:bui-position-static { + position: static; + } + } + + .bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + + .bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + + .bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + + .bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + + .bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + + .bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + + .bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + + .bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + + .bui-col-span-1 { + grid-column: span 1 / span 1; + } + + .bui-col-span-2 { + grid-column: span 2 / span 2; + } + + .bui-col-span-3 { + grid-column: span 3 / span 3; + } + + .bui-col-span-4 { + grid-column: span 4 / span 4; + } + + .bui-col-span-5 { + grid-column: span 5 / span 5; + } + + .bui-col-span-6 { + grid-column: span 6 / span 6; + } + + .bui-col-span-7 { + grid-column: span 7 / span 7; + } + + .bui-col-span-8 { + grid-column: span 8 / span 8; + } + + .bui-col-span-9 { + grid-column: span 9 / span 9; + } + + .bui-col-span-10 { + grid-column: span 10 / span 10; + } + + .bui-col-span-11 { + grid-column: span 11 / span 11; + } + + .bui-col-span-12 { + grid-column: span 12 / span 12; + } + + .bui-col-span-auto { + grid-column: span auto / span auto; + } + + .bui-col-start-1 { + grid-column-start: 1; + } + + .bui-col-start-2 { + grid-column-start: 2; + } + + .bui-col-start-3 { + grid-column-start: 3; + } + + .bui-col-start-4 { + grid-column-start: 4; + } + + .bui-col-start-5 { + grid-column-start: 5; + } + + .bui-col-start-6 { + grid-column-start: 6; + } + + .bui-col-start-7 { + grid-column-start: 7; + } + + .bui-col-start-8 { + grid-column-start: 8; + } + + .bui-col-start-9 { + grid-column-start: 9; + } + + .bui-col-start-10 { + grid-column-start: 10; + } + + .bui-col-start-11 { + grid-column-start: 11; + } + + .bui-col-start-12 { + grid-column-start: 12; + } + + .bui-col-start-13 { + grid-column-start: 13; + } + + .bui-col-start-auto { + grid-column-start: auto; + } + + .bui-col-end-1 { + grid-column-end: 1; + } + + .bui-col-end-2 { + grid-column-end: 2; + } + + .bui-col-end-3 { + grid-column-end: 3; + } + + .bui-col-end-4 { + grid-column-end: 4; + } + + .bui-col-end-5 { + grid-column-end: 5; + } + + .bui-col-end-6 { + grid-column-end: 6; + } + + .bui-col-end-7 { + grid-column-end: 7; + } + + .bui-col-end-8 { + grid-column-end: 8; + } + + .bui-col-end-9 { + grid-column-end: 9; + } + + .bui-col-end-10 { + grid-column-end: 10; + } + + .bui-col-end-11 { + grid-column-end: 11; + } + + .bui-col-end-12 { + grid-column-end: 12; + } + + .bui-col-end-13 { + grid-column-end: 13; + } + + .bui-col-end-auto { + grid-column-end: auto; + } + + .bui-row-span-1 { + grid-row: span 1 / span 1; + } + + .bui-row-span-2 { + grid-row: span 2 / span 2; + } + + .bui-row-span-3 { + grid-row: span 3 / span 3; + } + + .bui-row-span-4 { + grid-row: span 4 / span 4; + } + + .bui-row-span-5 { + grid-row: span 5 / span 5; + } + + .bui-row-span-6 { + grid-row: span 6 / span 6; + } + + .bui-row-span-7 { + grid-row: span 7 / span 7; + } + + .bui-row-span-8 { + grid-row: span 8 / span 8; + } + + .bui-row-span-9 { + grid-row: span 9 / span 9; + } + + .bui-row-span-10 { + grid-row: span 10 / span 10; + } + + .bui-row-span-11 { + grid-row: span 11 / span 11; + } + + .bui-row-span-12 { + grid-row: span 12 / span 12; + } + + .bui-row-span-auto { + grid-row: span auto / span auto; + } + + @media (width >= 640px) { + .xs\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .xs\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .xs\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .xs\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .xs\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .xs\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + + .xs\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + + .xs\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + + .xs\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + + .xs\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + + .xs\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + + .xs\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + + .xs\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + + .xs\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + + .xs\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + + .xs\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + + .xs\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + + .xs\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + + .xs\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + + .xs\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + + .xs\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + + .xs\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + + .xs\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + + .xs\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + + .xs\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + + .xs\:bui-col-span-auto { + grid-column: span auto / span auto; + } + + .xs\:bui-col-start-1 { + grid-column-start: 1; + } + + .xs\:bui-col-start-2 { + grid-column-start: 2; + } + + .xs\:bui-col-start-3 { + grid-column-start: 3; + } + + .xs\:bui-col-start-4 { + grid-column-start: 4; + } + + .xs\:bui-col-start-5 { + grid-column-start: 5; + } + + .xs\:bui-col-start-6 { + grid-column-start: 6; + } + + .xs\:bui-col-start-7 { + grid-column-start: 7; + } + + .xs\:bui-col-start-8 { + grid-column-start: 8; + } + + .xs\:bui-col-start-9 { + grid-column-start: 9; + } + + .xs\:bui-col-start-10 { + grid-column-start: 10; + } + + .xs\:bui-col-start-11 { + grid-column-start: 11; + } + + .xs\:bui-col-start-12 { + grid-column-start: 12; + } + + .xs\:bui-col-start-13 { + grid-column-start: 13; + } + + .xs\:bui-col-start-auto { + grid-column-start: auto; + } + + .xs\:bui-col-end-1 { + grid-column-end: 1; + } + + .xs\:bui-col-end-2 { + grid-column-end: 2; + } + + .xs\:bui-col-end-3 { + grid-column-end: 3; + } + + .xs\:bui-col-end-4 { + grid-column-end: 4; + } + + .xs\:bui-col-end-5 { + grid-column-end: 5; + } + + .xs\:bui-col-end-6 { + grid-column-end: 6; + } + + .xs\:bui-col-end-7 { + grid-column-end: 7; + } + + .xs\:bui-col-end-8 { + grid-column-end: 8; + } + + .xs\:bui-col-end-9 { + grid-column-end: 9; + } + + .xs\:bui-col-end-10 { + grid-column-end: 10; + } + + .xs\:bui-col-end-11 { + grid-column-end: 11; + } + + .xs\:bui-col-end-12 { + grid-column-end: 12; + } + + .xs\:bui-col-end-13 { + grid-column-end: 13; + } + + .xs\:bui-col-end-auto { + grid-column-end: auto; + } + + .xs\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + + .xs\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + + .xs\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + + .xs\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + + .xs\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + + .xs\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + + .xs\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + + .xs\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + + .xs\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + + .xs\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + + .xs\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + + .xs\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + + .xs\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + @media (width >= 768px) { + .sm\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .sm\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .sm\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .sm\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .sm\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .sm\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + + .sm\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + + .sm\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + + .sm\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + + .sm\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + + .sm\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + + .sm\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + + .sm\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + + .sm\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + + .sm\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + + .sm\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + + .sm\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + + .sm\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + + .sm\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + + .sm\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + + .sm\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + + .sm\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + + .sm\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + + .sm\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + + .sm\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + + .sm\:bui-col-span-auto { + grid-column: span auto / span auto; + } + + .sm\:bui-col-start-1 { + grid-column-start: 1; + } + + .sm\:bui-col-start-2 { + grid-column-start: 2; + } + + .sm\:bui-col-start-3 { + grid-column-start: 3; + } + + .sm\:bui-col-start-4 { + grid-column-start: 4; + } + + .sm\:bui-col-start-5 { + grid-column-start: 5; + } + + .sm\:bui-col-start-6 { + grid-column-start: 6; + } + + .sm\:bui-col-start-7 { + grid-column-start: 7; + } + + .sm\:bui-col-start-8 { + grid-column-start: 8; + } + + .sm\:bui-col-start-9 { + grid-column-start: 9; + } + + .sm\:bui-col-start-10 { + grid-column-start: 10; + } + + .sm\:bui-col-start-11 { + grid-column-start: 11; + } + + .sm\:bui-col-start-12 { + grid-column-start: 12; + } + + .sm\:bui-col-start-13 { + grid-column-start: 13; + } + + .sm\:bui-col-start-auto { + grid-column-start: auto; + } + + .sm\:bui-col-end-1 { + grid-column-end: 1; + } + + .sm\:bui-col-end-2 { + grid-column-end: 2; + } + + .sm\:bui-col-end-3 { + grid-column-end: 3; + } + + .sm\:bui-col-end-4 { + grid-column-end: 4; + } + + .sm\:bui-col-end-5 { + grid-column-end: 5; + } + + .sm\:bui-col-end-6 { + grid-column-end: 6; + } + + .sm\:bui-col-end-7 { + grid-column-end: 7; + } + + .sm\:bui-col-end-8 { + grid-column-end: 8; + } + + .sm\:bui-col-end-9 { + grid-column-end: 9; + } + + .sm\:bui-col-end-10 { + grid-column-end: 10; + } + + .sm\:bui-col-end-11 { + grid-column-end: 11; + } + + .sm\:bui-col-end-12 { + grid-column-end: 12; + } + + .sm\:bui-col-end-13 { + grid-column-end: 13; + } + + .sm\:bui-col-end-auto { + grid-column-end: auto; + } + + .sm\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + + .sm\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + + .sm\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + + .sm\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + + .sm\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + + .sm\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + + .sm\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + + .sm\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + + .sm\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + + .sm\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + + .sm\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + + .sm\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + + .sm\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + @media (width >= 1024px) { + .md\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .md\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .md\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .md\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .md\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .md\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + + .md\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + + .md\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + + .md\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + + .md\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + + .md\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + + .md\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + + .md\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + + .md\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + + .md\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + + .md\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + + .md\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + + .md\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + + .md\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + + .md\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + + .md\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + + .md\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + + .md\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + + .md\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + + .md\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + + .md\:bui-col-span-auto { + grid-column: span auto / span auto; + } + + .md\:bui-col-start-1 { + grid-column-start: 1; + } + + .md\:bui-col-start-2 { + grid-column-start: 2; + } + + .md\:bui-col-start-3 { + grid-column-start: 3; + } + + .md\:bui-col-start-4 { + grid-column-start: 4; + } + + .md\:bui-col-start-5 { + grid-column-start: 5; + } + + .md\:bui-col-start-6 { + grid-column-start: 6; + } + + .md\:bui-col-start-7 { + grid-column-start: 7; + } + + .md\:bui-col-start-8 { + grid-column-start: 8; + } + + .md\:bui-col-start-9 { + grid-column-start: 9; + } + + .md\:bui-col-start-10 { + grid-column-start: 10; + } + + .md\:bui-col-start-11 { + grid-column-start: 11; + } + + .md\:bui-col-start-12 { + grid-column-start: 12; + } + + .md\:bui-col-start-13 { + grid-column-start: 13; + } + + .md\:bui-col-start-auto { + grid-column-start: auto; + } + + .md\:bui-col-end-1 { + grid-column-end: 1; + } + + .md\:bui-col-end-2 { + grid-column-end: 2; + } + + .md\:bui-col-end-3 { + grid-column-end: 3; + } + + .md\:bui-col-end-4 { + grid-column-end: 4; + } + + .md\:bui-col-end-5 { + grid-column-end: 5; + } + + .md\:bui-col-end-6 { + grid-column-end: 6; + } + + .md\:bui-col-end-7 { + grid-column-end: 7; + } + + .md\:bui-col-end-8 { + grid-column-end: 8; + } + + .md\:bui-col-end-9 { + grid-column-end: 9; + } + + .md\:bui-col-end-10 { + grid-column-end: 10; + } + + .md\:bui-col-end-11 { + grid-column-end: 11; + } + + .md\:bui-col-end-12 { + grid-column-end: 12; + } + + .md\:bui-col-end-13 { + grid-column-end: 13; + } + + .md\:bui-col-end-auto { + grid-column-end: auto; + } + + .md\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + + .md\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + + .md\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + + .md\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + + .md\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + + .md\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + + .md\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + + .md\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + + .md\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + + .md\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + + .md\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + + .md\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + + .md\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + @media (width >= 1280px) { + .lg\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .lg\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .lg\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .lg\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .lg\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .lg\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + + .lg\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + + .lg\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + + .lg\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + + .lg\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + + .lg\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + + .lg\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + + .lg\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + + .lg\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + + .lg\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + + .lg\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + + .lg\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + + .lg\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + + .lg\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + + .lg\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + + .lg\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + + .lg\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + + .lg\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + + .lg\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + + .lg\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + + .lg\:bui-col-span-auto { + grid-column: span auto / span auto; + } + + .lg\:bui-col-start-1 { + grid-column-start: 1; + } + + .lg\:bui-col-start-2 { + grid-column-start: 2; + } + + .lg\:bui-col-start-3 { + grid-column-start: 3; + } + + .lg\:bui-col-start-4 { + grid-column-start: 4; + } + + .lg\:bui-col-start-5 { + grid-column-start: 5; + } + + .lg\:bui-col-start-6 { + grid-column-start: 6; + } + + .lg\:bui-col-start-7 { + grid-column-start: 7; + } + + .lg\:bui-col-start-8 { + grid-column-start: 8; + } + + .lg\:bui-col-start-9 { + grid-column-start: 9; + } + + .lg\:bui-col-start-10 { + grid-column-start: 10; + } + + .lg\:bui-col-start-11 { + grid-column-start: 11; + } + + .lg\:bui-col-start-12 { + grid-column-start: 12; + } + + .lg\:bui-col-start-13 { + grid-column-start: 13; + } + + .lg\:bui-col-start-auto { + grid-column-start: auto; + } + + .lg\:bui-col-end-1 { + grid-column-end: 1; + } + + .lg\:bui-col-end-2 { + grid-column-end: 2; + } + + .lg\:bui-col-end-3 { + grid-column-end: 3; + } + + .lg\:bui-col-end-4 { + grid-column-end: 4; + } + + .lg\:bui-col-end-5 { + grid-column-end: 5; + } + + .lg\:bui-col-end-6 { + grid-column-end: 6; + } + + .lg\:bui-col-end-7 { + grid-column-end: 7; + } + + .lg\:bui-col-end-8 { + grid-column-end: 8; + } + + .lg\:bui-col-end-9 { + grid-column-end: 9; + } + + .lg\:bui-col-end-10 { + grid-column-end: 10; + } + + .lg\:bui-col-end-11 { + grid-column-end: 11; + } + + .lg\:bui-col-end-12 { + grid-column-end: 12; + } + + .lg\:bui-col-end-13 { + grid-column-end: 13; + } + + .lg\:bui-col-end-auto { + grid-column-end: auto; + } + + .lg\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + + .lg\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + + .lg\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + + .lg\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + + .lg\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + + .lg\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + + .lg\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + + .lg\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + + .lg\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + + .lg\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + + .lg\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + + .lg\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + + .lg\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + @media (width >= 1536px) { + .xl\:bui-columns-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + + .xl\:bui-columns-2 { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + .xl\:bui-columns-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .xl\:bui-columns-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } + + .xl\:bui-columns-5 { + grid-template-columns: repeat(5, minmax(0, 1fr)); + } + + .xl\:bui-columns-6 { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + + .xl\:bui-columns-7 { + grid-template-columns: repeat(7, minmax(0, 1fr)); + } + + .xl\:bui-columns-8 { + grid-template-columns: repeat(8, minmax(0, 1fr)); + } + + .xl\:bui-columns-9 { + grid-template-columns: repeat(9, minmax(0, 1fr)); + } + + .xl\:bui-columns-10 { + grid-template-columns: repeat(10, minmax(0, 1fr)); + } + + .xl\:bui-columns-11 { + grid-template-columns: repeat(11, minmax(0, 1fr)); + } + + .xl\:bui-columns-12 { + grid-template-columns: repeat(12, minmax(0, 1fr)); + } + + .xl\:bui-columns-auto { + grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); + } + + .xl\:bui-col-span-1 { + grid-column: span 1 / span 1; + } + + .xl\:bui-col-span-2 { + grid-column: span 2 / span 2; + } + + .xl\:bui-col-span-3 { + grid-column: span 3 / span 3; + } + + .xl\:bui-col-span-4 { + grid-column: span 4 / span 4; + } + + .xl\:bui-col-span-5 { + grid-column: span 5 / span 5; + } + + .xl\:bui-col-span-6 { + grid-column: span 6 / span 6; + } + + .xl\:bui-col-span-7 { + grid-column: span 7 / span 7; + } + + .xl\:bui-col-span-8 { + grid-column: span 8 / span 8; + } + + .xl\:bui-col-span-9 { + grid-column: span 9 / span 9; + } + + .xl\:bui-col-span-10 { + grid-column: span 10 / span 10; + } + + .xl\:bui-col-span-11 { + grid-column: span 11 / span 11; + } + + .xl\:bui-col-span-12 { + grid-column: span 12 / span 12; + } + + .xl\:bui-col-span-auto { + grid-column: span auto / span auto; + } + + .xl\:bui-col-start-1 { + grid-column-start: 1; + } + + .xl\:bui-col-start-2 { + grid-column-start: 2; + } + + .xl\:bui-col-start-3 { + grid-column-start: 3; + } + + .xl\:bui-col-start-4 { + grid-column-start: 4; + } + + .xl\:bui-col-start-5 { + grid-column-start: 5; + } + + .xl\:bui-col-start-6 { + grid-column-start: 6; + } + + .xl\:bui-col-start-7 { + grid-column-start: 7; + } + + .xl\:bui-col-start-8 { + grid-column-start: 8; + } + + .xl\:bui-col-start-9 { + grid-column-start: 9; + } + + .xl\:bui-col-start-10 { + grid-column-start: 10; + } + + .xl\:bui-col-start-11 { + grid-column-start: 11; + } + + .xl\:bui-col-start-12 { + grid-column-start: 12; + } + + .xl\:bui-col-start-13 { + grid-column-start: 13; + } + + .xl\:bui-col-start-auto { + grid-column-start: auto; + } + + .xl\:bui-col-end-1 { + grid-column-end: 1; + } + + .xl\:bui-col-end-2 { + grid-column-end: 2; + } + + .xl\:bui-col-end-3 { + grid-column-end: 3; + } + + .xl\:bui-col-end-4 { + grid-column-end: 4; + } + + .xl\:bui-col-end-5 { + grid-column-end: 5; + } + + .xl\:bui-col-end-6 { + grid-column-end: 6; + } + + .xl\:bui-col-end-7 { + grid-column-end: 7; + } + + .xl\:bui-col-end-8 { + grid-column-end: 8; + } + + .xl\:bui-col-end-9 { + grid-column-end: 9; + } + + .xl\:bui-col-end-10 { + grid-column-end: 10; + } + + .xl\:bui-col-end-11 { + grid-column-end: 11; + } + + .xl\:bui-col-end-12 { + grid-column-end: 12; + } + + .xl\:bui-col-end-13 { + grid-column-end: 13; + } + + .xl\:bui-col-end-auto { + grid-column-end: auto; + } + + .xl\:bui-row-span-1 { + grid-row: span 1 / span 1; + } + + .xl\:bui-row-span-2 { + grid-row: span 2 / span 2; + } + + .xl\:bui-row-span-3 { + grid-row: span 3 / span 3; + } + + .xl\:bui-row-span-4 { + grid-row: span 4 / span 4; + } + + .xl\:bui-row-span-5 { + grid-row: span 5 / span 5; + } + + .xl\:bui-row-span-6 { + grid-row: span 6 / span 6; + } + + .xl\:bui-row-span-7 { + grid-row: span 7 / span 7; + } + + .xl\:bui-row-span-8 { + grid-row: span 8 / span 8; + } + + .xl\:bui-row-span-9 { + grid-row: span 9 / span 9; + } + + .xl\:bui-row-span-10 { + grid-row: span 10 / span 10; + } + + .xl\:bui-row-span-11 { + grid-row: span 11 / span 11; + } + + .xl\:bui-row-span-12 { + grid-row: span 12 / span 12; + } + + .xl\:bui-row-span-auto { + grid-row: span auto / span auto; + } + } + + .bui-gap { + gap: var(--gap); + } + + .bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .bui-gap-1 { + gap: var(--bui-space-1); + } + + .bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .bui-gap-2 { + gap: var(--bui-space-2); + } + + .bui-gap-3 { + gap: var(--bui-space-3); + } + + .bui-gap-4 { + gap: var(--bui-space-4); + } + + .bui-gap-5 { + gap: var(--bui-space-5); + } + + .bui-gap-6 { + gap: var(--bui-space-6); + } + + .bui-gap-7 { + gap: var(--bui-space-7); + } + + .bui-gap-8 { + gap: var(--bui-space-8); + } + + .bui-gap-9 { + gap: var(--bui-space-9); + } + + .bui-gap-10 { + gap: var(--bui-space-10); + } + + .bui-gap-11 { + gap: var(--bui-space-11); + } + + .bui-gap-12 { + gap: var(--bui-space-12); + } + + .bui-gap-13 { + gap: var(--bui-space-13); + } + + .bui-gap-14 { + gap: var(--bui-space-14); + } + + @media (width >= 640px) { + .xs\:bui-gap { + gap: var(--gap-xs); + } + + .xs\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .xs\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .xs\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .xs\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .xs\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .xs\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .xs\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .xs\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .xs\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .xs\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .xs\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .xs\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .xs\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .xs\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .xs\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .xs\:bui-gap-14 { + gap: var(--bui-space-14); + } + } + + @media (width >= 768px) { + .sm\:bui-gap { + gap: var(--gap-sm); + } + + .sm\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .sm\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .sm\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .sm\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .sm\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .sm\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .sm\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .sm\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .sm\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .sm\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .sm\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .sm\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .sm\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .sm\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .sm\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .sm\:bui-gap-14 { + gap: var(--bui-space-14); + } + } + + @media (width >= 1024px) { + .md\:bui-gap { + gap: var(--gap-md); + } + + .md\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .md\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .md\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .md\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .md\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .md\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .md\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .md\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .md\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .md\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .md\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .md\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .md\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .md\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .md\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .md\:bui-gap-14 { + gap: var(--bui-space-14); + } + } + + @media (width >= 1280px) { + .lg\:bui-gap { + gap: var(--gap-lg); + } + + .lg\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .lg\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .lg\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .lg\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .lg\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .lg\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .lg\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .lg\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .lg\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .lg\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .lg\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .lg\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .lg\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .lg\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .lg\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .lg\:bui-gap-14 { + gap: var(--bui-space-14); + } + } + + @media (width >= 1536px) { + .xl\:bui-gap { + gap: var(--gap-xl); + } + + .xl\:bui-gap-0\.5 { + gap: var(--bui-space-0_5); + } + + .xl\:bui-gap-1 { + gap: var(--bui-space-1); + } + + .xl\:bui-gap-1\.5 { + gap: var(--bui-space-1_5); + } + + .xl\:bui-gap-2 { + gap: var(--bui-space-2); + } + + .xl\:bui-gap-3 { + gap: var(--bui-space-3); + } + + .xl\:bui-gap-4 { + gap: var(--bui-space-4); + } + + .xl\:bui-gap-5 { + gap: var(--bui-space-5); + } + + .xl\:bui-gap-6 { + gap: var(--bui-space-6); + } + + .xl\:bui-gap-7 { + gap: var(--bui-space-7); + } + + .xl\:bui-gap-8 { + gap: var(--bui-space-8); + } + + .xl\:bui-gap-9 { + gap: var(--bui-space-9); + } + + .xl\:bui-gap-10 { + gap: var(--bui-space-10); + } + + .xl\:bui-gap-11 { + gap: var(--bui-space-11); + } + + .xl\:bui-gap-12 { + gap: var(--bui-space-12); + } + + .xl\:bui-gap-13 { + gap: var(--bui-space-13); + } + + .xl\:bui-gap-14 { + gap: var(--bui-space-14); + } + } + + .bui-align-start { + align-items: start; + } + + .bui-align-center { + align-items: center; + } + + .bui-align-end { + align-items: end; + } + + .bui-align-baseline { + align-items: baseline; + } + + .bui-align-stretch { + align-items: stretch; + } + + .bui-jc-start { + justify-content: start; + } + + .bui-jc-center { + justify-content: center; + } + + .bui-jc-end { + justify-content: end; + } + + .bui-jc-between { + justify-content: space-between; + } + + .bui-fd-row { + flex-direction: row; + } + + .bui-fd-column { + flex-direction: column; + } + + .bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .bui-fd-column-reverse { + flex-direction: column-reverse; + } + + @media (width >= 640px) { + .xs\:bui-align-start { + align-items: start; + } + + .xs\:bui-align-center { + align-items: center; + } + + .xs\:bui-align-end { + align-items: end; + } + + .xs\:bui-align-stretch { + align-items: stretch; + } + + .xs\:bui-jc-start { + justify-content: start; + } + + .xs\:bui-jc-center { + justify-content: center; + } + + .xs\:bui-jc-end { + justify-content: end; + } + + .xs\:bui-jc-between { + justify-content: space-between; + } + + .xs\:bui-fd-row { + flex-direction: row; + } + + .xs\:bui-fd-column { + flex-direction: column; + } + + .xs\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .xs\:bui-fd-column-reverse { + flex-direction: column-reverse; + } + } + + @media (width >= 768px) { + .sm\:bui-align-start { + align-items: start; + } + + .sm\:bui-align-center { + align-items: center; + } + + .sm\:bui-align-end { + align-items: end; + } + + .sm\:bui-align-stretch { + align-items: stretch; + } + + .sm\:bui-jc-start { + justify-content: start; + } + + .sm\:bui-jc-center { + justify-content: center; + } + + .sm\:bui-jc-end { + justify-content: end; + } + + .sm\:bui-jc-between { + justify-content: space-between; + } + + .sm\:bui-fd-row { + flex-direction: row; + } + + .sm\:bui-fd-column { + flex-direction: column; + } + + .sm\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .sm\:bui-fd-column-reverse { + flex-direction: column-reverse; + } + } + + @media (width >= 1024px) { + .md\:bui-align-start { + align-items: start; + } + + .md\:bui-align-center { + align-items: center; + } + + .md\:bui-align-end { + align-items: end; + } + + .md\:bui-align-stretch { + align-items: stretch; + } + + .md\:bui-jc-start { + justify-content: start; + } + + .md\:bui-jc-center { + justify-content: center; + } + + .md\:bui-jc-end { + justify-content: end; + } + + .md\:bui-jc-between { + justify-content: space-between; + } + + .md\:bui-fd-row { + flex-direction: row; + } + + .md\:bui-fd-column { + flex-direction: column; + } + + .md\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .md\:bui-fd-column-reverse { + flex-direction: column-reverse; + } + } + + @media (width >= 1280px) { + .lg\:bui-align-start { + align-items: start; + } + + .lg\:bui-align-center { + align-items: center; + } + + .lg\:bui-align-end { + align-items: end; + } + + .lg\:bui-align-stretch { + align-items: stretch; + } + + .lg\:bui-jc-start { + justify-content: start; + } + + .lg\:bui-jc-center { + justify-content: center; + } + + .lg\:bui-jc-end { + justify-content: end; + } + + .lg\:bui-jc-between { + justify-content: space-between; + } + + .lg\:bui-fd-row { + flex-direction: row; + } + + .lg\:bui-fd-column { + flex-direction: column; + } + + .lg\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .lg\:bui-fd-column-reverse { + flex-direction: column-reverse; + } + } + + @media (width >= 1536px) { + .xl\:bui-align-start { + align-items: start; + } + + .xl\:bui-align-center { + align-items: center; + } + + .xl\:bui-align-end { + align-items: end; + } + + .xl\:bui-align-stretch { + align-items: stretch; + } + + .xl\:bui-jc-start { + justify-content: start; + } + + .xl\:bui-jc-center { + justify-content: center; + } + + .xl\:bui-jc-end { + justify-content: end; + } + + .xl\:bui-jc-between { + justify-content: space-between; + } + + .xl\:bui-fd-row { + flex-direction: row; + } + + .xl\:bui-fd-column { + flex-direction: column; + } + + .xl\:bui-fd-row-reverse { + flex-direction: row-reverse; + } + + .xl\:bui-fd-column-reverse { + flex-direction: column-reverse; + } } } -.bui-SwitchIndicator { - background: var(--bui-gray-3); - border: 2px; - border-radius: 1.143rem; - width: 2rem; - height: 1.143rem; - transition: all .2s; - - &:before { - content: ""; - background: var(--bui-fg-solid); - border-radius: 16px; - width: .857rem; - height: .857rem; - margin: .143rem; - transition: all .2s; - display: block; - } -} \ No newline at end of file +@layer legacy; diff --git a/packages/ui/src/css/core.css b/packages/ui/src/css/core.css index a8ab7cfc6b..b24e8bad73 100644 --- a/packages/ui/src/css/core.css +++ b/packages/ui/src/css/core.css @@ -14,191 +14,19 @@ * limitations under the License. */ -/* Normalize */ -@import './normalize.css'; -@import './utilities.css'; +@layer base { + :where(a) { + color: inherit; + text-decoration: none; + } -/* Global reset */ -:where(a) { - color: inherit; - text-decoration: none; -} + @keyframes pulse { + 50% { + opacity: 0.5; + } + } -@keyframes pulse { - 50% { - opacity: 0.5; + body { + background-color: var(--bui-bg); } } - -body { - background-color: var(--bui-bg); -} - -/* Light theme tokens */ -:root { - /* Font families */ - --bui-font-regular: system-ui; - --bui-font-monospace: ui-monospace, 'Menlo', 'Monaco', 'Consolas', - 'Liberation Mono', 'Courier New', monospace; - - /* Font weights */ - --bui-font-weight-regular: 400; - --bui-font-weight-bold: 600; - - /* Font sizes */ - --bui-font-size-1: 0.625rem; /* 10px */ - --bui-font-size-2: 0.75rem; /* 12px */ - --bui-font-size-3: 0.875rem; /* 14px */ - --bui-font-size-4: 1rem; /* 16px */ - --bui-font-size-5: 1.25rem; /* 20px */ - --bui-font-size-6: 1.5rem; /* 24px */ - --bui-font-size-7: 2rem; /* 32px */ - --bui-font-size-8: 3rem; /* 48px */ - --bui-font-size-9: 4rem; /* 64px */ - --bui-font-size-10: 5.75rem; /* 92px */ - - /* Spacing */ - --bui-space: 0.25rem; /* This is the spacing multiplier */ - --bui-space-0_5: calc(var(--bui-space) * 0.5); /* 2px */ - --bui-space-1: var(--bui-space); /* 4px */ - --bui-space-1_5: calc(var(--bui-space) * 1.5); /* 6px */ - --bui-space-2: calc(var(--bui-space) * 2); /* 8px */ - --bui-space-3: calc(var(--bui-space) * 3); /* 12px */ - --bui-space-4: calc(var(--bui-space) * 4); /* 16px */ - --bui-space-5: calc(var(--bui-space) * 5); /* 20px */ - --bui-space-6: calc(var(--bui-space) * 6); /* 24px */ - --bui-space-7: calc(var(--bui-space) * 7); /* 28px */ - --bui-space-8: calc(var(--bui-space) * 8); /* 32px */ - --bui-space-9: calc(var(--bui-space) * 9); /* 36px */ - --bui-space-10: calc(var(--bui-space) * 10); /* 40px */ - --bui-space-11: calc(var(--bui-space) * 11); /* 44px */ - --bui-space-12: calc(var(--bui-space) * 12); /* 48px */ - --bui-space-13: calc(var(--bui-space) * 13); /* 52px */ - --bui-space-14: calc(var(--bui-space) * 14); /* 56px */ - - /* Radius */ - --bui-radius-1: calc(0.125rem); - --bui-radius-2: calc(0.25rem); - --bui-radius-3: calc(0.5rem); - --bui-radius-4: calc(0.75rem); - --bui-radius-5: calc(1rem); - --bui-radius-6: calc(1.25rem); - --bui-radius-full: 9999px; - - /* Base Colors */ - --bui-black: #000000; - --bui-white: #ffffff; - - /* Gray scale */ - --bui-gray-1: #f8f8f8; - --bui-gray-2: #ececec; - --bui-gray-3: #d9d9d9; - --bui-gray-4: #c1c1c1; - --bui-gray-5: #9e9e9e; - --bui-gray-6: #8c8c8c; - --bui-gray-7: #757575; - --bui-gray-8: #595959; - - /* Background Colors */ - --bui-bg: var(--bui-gray-1); - --bui-bg-surface-1: var(--bui-white); - --bui-bg-surface-2: var(--bui-gray-2); - --bui-bg-solid: #1f5493; - --bui-bg-solid-hover: #163a66; - --bui-bg-solid-pressed: #0f2b4e; - --bui-bg-solid-disabled: #ebebeb; - --bui-bg-tint: transparent; - --bui-bg-tint-hover: rgba(31, 84, 147, 0.4); - --bui-bg-tint-pressed: rgba(31, 84, 147, 0.6); - --bui-bg-tint-disabled: #ebebeb; - --bui-bg-danger: #feebe7; - --bui-bg-warning: #fff2b2; - --bui-bg-success: #e6f6eb; - - /* Foreground Colors */ - --bui-fg-primary: var(--bui-black); - --bui-fg-secondary: var(--bui-gray-7); - --bui-fg-link: #1f5493; - --bui-fg-link-hover: #1f2d5c; - --bui-fg-disabled: #9e9e9e; - --bui-fg-solid: var(--bui-white); - --bui-fg-solid-disabled: #9c9c9c; - --bui-fg-tint: #1f5493; - --bui-fg-tint-disabled: var(--bui-gray-5); - --bui-fg-danger: #e22b2b; - --bui-fg-warning: #e36d05; - --bui-fg-success: #1db954; - - /* Border Colors */ - --bui-border: rgba(0, 0, 0, 0.1); - --bui-border-hover: rgba(0, 0, 0, 0.2); - --bui-border-pressed: rgba(0, 0, 0, 0.4); - --bui-border-disabled: rgba(0, 0, 0, 0.1); - --bui-border-danger: #f87a7a; - --bui-border-warning: #e36d05; - --bui-border-success: #53db83; - - /* Special Colors */ - --bui-ring: #1f5493; - --bui-scrollbar: #a0a0a03b; - --bui-scrollbar-thumb: #a0a0a0; - - --bui-animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; -} - -/* Dark theme tokens */ -[data-theme-mode='dark'] { - /* Gray scale */ - --bui-gray-1: #191919; - --bui-gray-2: #242424; - --bui-gray-3: #373737; - --bui-gray-4: #464646; - --bui-gray-5: #575757; - --bui-gray-6: #7b7b7b; - --bui-gray-7: #9e9e9e; - --bui-gray-8: #b4b4b4; - - /* Background Colors */ - --bui-bg: #333333; - --bui-bg-surface-1: #424242; - --bui-bg-surface-2: var(--bui-gray-2); - --bui-bg-solid: #9cc9ff; - --bui-bg-solid-hover: #83b9fd; - --bui-bg-solid-pressed: #83b9fd; - --bui-bg-solid-disabled: #222222; - --bui-bg-tint: transparent; - --bui-bg-tint-hover: rgba(156, 201, 255, 0.12); - --bui-bg-tint-pressed: rgba(156, 201, 255, 0.16); - --bui-bg-tint-disabled: transparent; - --bui-bg-danger: #3b1219; - --bui-bg-warning: #302008; - --bui-bg-success: #132d21; - - /* Foreground Colors */ - --bui-fg-primary: var(--bui-white); - --bui-fg-secondary: var(--bui-gray-7); - --bui-fg-link: #9cc9ff; - --bui-fg-link-hover: #7eb5f7; - --bui-fg-disabled: var(--bui-gray-7); - --bui-fg-solid: #101821; - --bui-fg-solid-disabled: var(--bui-gray-5); - --bui-fg-tint: #9cc9ff; - --bui-fg-tint-disabled: var(--bui-gray-5); - --bui-fg-danger: #e22b2b; - --bui-fg-warning: #e36d05; - --bui-fg-success: #1db954; - - /* Border Colors */ - --bui-border: rgba(255, 255, 255, 0.12); - --bui-border-hover: rgba(255, 255, 255, 0.4); - --bui-border-pressed: rgba(255, 255, 255, 0.5); - --bui-border-disabled: rgba(255, 255, 255, 0.2); - --bui-border-danger: #f87a7a; - --bui-border-warning: #e36d05; - --bui-border-success: #53db83; - - /* Special Colors */ - --bui-ring: #1f5493; - --bui-scrollbar: #3636363a; - --bui-scrollbar-thumb: #575757; -} From f222a2eab999408abdff5c6146b0ae5826e4ad10 Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Tue, 23 Sep 2025 21:57:10 +0300 Subject: [PATCH 131/244] fix: distributed actions visibility in scaffolder depending on the plugin startup order, some distributed actions might not be available when the scaffolder backend starts. this was mentioned in the comment that is now removed. while this might change in the future, this would patch the current way the distributed actions are fetched. related #31213 and #31207 closes #31187 Signed-off-by: Hellgren Heikki --- .changeset/loud-windows-give.md | 8 + app-config.yaml | 4 +- .../actions/TemplateActionRegistry.test.ts | 278 ++++++++++++++++++ .../actions/TemplateActionRegistry.ts | 79 ++++- .../src/scaffolder/actions/index.ts | 5 +- .../dryrun/DecoratedActionsRegistry.ts | 33 ++- .../src/scaffolder/dryrun/createDryRunner.ts | 2 +- .../tasks/NunjucksWorkflowRunner.test.ts | 14 +- .../tasks/NunjucksWorkflowRunner.ts | 6 +- .../src/scaffolder/tasks/TaskWorker.ts | 2 +- .../scaffolder-backend/src/service/router.ts | 91 ++---- 11 files changed, 438 insertions(+), 84 deletions(-) create mode 100644 .changeset/loud-windows-give.md create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.test.ts diff --git a/.changeset/loud-windows-give.md b/.changeset/loud-windows-give.md new file mode 100644 index 0000000000..7e9ea6881d --- /dev/null +++ b/.changeset/loud-windows-give.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Fixed distributed actions not being visible in the scaffolder template actions. + +Depending on the plugin startup order, some of the distributed actions were not being registered correctly, +causing them to be invisible in the scaffolder template actions list. diff --git a/app-config.yaml b/app-config.yaml index eacf9a96aa..b45255d26c 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -65,7 +65,9 @@ backend: - host: example.com - host: '*.mozilla.org' # workingDirectory: /tmp # Use this to configure a working directory for the scaffolder, defaults to the OS temp-dir - + actions: + pluginSources: + - catalog # See README.md in the proxy-backend plugin for information on the configuration format proxy: endpoints: diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.test.ts new file mode 100644 index 0000000000..f3a3b15ec9 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.test.ts @@ -0,0 +1,278 @@ +/* + * Copyright 2021 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 { ConflictError, NotFoundError } from '@backstage/errors'; +import { createTemplateAction } from '@backstage/plugin-scaffolder-node'; +import { DefaultTemplateActionRegistry } from './TemplateActionRegistry'; +import { mockCredentials, mockServices } from '@backstage/backend-test-utils'; +import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha'; + +describe('DefaultTemplateActionRegistry', () => { + let registry: DefaultTemplateActionRegistry; + let mockActionsService: ReturnType; + let mockAuthService: ReturnType; + let mockLogger: ReturnType; + + beforeEach(() => { + mockActionsService = actionsRegistryServiceMock(); + mockAuthService = mockServices.auth(); + mockLogger = mockServices.logger.mock(); + + registry = new DefaultTemplateActionRegistry( + mockActionsService, + mockAuthService, + mockLogger, + ); + }); + + describe('register', () => { + it('should register a template action successfully', () => { + const action = createTemplateAction({ + id: 'test-action', + description: 'Test action', + handler: jest.fn(), + }); + + expect(() => registry.register(action)).not.toThrow(); + }); + + it('should throw ConflictError when registering action with duplicate ID', () => { + const action1 = createTemplateAction({ + id: 'duplicate-action', + description: 'First action', + handler: jest.fn(), + }); + + const action2 = createTemplateAction({ + id: 'duplicate-action', + description: 'Second action', + handler: jest.fn(), + }); + + registry.register(action1); + + expect(() => registry.register(action2)).toThrow(ConflictError); + expect(() => registry.register(action2)).toThrow( + "Template action with ID 'duplicate-action' has already been registered", + ); + }); + }); + + describe('get', () => { + it('should return a registered action', async () => { + const action = createTemplateAction({ + id: 'test-action', + description: 'Test action', + handler: jest.fn(), + }); + + registry.register(action); + const result = await registry.get('test-action'); + + expect(result).toBe(action); + }); + + it('should return action from ActionsService', async () => { + mockActionsService.register({ + name: 'service-action', + title: 'Service Action', + description: 'Service action', + schema: { + input: z => z.object({}), + output: z => z.object({}), + }, + attributes: { + readOnly: true, + destructive: false, + }, + action: async () => ({ output: {} }), + }); + + const result = await registry.get('test:service-action'); + + expect(result.id).toBe('test:service-action'); + expect(result.description).toBe('Service action'); + expect(result.supportsDryRun).toBe(true); + }); + + it('should throw NotFoundError when action is not found', async () => { + await expect(registry.get('non-existent-action')).rejects.toThrow( + NotFoundError, + ); + await expect(registry.get('non-existent-action')).rejects.toThrow( + "Template action with ID 'non-existent-action' is not registered", + ); + }); + + it('should use own service credentials when getting action', async () => { + const spy = jest.spyOn(mockActionsService, 'list'); + + await expect(registry.get('non-existent')).rejects.toThrow(); + + expect(spy).toHaveBeenCalledWith({ + credentials: await mockAuthService.getOwnServiceCredentials(), + }); + }); + }); + + describe('list', () => { + it('should return empty map when no actions are registered', async () => { + const result = await registry.list(); + + expect(result).toBeInstanceOf(Map); + expect(result.size).toBe(0); + }); + + it('should return all registered actions', async () => { + const action1 = createTemplateAction({ + id: 'action-1', + description: 'First action', + handler: jest.fn(), + }); + + const action2 = createTemplateAction({ + id: 'action-2', + description: 'Second action', + handler: jest.fn(), + }); + + registry.register(action1); + registry.register(action2); + + const result = await registry.list(); + + expect(result.size).toBe(2); + expect(result.get('action-1')).toBe(action1); + expect(result.get('action-2')).toBe(action2); + }); + + it('should include actions from ActionsService', async () => { + mockActionsService.register({ + name: 'service-action', + title: 'Service Action', + description: 'Service action', + schema: { + input: z => z.object({}), + output: z => z.object({}), + }, + attributes: { + readOnly: true, + destructive: false, + }, + action: async () => ({ output: {} }), + }); + + const result = await registry.list(); + + expect(result.size).toBe(1); + const action = result.get('test:service-action'); + expect(action).toBeDefined(); + expect(action!.id).toBe('test:service-action'); + expect(action!.description).toBe('Service action'); + expect(action!.supportsDryRun).toBe(true); + }); + + it('should prioritize locally registered actions over service actions', async () => { + const localAction = createTemplateAction({ + id: 'test:same-id', + description: 'Local action', + handler: jest.fn(), + }); + + mockActionsService.register({ + name: 'same-id', + title: 'Same ID', + description: 'Service action', + schema: { + input: z => z.object({}), + output: z => z.object({}), + }, + action: async () => ({ output: {} }), + }); + + registry.register(localAction); + const result = await registry.list(); + + expect(result.get('test:same-id')).toBe(localAction); + expect(mockLogger.warn).toHaveBeenCalledWith( + "Template action with ID 'test:same-id' has already been registered, skipping action provided by actions service", + ); + }); + + it('should use provided credentials when listing actions', async () => { + const credentials = mockCredentials.user(); + const spy = jest.spyOn(mockActionsService, 'list'); + + await registry.list({ credentials }); + + expect(spy).toHaveBeenCalledWith({ credentials }); + }); + + it('should use own service credentials when no credentials provided', async () => { + const spy = jest.spyOn(mockActionsService, 'list'); + + await registry.list(); + + expect(spy).toHaveBeenCalledWith({ + credentials: await mockAuthService.getOwnServiceCredentials(), + }); + }); + + it('should set supportsDryRun to false for destructive actions', async () => { + mockActionsService.register({ + name: 'destructive-action', + title: 'Destructive Action', + description: 'Destructive action', + schema: { + input: z => z.object({}), + output: z => z.object({}), + }, + attributes: { + readOnly: false, + destructive: true, + }, + action: async () => ({ output: {} }), + }); + + const result = await registry.list(); + const action = result.get('test:destructive-action'); + + expect(action!.supportsDryRun).toBe(false); + }); + + it('should set supportsDryRun to false for non-readonly actions', async () => { + mockActionsService.register({ + name: 'non-readonly-action', + title: 'Non-readonly Action', + description: 'Non-readonly action', + schema: { + input: z => z.object({}), + output: z => z.object({}), + }, + attributes: { + readOnly: false, + destructive: false, + }, + action: async () => ({ output: {} }), + }); + + const result = await registry.list(); + const action = result.get('test:non-readonly-action'); + + expect(action!.supportsDryRun).toBe(false); + }); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts index d6d7685a21..7bcf120646 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts @@ -16,13 +16,39 @@ import { ConflictError, NotFoundError } from '@backstage/errors'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; +import { ActionsService } from '@backstage/backend-plugin-api/alpha'; +import { + AuthService, + BackstageCredentials, + LoggerService, +} from '@backstage/backend-plugin-api'; +import { isPlainObject } from 'lodash'; +import { Schema } from 'jsonschema'; +import { JsonObject } from '@backstage/types'; + +/** + * @internal + */ +export interface TemplateActionRegistry { + register(action: TemplateAction): void; + get(actionId: string): Promise>; + list(options?: { + credentials?: BackstageCredentials; + }): Promise>>; +} /** * Registry of all registered template actions. */ -export class TemplateActionRegistry { +export class DefaultTemplateActionRegistry implements TemplateActionRegistry { private readonly actions = new Map(); + constructor( + private readonly actionsRegistry: ActionsService, + private readonly auth: AuthService, + private readonly logger: LoggerService, + ) {} + register(action: TemplateAction) { if (this.actions.has(action.id)) { throw new ConflictError( @@ -33,8 +59,8 @@ export class TemplateActionRegistry { this.actions.set(action.id, action); } - get(actionId: string): TemplateAction { - const action = this.actions.get(actionId); + async get(actionId: string): Promise> { + const action = (await this.list()).get(actionId); if (!action) { throw new NotFoundError( `Template action with ID '${actionId}' is not registered. See https://backstage.io/docs/features/software-templates/builtin-actions/ on how to add a new action module.`, @@ -43,7 +69,50 @@ export class TemplateActionRegistry { return action; } - list(): TemplateAction[] { - return [...this.actions.values()]; + async list(options?: { + credentials?: BackstageCredentials; + }): Promise>> { + const ret = new Map(this.actions); + + const { actions } = await this.actionsRegistry.list({ + credentials: + options?.credentials ?? (await this.auth.getOwnServiceCredentials()), + }); + + for (const action of actions) { + if (ret.has(action.id)) { + this.logger.warn( + `Template action with ID '${action.id}' has already been registered, skipping action provided by actions service`, + ); + continue; + } + + ret.set(action.id, { + id: action.id, + description: action.description, + examples: [], + supportsDryRun: + action.attributes?.readOnly === true && + action.attributes?.destructive === false, + handler: async ctx => { + const { output } = await this.actionsRegistry.invoke({ + id: action.id, + input: ctx.input, + credentials: await ctx.getInitiatorCredentials(), + }); + + if (isPlainObject(output)) { + for (const [key, value] of Object.entries(output as JsonObject)) { + ctx.output(key as keyof typeof output, value); + } + } + }, + schema: { + input: action.schema.input as Schema, + output: action.schema.output as Schema, + }, + }); + } + return ret; } } diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/index.ts index ad128b19b7..f6bd39397c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/index.ts @@ -16,4 +16,7 @@ export * from './builtin'; -export { TemplateActionRegistry } from './TemplateActionRegistry'; +export { + type TemplateActionRegistry, + DefaultTemplateActionRegistry, +} from './TemplateActionRegistry'; diff --git a/plugins/scaffolder-backend/src/scaffolder/dryrun/DecoratedActionsRegistry.ts b/plugins/scaffolder-backend/src/scaffolder/dryrun/DecoratedActionsRegistry.ts index 7109a6621e..b3f4b5e2cf 100644 --- a/plugins/scaffolder-backend/src/scaffolder/dryrun/DecoratedActionsRegistry.ts +++ b/plugins/scaffolder-backend/src/scaffolder/dryrun/DecoratedActionsRegistry.ts @@ -16,24 +16,43 @@ import { TemplateAction } from '@backstage/plugin-scaffolder-node'; import { TemplateActionRegistry } from '../actions'; +import { BackstageCredentials } from '@backstage/backend-plugin-api'; /** @internal */ -export class DecoratedActionsRegistry extends TemplateActionRegistry { +export class DecoratedActionsRegistry implements TemplateActionRegistry { + private readonly innerActions: Map = new Map(); + constructor( private readonly innerRegistry: TemplateActionRegistry, extraActions: Array, ) { - super(); for (const action of extraActions) { - this.register(action); + this.innerActions.set(action.id, action); } } - get(actionId: string): TemplateAction { + async get(actionId: string): Promise { try { - return super.get(actionId); - } catch { - return this.innerRegistry.get(actionId); + return await this.innerRegistry.get(actionId); + } catch (e) { + if (!this.innerActions.has(actionId)) { + throw e; + } + return this.innerActions.get(actionId)!; } } + + async list(options?: { + credentials?: BackstageCredentials; + }): Promise>> { + const inner = await this.innerRegistry.list(options); + return new Map>([ + ...inner, + ...this.innerActions, + ]); + } + + register(action: TemplateAction): void { + this.innerRegistry.register(action); + } } diff --git a/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts b/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts index d384443252..43c5aea40f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/dryrun/createDryRunner.ts @@ -41,9 +41,9 @@ import fs from 'fs-extra'; import path from 'path'; import { fileURLToPath } from 'url'; import { v4 as uuid } from 'uuid'; -import { TemplateActionRegistry } from '../actions'; import { NunjucksWorkflowRunner } from '../tasks/NunjucksWorkflowRunner'; import { DecoratedActionsRegistry } from './DecoratedActionsRegistry'; +import { TemplateActionRegistry } from '../actions'; interface DryRunInput { spec: TaskSpec; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 8019bd4134..886ddda36f 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -15,15 +15,18 @@ */ import { NunjucksWorkflowRunner } from './NunjucksWorkflowRunner'; -import { TemplateActionRegistry } from '../actions'; +import { + DefaultTemplateActionRegistry, + TemplateActionRegistry, +} from '../actions'; import { ScmIntegrations } from '@backstage/integration'; import { JsonObject } from '@backstage/types'; import { ConfigReader } from '@backstage/config'; import { TaskSpec } from '@backstage/plugin-scaffolder-common'; import { createTemplateAction, - TaskSecrets, TaskContext, + TaskSecrets, } from '@backstage/plugin-scaffolder-node'; import { UserEntity } from '@backstage/catalog-model'; import { @@ -36,6 +39,7 @@ import { mockCredentials, mockServices, } from '@backstage/backend-test-utils'; +import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha'; describe('NunjucksWorkflowRunner', () => { let actionRegistry: TemplateActionRegistry; @@ -104,7 +108,11 @@ describe('NunjucksWorkflowRunner', () => { // This one is ESM-only stripAnsi = await import('strip-ansi').then(m => m.default); - actionRegistry = new TemplateActionRegistry(); + actionRegistry = new DefaultTemplateActionRegistry( + actionsRegistryServiceMock(), + mockServices.auth(), + mockServices.logger.mock(), + ); fakeActionHandler = jest.fn(); fakeTaskLog = jest.fn(); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index bcae93fb4d..d13fa58a94 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -33,7 +33,7 @@ import { SecureTemplater, SecureTemplateRenderer, } from '../../lib/templating/SecureTemplater'; -import { TemplateActionRegistry } from '../actions/TemplateActionRegistry'; +import { TemplateActionRegistry } from '../actions/TemplateActionRegistry.ts'; import { generateExampleOutput, isTruthy } from './helper'; import { TaskTrackType, WorkflowResponse, WorkflowRunner } from './types'; @@ -61,8 +61,8 @@ import { createCounterMetric, createHistogramMetric } from '../../util/metrics'; import { BackstageLoggerTransport, WinstonLogger } from './logger'; import { convertFiltersToRecord } from '../../util/templating'; import { - CheckpointState, CheckpointContext, + CheckpointState, } from '@backstage/plugin-scaffolder-node/alpha'; type NunjucksWorkflowRunnerOptions = { @@ -245,7 +245,7 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { return; } const action: TemplateAction = - this.options.actionRegistry.get(step.action); + await this.options.actionRegistry.get(step.action); const { taskLogger } = createStepLogger({ task, step, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index adfdf0b553..7b85dd1270 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -25,7 +25,7 @@ import { TemplateGlobal, } from '@backstage/plugin-scaffolder-node'; import PQueue from 'p-queue'; -import { TemplateActionRegistry } from '../actions/TemplateActionRegistry'; +import { TemplateActionRegistry } from '../actions/TemplateActionRegistry.ts'; import { NunjucksWorkflowRunner } from './NunjucksWorkflowRunner'; import { WorkflowRunner } from './types'; import { setTimeout } from 'timers/promises'; diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 2a0792346d..bcdcedb70d 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -26,7 +26,7 @@ import { resolveSafeChildPath, SchedulerService, } from '@backstage/backend-plugin-api'; -import { Schema } from 'jsonschema'; +import { validate } from 'jsonschema'; import { CompoundEntityRef, Entity, @@ -41,10 +41,10 @@ import { ScmIntegrations } from '@backstage/integration'; import { EventsService } from '@backstage/plugin-events-node'; import { - createConditionAuthorizer, - createPermissionIntegrationRouter, - createConditionTransformer, ConditionTransformer, + createConditionAuthorizer, + createConditionTransformer, + createPermissionIntegrationRouter, } from '@backstage/plugin-permission-node'; import { TaskSpec, @@ -53,11 +53,11 @@ import { } from '@backstage/plugin-scaffolder-common'; import { RESOURCE_TYPE_SCAFFOLDER_ACTION, - RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, RESOURCE_TYPE_SCAFFOLDER_TASK, + RESOURCE_TYPE_SCAFFOLDER_TEMPLATE, scaffolderActionPermissions, - scaffolderTaskPermissions, scaffolderPermissions, + scaffolderTaskPermissions, scaffolderTemplatePermissions, taskCancelPermission, taskCreatePermission, @@ -67,6 +67,7 @@ import { } from '@backstage/plugin-scaffolder-common/alpha'; import { TaskBroker, + TaskFilters, TaskStatus, TemplateAction, TemplateFilter, @@ -80,15 +81,14 @@ import { } from '@backstage/plugin-scaffolder-node/alpha'; import { HumanDuration, JsonObject } from '@backstage/types'; import express from 'express'; -import { validate } from 'jsonschema'; import { Duration } from 'luxon'; import { pathToFileURL } from 'url'; import { v4 as uuid } from 'uuid'; import { z } from 'zod'; import { DatabaseTaskStore, + DefaultTemplateActionRegistry, TaskWorker, - TemplateActionRegistry, } from '../scaffolder'; import { createDryRunner } from '../scaffolder/dryrun'; import { StorageTaskBroker } from '../scaffolder/tasks/StorageTaskBroker'; @@ -115,25 +115,22 @@ import { } from '../util/templating'; import { createDefaultFilters } from '../lib/templating/filters/createDefaultFilters'; import { - ScaffolderPermissionRuleInput, - TaskPermissionRuleInput, - isTaskPermissionRuleInput, ActionPermissionRuleInput, isActionPermissionRuleInput, + isTaskPermissionRuleInput, isTemplatePermissionRuleInput, + ScaffolderPermissionRuleInput, + TaskPermissionRuleInput, TemplatePermissionRuleInput, } from './permissions'; import { CatalogService } from '@backstage/plugin-catalog-node'; import { scaffolderActionRules, - scaffolderTemplateRules, scaffolderTaskRules, + scaffolderTemplateRules, } from './rules'; - -import { TaskFilters } from '@backstage/plugin-scaffolder-node'; import { ActionsService } from '@backstage/backend-plugin-api/alpha'; -import { isPlainObject } from 'lodash'; /** * RouterOptions @@ -272,7 +269,11 @@ export async function createRouter( taskBroker = options.taskBroker; } - const actionRegistry = new TemplateActionRegistry(); + const actionRegistry = new DefaultTemplateActionRegistry( + actionsRegistry, + auth, + logger, + ); const templateExtensions = { additionalTemplateFilters: convertFiltersToRecord( @@ -306,48 +307,10 @@ export async function createRouter( workers.push(worker); } - // TODO(blam): it's a little unfortunate that you have to restart the scaffolder - // backend in order to pick these up. We should really just make `ActionsRegistry.get()` async - // and then we can move this logic into the there instead. - // But we can't make those changes until next major. - // Alternatively, we could look at setting up a periodic task that refreshes the actions registry, but - // not feeling that it's worth the complexity. - const { actions: distributedActions } = await actionsRegistry.list({ - credentials: await auth.getOwnServiceCredentials(), - }); - for (const action of actions) { actionRegistry.register(action); } - for (const action of distributedActions) { - actionRegistry.register({ - id: action.id, - description: action.description, - examples: [], - supportsDryRun: - action.attributes?.readOnly === true && - action.attributes?.destructive === false, - handler: async ctx => { - const { output } = await actionsRegistry.invoke({ - id: action.id, - input: ctx.input, - credentials: await ctx.getInitiatorCredentials(), - }); - - if (isPlainObject(output)) { - for (const [key, value] of Object.entries(output as JsonObject)) { - ctx.output(key as keyof typeof output, value); - } - } - }, - schema: { - input: action.schema.input as Schema, - output: action.schema.output as Schema, - }, - }); - } - const launchWorkers = () => workers.forEach(worker => worker.start()); const shutdownWorkers = async () => { @@ -479,16 +442,20 @@ export async function createRouter( eventId: 'action-fetch', request: req, }); + const credentials = await httpAuth.credentials(req); try { - const actionsList = actionRegistry.list().map(action => { - return { - id: action.id, - description: action.description, - examples: action.examples, - schema: action.schema, - }; - }); + const list = await actionRegistry.list({ credentials }); + const actionsList = Array.from(list.values()) + .map(action => { + return { + id: action.id, + description: action.description, + examples: action.examples, + schema: action.schema, + }; + }) + .sort((a, b) => a.id.localeCompare(b.id)); await auditorEvent?.success(); From a39f28c17a73d13e92fb3272a07d972fddfb93a7 Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Wed, 24 Sep 2025 09:48:22 +0300 Subject: [PATCH 132/244] fix(scaffolder): use initiator credentials for getting action Signed-off-by: Hellgren Heikki --- .../actions/TemplateActionRegistry.test.ts | 78 ++++++++----------- .../actions/TemplateActionRegistry.ts | 25 +++--- .../dryrun/DecoratedActionsRegistry.ts | 11 ++- .../tasks/NunjucksWorkflowRunner.test.ts | 1 - .../tasks/NunjucksWorkflowRunner.ts | 6 +- .../src/scaffolder/tasks/TaskWorker.ts | 2 +- .../scaffolder-backend/src/service/router.ts | 1 - 7 files changed, 60 insertions(+), 64 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.test.ts index f3a3b15ec9..c5d437d57b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.test.ts @@ -23,17 +23,14 @@ import { actionsRegistryServiceMock } from '@backstage/backend-test-utils/alpha' describe('DefaultTemplateActionRegistry', () => { let registry: DefaultTemplateActionRegistry; let mockActionsService: ReturnType; - let mockAuthService: ReturnType; let mockLogger: ReturnType; beforeEach(() => { mockActionsService = actionsRegistryServiceMock(); - mockAuthService = mockServices.auth(); mockLogger = mockServices.logger.mock(); registry = new DefaultTemplateActionRegistry( mockActionsService, - mockAuthService, mockLogger, ); }); @@ -80,7 +77,9 @@ describe('DefaultTemplateActionRegistry', () => { }); registry.register(action); - const result = await registry.get('test-action'); + const result = await registry.get('test-action', { + credentials: mockCredentials.user(), + }); expect(result).toBe(action); }); @@ -101,7 +100,9 @@ describe('DefaultTemplateActionRegistry', () => { action: async () => ({ output: {} }), }); - const result = await registry.get('test:service-action'); + const result = await registry.get('test:service-action', { + credentials: mockCredentials.user(), + }); expect(result.id).toBe('test:service-action'); expect(result.description).toBe('Service action'); @@ -109,28 +110,26 @@ describe('DefaultTemplateActionRegistry', () => { }); it('should throw NotFoundError when action is not found', async () => { - await expect(registry.get('non-existent-action')).rejects.toThrow( - NotFoundError, - ); - await expect(registry.get('non-existent-action')).rejects.toThrow( + await expect( + registry.get('non-existent-action', { + credentials: mockCredentials.user(), + }), + ).rejects.toThrow(NotFoundError); + await expect( + registry.get('non-existent-action', { + credentials: mockCredentials.user(), + }), + ).rejects.toThrow( "Template action with ID 'non-existent-action' is not registered", ); }); - - it('should use own service credentials when getting action', async () => { - const spy = jest.spyOn(mockActionsService, 'list'); - - await expect(registry.get('non-existent')).rejects.toThrow(); - - expect(spy).toHaveBeenCalledWith({ - credentials: await mockAuthService.getOwnServiceCredentials(), - }); - }); }); describe('list', () => { it('should return empty map when no actions are registered', async () => { - const result = await registry.list(); + const result = await registry.list({ + credentials: mockCredentials.user(), + }); expect(result).toBeInstanceOf(Map); expect(result.size).toBe(0); @@ -152,7 +151,9 @@ describe('DefaultTemplateActionRegistry', () => { registry.register(action1); registry.register(action2); - const result = await registry.list(); + const result = await registry.list({ + credentials: mockCredentials.user(), + }); expect(result.size).toBe(2); expect(result.get('action-1')).toBe(action1); @@ -175,7 +176,9 @@ describe('DefaultTemplateActionRegistry', () => { action: async () => ({ output: {} }), }); - const result = await registry.list(); + const result = await registry.list({ + credentials: mockCredentials.user(), + }); expect(result.size).toBe(1); const action = result.get('test:service-action'); @@ -204,7 +207,9 @@ describe('DefaultTemplateActionRegistry', () => { }); registry.register(localAction); - const result = await registry.list(); + const result = await registry.list({ + credentials: mockCredentials.user(), + }); expect(result.get('test:same-id')).toBe(localAction); expect(mockLogger.warn).toHaveBeenCalledWith( @@ -212,25 +217,6 @@ describe('DefaultTemplateActionRegistry', () => { ); }); - it('should use provided credentials when listing actions', async () => { - const credentials = mockCredentials.user(); - const spy = jest.spyOn(mockActionsService, 'list'); - - await registry.list({ credentials }); - - expect(spy).toHaveBeenCalledWith({ credentials }); - }); - - it('should use own service credentials when no credentials provided', async () => { - const spy = jest.spyOn(mockActionsService, 'list'); - - await registry.list(); - - expect(spy).toHaveBeenCalledWith({ - credentials: await mockAuthService.getOwnServiceCredentials(), - }); - }); - it('should set supportsDryRun to false for destructive actions', async () => { mockActionsService.register({ name: 'destructive-action', @@ -247,7 +233,9 @@ describe('DefaultTemplateActionRegistry', () => { action: async () => ({ output: {} }), }); - const result = await registry.list(); + const result = await registry.list({ + credentials: mockCredentials.user(), + }); const action = result.get('test:destructive-action'); expect(action!.supportsDryRun).toBe(false); @@ -269,7 +257,9 @@ describe('DefaultTemplateActionRegistry', () => { action: async () => ({ output: {} }), }); - const result = await registry.list(); + const result = await registry.list({ + credentials: mockCredentials.user(), + }); const action = result.get('test:non-readonly-action'); expect(action!.supportsDryRun).toBe(false); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts index 7bcf120646..dab1447eee 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts @@ -18,7 +18,6 @@ import { ConflictError, NotFoundError } from '@backstage/errors'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; import { ActionsService } from '@backstage/backend-plugin-api/alpha'; import { - AuthService, BackstageCredentials, LoggerService, } from '@backstage/backend-plugin-api'; @@ -31,9 +30,12 @@ import { JsonObject } from '@backstage/types'; */ export interface TemplateActionRegistry { register(action: TemplateAction): void; - get(actionId: string): Promise>; - list(options?: { - credentials?: BackstageCredentials; + get( + actionId: string, + options: { credentials: BackstageCredentials }, + ): Promise>; + list(options: { + credentials: BackstageCredentials; }): Promise>>; } @@ -45,7 +47,6 @@ export class DefaultTemplateActionRegistry implements TemplateActionRegistry { constructor( private readonly actionsRegistry: ActionsService, - private readonly auth: AuthService, private readonly logger: LoggerService, ) {} @@ -59,8 +60,11 @@ export class DefaultTemplateActionRegistry implements TemplateActionRegistry { this.actions.set(action.id, action); } - async get(actionId: string): Promise> { - const action = (await this.list()).get(actionId); + async get( + actionId: string, + options: { credentials: BackstageCredentials }, + ): Promise> { + const action = (await this.list(options)).get(actionId); if (!action) { throw new NotFoundError( `Template action with ID '${actionId}' is not registered. See https://backstage.io/docs/features/software-templates/builtin-actions/ on how to add a new action module.`, @@ -69,14 +73,13 @@ export class DefaultTemplateActionRegistry implements TemplateActionRegistry { return action; } - async list(options?: { - credentials?: BackstageCredentials; + async list(options: { + credentials: BackstageCredentials; }): Promise>> { const ret = new Map(this.actions); const { actions } = await this.actionsRegistry.list({ - credentials: - options?.credentials ?? (await this.auth.getOwnServiceCredentials()), + credentials: options.credentials, }); for (const action of actions) { diff --git a/plugins/scaffolder-backend/src/scaffolder/dryrun/DecoratedActionsRegistry.ts b/plugins/scaffolder-backend/src/scaffolder/dryrun/DecoratedActionsRegistry.ts index b3f4b5e2cf..edbe28a0f5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/dryrun/DecoratedActionsRegistry.ts +++ b/plugins/scaffolder-backend/src/scaffolder/dryrun/DecoratedActionsRegistry.ts @@ -31,9 +31,12 @@ export class DecoratedActionsRegistry implements TemplateActionRegistry { } } - async get(actionId: string): Promise { + async get( + actionId: string, + options: { credentials: BackstageCredentials }, + ): Promise { try { - return await this.innerRegistry.get(actionId); + return await this.innerRegistry.get(actionId, options); } catch (e) { if (!this.innerActions.has(actionId)) { throw e; @@ -42,8 +45,8 @@ export class DecoratedActionsRegistry implements TemplateActionRegistry { } } - async list(options?: { - credentials?: BackstageCredentials; + async list(options: { + credentials: BackstageCredentials; }): Promise>> { const inner = await this.innerRegistry.list(options); return new Map>([ diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts index 886ddda36f..2c661fab56 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.test.ts @@ -110,7 +110,6 @@ describe('NunjucksWorkflowRunner', () => { actionRegistry = new DefaultTemplateActionRegistry( actionsRegistryServiceMock(), - mockServices.auth(), mockServices.logger.mock(), ); fakeActionHandler = jest.fn(); diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts index d13fa58a94..4d070daa52 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/NunjucksWorkflowRunner.ts @@ -33,7 +33,7 @@ import { SecureTemplater, SecureTemplateRenderer, } from '../../lib/templating/SecureTemplater'; -import { TemplateActionRegistry } from '../actions/TemplateActionRegistry.ts'; +import { TemplateActionRegistry } from '../actions/TemplateActionRegistry'; import { generateExampleOutput, isTruthy } from './helper'; import { TaskTrackType, WorkflowResponse, WorkflowRunner } from './types'; @@ -245,7 +245,9 @@ export class NunjucksWorkflowRunner implements WorkflowRunner { return; } const action: TemplateAction = - await this.options.actionRegistry.get(step.action); + await this.options.actionRegistry.get(step.action, { + credentials: await task.getInitiatorCredentials(), + }); const { taskLogger } = createStepLogger({ task, step, diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts index 7b85dd1270..adfdf0b553 100644 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts +++ b/plugins/scaffolder-backend/src/scaffolder/tasks/TaskWorker.ts @@ -25,7 +25,7 @@ import { TemplateGlobal, } from '@backstage/plugin-scaffolder-node'; import PQueue from 'p-queue'; -import { TemplateActionRegistry } from '../actions/TemplateActionRegistry.ts'; +import { TemplateActionRegistry } from '../actions/TemplateActionRegistry'; import { NunjucksWorkflowRunner } from './NunjucksWorkflowRunner'; import { WorkflowRunner } from './types'; import { setTimeout } from 'timers/promises'; diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index bcdcedb70d..3894ffb876 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -271,7 +271,6 @@ export async function createRouter( const actionRegistry = new DefaultTemplateActionRegistry( actionsRegistry, - auth, logger, ); From 68036b78e87d36006ecfc6c196ee1ab5b3a06a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 9 Oct 2025 13:31:42 +0200 Subject: [PATCH 133/244] generate api report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- packages/ui/report.api.md | 72 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index f546761837..24c41e3d81 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -11,8 +11,12 @@ import { ColumnProps } from 'react-aria-components'; import { ComponentProps } from 'react'; import type { ComponentPropsWithRef } from 'react'; import { Context } from 'react'; +import { DetailedHTMLProps } from 'react'; +import type { DialogTriggerProps as DialogTriggerProps_2 } from 'react-aria-components'; import type { ElementType } from 'react'; import { ForwardRefExoticComponent } from 'react'; +import type { HeadingProps } from 'react-aria-components'; +import { HTMLAttributes } from 'react'; import { JSX as JSX_2 } from 'react/jsx-runtime'; import { LinkProps as LinkProps_2 } from 'react-aria-components'; import type { ListBoxItemProps } from 'react-aria-components'; @@ -21,6 +25,7 @@ import type { MenuItemProps as MenuItemProps_2 } from 'react-aria-components'; import type { MenuProps as MenuProps_2 } from 'react-aria-components'; import type { MenuSectionProps as MenuSectionProps_2 } from 'react-aria-components'; import type { MenuTriggerProps as MenuTriggerProps_2 } from 'react-aria-components'; +import type { ModalOverlayProps } from 'react-aria-components'; import type { PopoverProps } from 'react-aria-components'; import type { RadioGroupProps as RadioGroupProps_2 } from 'react-aria-components'; import type { RadioProps as RadioProps_2 } from 'react-aria-components'; @@ -690,6 +695,73 @@ export type DataAttributesMap = Record; // @public export type DataAttributeValues = readonly (string | number | boolean)[]; +// @public (undocumented) +export const Dialog: ForwardRefExoticComponent< + DialogProps & RefAttributes +>; + +// @public (undocumented) +export const DialogBody: ForwardRefExoticComponent< + DialogBodyProps & RefAttributes +>; + +// @public +export interface DialogBodyProps { + // (undocumented) + children?: React.ReactNode; + // (undocumented) + className?: string; + // (undocumented) + height?: number | string; +} + +// @public (undocumented) +export const DialogClose: ForwardRefExoticComponent< + DialogCloseProps & RefAttributes +>; + +// @public +export interface DialogCloseProps extends Omit { + // (undocumented) + variant?: 'primary' | 'secondary' | 'tertiary'; +} + +// @public (undocumented) +export const DialogFooter: ForwardRefExoticComponent< + Omit< + DetailedHTMLProps, HTMLDivElement>, + 'ref' + > & + RefAttributes +>; + +// @public (undocumented) +export const DialogHeader: ForwardRefExoticComponent< + DialogHeaderProps & RefAttributes +>; + +// @public +export interface DialogHeaderProps extends HeadingProps { + // (undocumented) + children?: React.ReactNode; + // (undocumented) + className?: string; +} + +// @public +export interface DialogProps extends ModalOverlayProps { + // (undocumented) + children?: React.ReactNode; + // (undocumented) + className?: string; +} + +// @public (undocumented) +export const DialogTrigger: (props: DialogTriggerProps) => JSX_2.Element; + +// @public +export interface DialogTriggerProps extends DialogTriggerProps_2 {} + // @public (undocumented) export type Display = 'none' | 'flex' | 'block' | 'inline'; From a1dae7180d23f7c3a84ea80780139b3ff76df041 Mon Sep 17 00:00:00 2001 From: Hellgren Heikki Date: Thu, 9 Oct 2025 15:11:17 +0300 Subject: [PATCH 134/244] feat(eslint): relax frontend imports for nfs allow frontend plugins to import from other frontend plugins with same plugin id to allow plugin overrides without unnecessary eslint warning. relates to #31372 Signed-off-by: Hellgren Heikki --- .changeset/hungry-needles-clean.md | 8 +++++++ .../docs/rules/no-mixed-plugin-imports.md | 21 ++++++++++++++++++- packages/eslint-plugin/lib/getPackages.js | 2 +- .../rules/no-mixed-plugin-imports.js | 13 ++++++++++++ .../packages/bar-override/package.json | 19 +++++++++++++++++ .../monorepo/packages/bar/package.json | 3 ++- .../monorepo/packages/foo/package.json | 3 ++- 7 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 .changeset/hungry-needles-clean.md create mode 100644 packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar-override/package.json diff --git a/.changeset/hungry-needles-clean.md b/.changeset/hungry-needles-clean.md new file mode 100644 index 0000000000..6bab8f238e --- /dev/null +++ b/.changeset/hungry-needles-clean.md @@ -0,0 +1,8 @@ +--- +'@backstage/eslint-plugin': patch +--- + +Allow frontend plugin to import from another frontend plugin with same plugin id. + +This prevents the ESLint rule from incorrectly flagging these imports in the new frontend system +where plugin override requires cross-plugin imports. diff --git a/packages/eslint-plugin/docs/rules/no-mixed-plugin-imports.md b/packages/eslint-plugin/docs/rules/no-mixed-plugin-imports.md index e8570054e4..26a332d105 100644 --- a/packages/eslint-plugin/docs/rules/no-mixed-plugin-imports.md +++ b/packages/eslint-plugin/docs/rules/no-mixed-plugin-imports.md @@ -1,6 +1,25 @@ # @backstage/no-mixed-plugin-imports -Disallow mixed imports between backstage plugins. +This rule ensures that imports between Backstage plugins are consistent with their intended usage. + +The rule checks the `backstage.role` field in the `package.json` of both the importing and target packages to determine if they are compatible. + +Plugin roles include: + +- `frontend-plugin` (or `frontend` for short) +- `backend-plugin` (or `backend` for short) +- `web-library` (or `react` for short) +- `node-library` (or `node` for short) +- `common-library` (or `common` for short) + +Prohibited imports include: + +- A `frontend` plugin importing directly from another `frontend`, `backend`, or `node` package. Instead, it should import from the corresponding `react` or `common` package. + - With an exception with the new frontend system where frontend plugins with the same plugin id are allowed to import from each other. +- A `backend` plugin importing directly from another `backend`, `frontend`, or `react` package. Instead, it should import from the corresponding `node` or `common` package. +- A `react` package importing from `frontend`, `backend`, or `node` packages. +- A `node` package importing from `frontend`, `backend`, or `react` packages +- A `common` package importing directly from any other plugin package. ## Usage diff --git a/packages/eslint-plugin/lib/getPackages.js b/packages/eslint-plugin/lib/getPackages.js index e90536ff52..68739d358b 100644 --- a/packages/eslint-plugin/lib/getPackages.js +++ b/packages/eslint-plugin/lib/getPackages.js @@ -21,7 +21,7 @@ const manypkg = require('@manypkg/get-packages'); /** * @typedef ExtendedPackage - * @type {import('@manypkg/get-packages').Package & { packageJson: { exports?: Record, files?: Array, backstage?: { inline?: boolean, role?: string } }}} packageJson + * @type {import('@manypkg/get-packages').Package & { packageJson: { exports?: Record, files?: Array, backstage?: { inline?: boolean, role?: string, pluginId?: string } }}} packageJson */ /** diff --git a/packages/eslint-plugin/rules/no-mixed-plugin-imports.js b/packages/eslint-plugin/rules/no-mixed-plugin-imports.js index b5e79b509e..cf8b3bde0b 100644 --- a/packages/eslint-plugin/rules/no-mixed-plugin-imports.js +++ b/packages/eslint-plugin/rules/no-mixed-plugin-imports.js @@ -146,11 +146,24 @@ module.exports = { } const sourceRole = pkg.packageJson.backstage?.role; + const sourcePluginId = pkg.packageJson.backstage?.pluginId; const targetRole = targetPackage.packageJson.backstage?.role; + const targetPluginId = targetPackage.packageJson.backstage?.pluginId; if (!sourceRole || !targetRole) { return; } + // Allow frontend plugins to import from other frontend plugins with the same pluginId for NFS + if ( + sourceRole === 'frontend-plugin' && + targetRole === 'frontend-plugin' && + sourcePluginId && + targetPluginId && + sourcePluginId === targetPluginId + ) { + return; + } + if ( roleRules.some( rule => diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar-override/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar-override/package.json new file mode 100644 index 0000000000..ff8996a0a2 --- /dev/null +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar-override/package.json @@ -0,0 +1,19 @@ +{ + "name": "@internal/bar-override", + "backstage": { + "role": "frontend-plugin", + "pluginId": "bar" + }, + "exports": { + ".": "./src/index.ts", + "./BarPage": "./src/components/Bar.tsx", + "./package.json": "./package.json" + }, + "dependencies": { + "inline-dep": "*", + "react-router": "*" + }, + "devDependencies": { + "react-router-dom": "*" + } +} diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json index ba55598dc2..bd60f93ce6 100644 --- a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/bar/package.json @@ -1,7 +1,8 @@ { "name": "@internal/bar", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "bar" }, "exports": { ".": "./src/index.ts", diff --git a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json index e8e4d4ba70..66be5cecf2 100644 --- a/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json +++ b/packages/eslint-plugin/src/__fixtures__/monorepo/packages/foo/package.json @@ -1,7 +1,8 @@ { "name": "@internal/foo", "backstage": { - "role": "frontend-plugin" + "role": "frontend-plugin", + "pluginId": "foo" }, "files": [ "dist", From f041c1fe10981ea554da91aa06548ed1d9a043a4 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 9 Oct 2025 15:50:53 +0200 Subject: [PATCH 135/244] ui: extract data-* attributes Signed-off-by: Vincenzo Scamporlino --- packages/ui/src/utils/extractProps.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/packages/ui/src/utils/extractProps.ts b/packages/ui/src/utils/extractProps.ts index 1668117909..3914072ff4 100644 --- a/packages/ui/src/utils/extractProps.ts +++ b/packages/ui/src/utils/extractProps.ts @@ -86,16 +86,25 @@ export function extractProps( } // Ensure keys from props that are defined in propDefs are removed - const cleanedProps = Object.keys(props).reduce((acc, key) => { - if (!propDefs.hasOwnProperty(key)) { - acc[key] = props[key]; - } - return acc; - }, {} as { [key: string]: any }); + const { cleanedProps, dataProps } = Object.keys(props).reduce( + (acc, key) => { + if (key.startsWith('data-')) { + acc.dataProps[key] = props[key]; + } + if (!propDefs.hasOwnProperty(key)) { + acc.cleanedProps[key] = props[key]; + } + return acc; + }, + { dataProps: {}, cleanedProps: {} } as { + dataProps: { [key: string]: any }; + cleanedProps: { [key: string]: any }; + }, + ); const newClassNames = className .filter(name => name && name.trim() !== '') .join(' '); - return { ...cleanedProps, className: newClassNames, style }; + return { ...cleanedProps, className: newClassNames, style, dataProps }; } From 03050a6ad426e6ed6893ca179a3deb2cf899f194 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 9 Oct 2025 15:51:33 +0200 Subject: [PATCH 136/244] ui: make sure data attributes are passed down to the DOM Signed-off-by: Vincenzo Scamporlino --- packages/ui/src/components/Box/Box.tsx | 3 ++- packages/ui/src/components/Container/Container.tsx | 3 ++- packages/ui/src/components/Flex/Flex.tsx | 3 ++- packages/ui/src/components/Grid/Grid.tsx | 6 ++++-- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/ui/src/components/Box/Box.tsx b/packages/ui/src/components/Box/Box.tsx index 4273ee86f9..06d7d1d434 100644 --- a/packages/ui/src/components/Box/Box.tsx +++ b/packages/ui/src/components/Box/Box.tsx @@ -40,11 +40,12 @@ export const Box = forwardRef((props, ref) => { }; const { classNames } = useStyles('Box'); - const { className, style } = extractProps(props, propDefs); + const { className, style, dataProps } = extractProps(props, propDefs); return createElement(props.as || 'div', { ref, className: clsx(classNames.root, className), + ...dataProps, style, children, }); diff --git a/packages/ui/src/components/Container/Container.tsx b/packages/ui/src/components/Container/Container.tsx index 7be4e5fdce..eef1e187c4 100644 --- a/packages/ui/src/components/Container/Container.tsx +++ b/packages/ui/src/components/Container/Container.tsx @@ -43,11 +43,12 @@ export const Container = forwardRef( ...displayPropDefs, ...containerSpacingProps, }; - const { className, style } = extractProps(props, propDefs); + const { className, style, dataProps } = extractProps(props, propDefs); return createElement('div', { ref, className: clsx(classNames.root, className), + ...dataProps, style, children, }); diff --git a/packages/ui/src/components/Flex/Flex.tsx b/packages/ui/src/components/Flex/Flex.tsx index ded4fffffa..021fe87820 100644 --- a/packages/ui/src/components/Flex/Flex.tsx +++ b/packages/ui/src/components/Flex/Flex.tsx @@ -32,11 +32,12 @@ export const Flex = forwardRef((props, ref) => { }; const { classNames } = useStyles('Flex'); - const { className, style } = extractProps(props, propDefs); + const { className, style, dataProps } = extractProps(props, propDefs); return createElement('div', { ref, className: clsx(classNames.root, className), + ...dataProps, style, children: props.children, }); diff --git a/packages/ui/src/components/Grid/Grid.tsx b/packages/ui/src/components/Grid/Grid.tsx index 27257c8972..18ed40b87b 100644 --- a/packages/ui/src/components/Grid/Grid.tsx +++ b/packages/ui/src/components/Grid/Grid.tsx @@ -32,11 +32,12 @@ const GridRoot = forwardRef((props, ref) => { const { classNames } = useStyles('Grid'); - const { className, style } = extractProps(props, propDefs); + const { className, style, dataProps } = extractProps(props, propDefs); return createElement('div', { ref, className: clsx(classNames.root, className), + ...dataProps, style, children: props.children, }); @@ -48,11 +49,12 @@ const GridItem = forwardRef((props, ref) => { }; const { classNames } = useStyles('Grid'); - const { className, style } = extractProps(props, propDefs); + const { className, style, dataProps } = extractProps(props, propDefs); return createElement('div', { ref, className: clsx(classNames.item, className), + ...dataProps, style, children: props.children, }); From b94006200dbd4eb0aa363249d31b3b3f5775343a Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Thu, 9 Oct 2025 15:53:57 +0200 Subject: [PATCH 137/244] ui: data attributes changesets Signed-off-by: Vincenzo Scamporlino --- .changeset/open-symbols-find.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/open-symbols-find.md diff --git a/.changeset/open-symbols-find.md b/.changeset/open-symbols-find.md new file mode 100644 index 0000000000..a7d4908980 --- /dev/null +++ b/.changeset/open-symbols-find.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +Added support for data attributes in ``, ``, ``, and `` components, ensuring they are correctly applied to the rendered elements. From c9778ca53e4a5809f709fd30058eb6084d0d8edf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sofia=20Sj=C3=B6blad?= Date: Thu, 9 Oct 2025 16:48:14 +0200 Subject: [PATCH 138/244] add documentation for dialog component MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sofia Sjöblad --- docs-ui/src/content/components/dialog.mdx | 101 +++++++++++++ .../src/content/components/dialog.props.ts | 139 ++++++++++++++++++ docs-ui/src/snippets/stories-snippets.tsx | 2 + docs-ui/src/utils/data.ts | 5 + .../src/components/Dialog/Dialog.stories.tsx | 138 +++++++++++------ .../src/components/Dialog/Dialog.styles.css | 1 + 6 files changed, 338 insertions(+), 48 deletions(-) create mode 100644 docs-ui/src/content/components/dialog.mdx create mode 100644 docs-ui/src/content/components/dialog.props.ts diff --git a/docs-ui/src/content/components/dialog.mdx b/docs-ui/src/content/components/dialog.mdx new file mode 100644 index 0000000000..2524fc1a24 --- /dev/null +++ b/docs-ui/src/content/components/dialog.mdx @@ -0,0 +1,101 @@ +import { PropsTable } from '@/components/PropsTable'; +import { Snippet } from '@/components/Snippet'; +import { CodeBlock } from '@/components/CodeBlock'; +import {DialogSnippet} from '@/snippets/stories-snippets'; +import { + dialogPropDefs, + dialogTriggerPropDefs, + dialogHeaderPropDefs, + dialogBodyPropDefs, + dialogFooterPropDefs, + dialogClosePropDefs, + dialogUsageSnippet, + dialogDefaultSnippet, + dialogScrollableSnippet, + dialogWithFormSnippet, +} from './dialog.props'; +import { PageTitle } from '@/components/PageTitle'; +import { Theming } from '@/components/Theming'; +import { ChangelogComponent } from '@/components/ChangelogComponent'; + + + +} + code={dialogDefaultSnippet} +/> + +## Usage + + + +## API reference + +### Dialog + +The main dialog container that renders as a modal overlay. + + + +### DialogTrigger + +Wraps a trigger element and the dialog content to handle open/close state. + + + +### DialogHeader + +Displays the dialog title with a built-in close button. + + + +### DialogBody + +The main content area of the dialog with optional scrolling. + + + +### DialogFooter + +Contains action buttons or other footer content. + + + +### DialogClose + +A button that closes the dialog when pressed. + + + +## Examples + +### Scrollable Content + +Dialog with a fixed height body that scrolls when content overflows. + +} + code={dialogScrollableSnippet} +/> + +### Dialog with Form + +Dialog containing form elements for user input. + +} + code={dialogWithFormSnippet} +/> + + + + diff --git a/docs-ui/src/content/components/dialog.props.ts b/docs-ui/src/content/components/dialog.props.ts new file mode 100644 index 0000000000..feefc4efd5 --- /dev/null +++ b/docs-ui/src/content/components/dialog.props.ts @@ -0,0 +1,139 @@ +import { + classNamePropDefs, + stylePropDefs, + type PropDef, +} from '@/utils/propDefs'; + +export const dialogPropDefs: Record = { + children: { type: 'enum', values: ['ReactNode'], responsive: false }, + ...classNamePropDefs, + ...stylePropDefs, +}; + +export const dialogTriggerPropDefs: Record = { + children: { type: 'enum', values: ['ReactNode'], responsive: false }, +}; + +export const dialogHeaderPropDefs: Record = { + children: { type: 'enum', values: ['ReactNode'], responsive: false }, + ...classNamePropDefs, + ...stylePropDefs, +}; + +export const dialogBodyPropDefs: Record = { + children: { type: 'enum', values: ['ReactNode'], responsive: false }, + height: { + type: 'enum', + values: ['number', 'string'], + responsive: false, + }, + ...classNamePropDefs, + ...stylePropDefs, +}; + +export const dialogFooterPropDefs: Record = { + children: { type: 'enum', values: ['ReactNode'], responsive: false }, + ...classNamePropDefs, + ...stylePropDefs, +}; + +export const dialogClosePropDefs: Record = { + variant: { + type: 'enum', + values: ['primary', 'secondary', 'tertiary'], + default: 'secondary', + responsive: false, + }, + children: { type: 'enum', values: ['ReactNode'], responsive: false }, + ...classNamePropDefs, + ...stylePropDefs, +}; + +export const dialogUsageSnippet = `import { + Dialog, + DialogTrigger, + DialogHeader, + DialogBody, + DialogFooter, + DialogClose +} from '@backstage/ui'; + + + + + Title + Content + + Close + + +`; + +export const dialogDefaultSnippet = ` + + + Example Dialog + + This is a basic dialog example with React Aria Components. + + + Close + Save + + +`; + +export const dialogScrollableSnippet = ` + + + Long Content Dialog + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim + veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea + commodo consequat. + + + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum + dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non + proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + + + Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium + doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore + veritatis et quasi architecto beatae vitae dicta sunt explicabo. + + + + + Cancel + Accept + + + +`; + +export const dialogWithFormSnippet = ` + + + Create New User + + + + + + + + + + Cancel + Create User + + + +`; diff --git a/docs-ui/src/snippets/stories-snippets.tsx b/docs-ui/src/snippets/stories-snippets.tsx index 5aa5b8c7d9..a84e790476 100644 --- a/docs-ui/src/snippets/stories-snippets.tsx +++ b/docs-ui/src/snippets/stories-snippets.tsx @@ -17,6 +17,7 @@ import * as MenuStories from '../../../packages/ui/src/components/Menu/Menu.stor import * as LinkStories from '../../../packages/ui/src/components/Link/Link.stories'; import * as AvatarStories from '../../../packages/ui/src/components/Avatar/Avatar.stories'; import * as CollapsibleStories from '../../../packages/ui/src/components/Collapsible/Collapsible.stories'; +import * as DialogStories from '../../../packages/ui/src/components/Dialog/Dialog.stories'; import * as RadioGroupStories from '../../../packages/ui/src/components/RadioGroup/RadioGroup.stories'; import * as TabsStories from '../../../packages/ui/src/components/Tabs/Tabs.stories'; import * as SwitchStories from '../../../packages/ui/src/components/Switch/Switch.stories'; @@ -60,6 +61,7 @@ export const MenuSnippet = createSnippetComponent(MenuStories); export const LinkSnippet = createSnippetComponent(LinkStories); export const AvatarSnippet = createSnippetComponent(AvatarStories); export const CollapsibleSnippet = createSnippetComponent(CollapsibleStories); +export const DialogSnippet = createSnippetComponent(DialogStories); export const RadioGroupSnippet = createSnippetComponent(RadioGroupStories); export const TabsSnippet = createSnippetComponent(TabsStories); export const SwitchSnippet = createSnippetComponent(SwitchStories); diff --git a/docs-ui/src/utils/data.ts b/docs-ui/src/utils/data.ts index 5e7305da28..dfe563c0d1 100644 --- a/docs-ui/src/utils/data.ts +++ b/docs-ui/src/utils/data.ts @@ -101,6 +101,11 @@ export const components: Page[] = [ slug: 'collapsible', status: 'alpha', }, + { + title: 'Dialog', + slug: 'dialog', + status: 'alpha', + }, { title: 'Header', slug: 'header', diff --git a/packages/ui/src/components/Dialog/Dialog.stories.tsx b/packages/ui/src/components/Dialog/Dialog.stories.tsx index 47b62330f7..dacf6427b6 100644 --- a/packages/ui/src/components/Dialog/Dialog.stories.tsx +++ b/packages/ui/src/components/Dialog/Dialog.stories.tsx @@ -22,7 +22,7 @@ import { DialogFooter, DialogClose, } from './Dialog'; -import { Button, Flex, Text } from '@backstage/ui'; +import { Button, Flex, Text, TextField, Select } from '@backstage/ui'; const meta = { title: 'Components/Dialog', @@ -33,64 +33,106 @@ export default meta; type Story = StoryObj; export const Default: Story = { - args: { - children: ( - <> - Hello + render: () => ( + + + + Example Dialog - Hello world + + This is a basic dialog example with React Aria Components. + - - Close - console.log('Save')}> - Save - - + Close + Save - - ), - }, - render: args => ( - - - + ), }; -export const CustomBodyMaxHeight: Story = { - args: { - children: ( - <> - Hello - - {Array.from({ length: 40 }).map((_, index) => ( - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Quisquam, - quos. - - ))} +export const Scrollable: Story = { + render: () => ( + + + + Long Content Dialog + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do + eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim + ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut + aliquip ex ea commodo consequat. + + + Duis aute irure dolor in reprehenderit in voluptate velit esse + cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat + cupidatat non proident, sunt in culpa qui officia deserunt mollit + anim id est laborum. + + + Sed ut perspiciatis unde omnis iste natus error sit voluptatem + accusantium doloremque laudantium, totam rem aperiam, eaque ipsa + quae ab illo inventore veritatis et quasi architecto beatae vitae + dicta sunt explicabo. + - - Close - console.log('Save')}> - Save - - + Cancel + Accept - - ), - }, - render: args => ( - - - + + + ), +}; + +export const Confirmation: Story = { + render: () => ( + + + + Confirm Delete + + + Are you sure you want to delete this item? This action cannot be + undone. + + + + Cancel + Delete + + + + ), +}; + +export const WithForm: Story = { + render: () => ( + + + + Create New User + + + + + ( return ( ( secondaryLabel={secondaryLabelText} description={description} /> -
{children}
+
+ {children} +
); @@ -85,7 +88,7 @@ export const Radio = forwardRef((props, ref) => { return ( diff --git a/packages/ui/src/components/ScrollArea/ScrollArea.styles.css b/packages/ui/src/components/ScrollArea/ScrollArea.module.css similarity index 100% rename from packages/ui/src/components/ScrollArea/ScrollArea.styles.css rename to packages/ui/src/components/ScrollArea/ScrollArea.module.css diff --git a/packages/ui/src/components/ScrollArea/ScrollArea.tsx b/packages/ui/src/components/ScrollArea/ScrollArea.tsx index 44722fbd12..e182ba8c99 100644 --- a/packages/ui/src/components/ScrollArea/ScrollArea.tsx +++ b/packages/ui/src/components/ScrollArea/ScrollArea.tsx @@ -18,6 +18,7 @@ import { forwardRef } from 'react'; import { ScrollArea as ScrollAreaPrimitive } from '@base-ui-components/react/scroll-area'; import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; +import styles from './ScrollArea.module.css'; const ScrollAreaRoot = forwardRef< React.ElementRef, @@ -28,7 +29,7 @@ const ScrollAreaRoot = forwardRef< return ( ); @@ -44,7 +45,11 @@ const ScrollAreaViewport = forwardRef< return ( ); @@ -60,7 +65,11 @@ const ScrollAreaScrollbar = forwardRef< return ( ); @@ -76,7 +85,7 @@ const ScrollAreaThumb = forwardRef< return ( ); diff --git a/packages/ui/src/components/SearchField/SearchField.styles.css b/packages/ui/src/components/SearchField/SearchField.module.css similarity index 100% rename from packages/ui/src/components/SearchField/SearchField.styles.css rename to packages/ui/src/components/SearchField/SearchField.module.css diff --git a/packages/ui/src/components/SearchField/SearchField.tsx b/packages/ui/src/components/SearchField/SearchField.tsx index cb0eb41eda..820ceb42b9 100644 --- a/packages/ui/src/components/SearchField/SearchField.tsx +++ b/packages/ui/src/components/SearchField/SearchField.tsx @@ -25,6 +25,8 @@ import { FieldLabel } from '../FieldLabel'; import { FieldError } from '../FieldError'; import { RiSearch2Line, RiCloseCircleLine } from '@remixicon/react'; import { useStyles } from '../../hooks/useStyles'; +import stylesSearchField from './SearchField.module.css'; +import stylesTextField from '../TextField/TextField.module.css'; import type { SearchFieldProps } from './types'; @@ -102,6 +104,8 @@ export const SearchField = forwardRef( className={clsx( textFieldClassNames.root, searchFieldClassNames.root, + stylesTextField[textFieldClassNames.root], + stylesSearchField[searchFieldClassNames.root], className, )} {...dataAttributes} @@ -120,12 +124,18 @@ export const SearchField = forwardRef( description={description} />
{icon !== false && ( )} - - + + {options?.map(option => ( -
+
- + {option.label} diff --git a/packages/ui/src/components/Skeleton/Skeleton.styles.css b/packages/ui/src/components/Skeleton/Skeleton.module.css similarity index 100% rename from packages/ui/src/components/Skeleton/Skeleton.styles.css rename to packages/ui/src/components/Skeleton/Skeleton.module.css diff --git a/packages/ui/src/components/Skeleton/Skeleton.tsx b/packages/ui/src/components/Skeleton/Skeleton.tsx index 772a69bc28..f867f7fff7 100644 --- a/packages/ui/src/components/Skeleton/Skeleton.tsx +++ b/packages/ui/src/components/Skeleton/Skeleton.tsx @@ -16,6 +16,8 @@ import { useStyles } from '../../hooks/useStyles'; import { SkeletonProps } from './types'; +import styles from './Skeleton.module.css'; +import clsx from 'clsx'; /** @public */ export const Skeleton = (props: SkeletonProps) => { @@ -24,7 +26,7 @@ export const Skeleton = (props: SkeletonProps) => { return (
( @@ -25,8 +27,14 @@ export const Switch = forwardRef( const { classNames } = useStyles('Switch'); return ( - -
+ +
{label} ); diff --git a/packages/ui/src/components/Table/Table.styles.css b/packages/ui/src/components/Table/Table.module.css similarity index 100% rename from packages/ui/src/components/Table/Table.styles.css rename to packages/ui/src/components/Table/Table.module.css diff --git a/packages/ui/src/components/Table/components/Cell.tsx b/packages/ui/src/components/Table/components/Cell.tsx index d511ed21cb..e7f5fad0e8 100644 --- a/packages/ui/src/components/Table/components/Cell.tsx +++ b/packages/ui/src/components/Table/components/Cell.tsx @@ -20,6 +20,7 @@ import { Link } from '../../Link'; import { Cell as ReactAriaCell } from 'react-aria-components'; import type { CellProps } from '../types'; import { useStyles } from '../../../hooks/useStyles'; +import styles from '../Table.module.css'; /** @public */ const Cell = (props: CellProps) => { @@ -36,12 +37,29 @@ const Cell = (props: CellProps) => { const { classNames } = useStyles('Table'); return ( - -
- {leadingIcon && ( -
{leadingIcon}
+ +
+ > + {leadingIcon && ( +
+ {leadingIcon} +
+ )} +
{href ? ( {title} diff --git a/packages/ui/src/components/Table/components/CellProfile.tsx b/packages/ui/src/components/Table/components/CellProfile.tsx index 4e4906046d..89bb9234f9 100644 --- a/packages/ui/src/components/Table/components/CellProfile.tsx +++ b/packages/ui/src/components/Table/components/CellProfile.tsx @@ -21,6 +21,7 @@ import { Link } from '../../Link/Link'; import { Avatar } from '@base-ui-components/react/avatar'; import { useStyles } from '../../../hooks/useStyles'; import { Cell as ReactAriaCell } from 'react-aria-components'; +import styles from '../Table.module.css'; /** @public */ export const CellProfile = (props: CellProfileProps) => { @@ -36,18 +37,39 @@ export const CellProfile = (props: CellProfileProps) => { const { classNames } = useStyles('Table'); return ( - -
-
+ +
+
{src && ( - + - + {(name || '') .split(' ') .map(word => word[0]) @@ -58,7 +80,12 @@ export const CellProfile = (props: CellProfileProps) => { )}
-
+
{name && href ? ( {name} ) : ( diff --git a/packages/ui/src/components/Table/components/Column.tsx b/packages/ui/src/components/Table/components/Column.tsx index 7b9241edc9..dcc408b1ed 100644 --- a/packages/ui/src/components/Table/components/Column.tsx +++ b/packages/ui/src/components/Table/components/Column.tsx @@ -20,6 +20,8 @@ import { } from 'react-aria-components'; import { Icon } from '../../Icon'; import { useStyles } from '../../../hooks/useStyles'; +import styles from '../Table.module.css'; +import clsx from 'clsx'; /** @public */ export const Column = ( @@ -28,12 +30,26 @@ export const Column = ( const { classNames } = useStyles('Table'); return ( - + {({ allowsSorting, sortDirection }) => ( -
+
{props.children} {allowsSorting && ( -