@backstage/plugin-app 0.4.1-next.2 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/dist/apis/PluginHeaderActionsApi/DefaultPluginHeaderActionsApi.esm.js +8 -1
- package/dist/apis/PluginHeaderActionsApi/DefaultPluginHeaderActionsApi.esm.js.map +1 -1
- package/dist/apis/PluginWrapperApi/DefaultPluginWrapperApi.esm.js +134 -15
- package/dist/apis/PluginWrapperApi/DefaultPluginWrapperApi.esm.js.map +1 -1
- package/dist/apis/ToastApiForwarder.esm.js +94 -0
- package/dist/apis/ToastApiForwarder.esm.js.map +1 -0
- package/dist/apis/toastApiForwarderRef.esm.js +8 -0
- package/dist/apis/toastApiForwarderRef.esm.js.map +1 -0
- package/dist/components/Toast/Toast.esm.js +156 -0
- package/dist/components/Toast/Toast.esm.js.map +1 -0
- package/dist/components/Toast/Toast.module.css.esm.js +8 -0
- package/dist/components/Toast/Toast.module.css.esm.js.map +1 -0
- package/dist/components/Toast/ToastContainer.esm.js +90 -0
- package/dist/components/Toast/ToastContainer.esm.js.map +1 -0
- package/dist/components/Toast/ToastDisplay.esm.js +51 -0
- package/dist/components/Toast/ToastDisplay.esm.js.map +1 -0
- package/dist/defaultApis.esm.js +19 -1
- package/dist/defaultApis.esm.js.map +1 -1
- package/dist/extensions/AppNav.esm.js +35 -6
- package/dist/extensions/AppNav.esm.js.map +1 -1
- package/dist/extensions/AppRoot.esm.js +40 -34
- package/dist/extensions/AppRoot.esm.js.map +1 -1
- package/dist/extensions/IconsApi.esm.js.map +1 -1
- package/dist/extensions/PluginWrapperApi.esm.js +1 -2
- package/dist/extensions/PluginWrapperApi.esm.js.map +1 -1
- package/dist/extensions/components.esm.js +30 -18
- package/dist/extensions/components.esm.js.map +1 -1
- package/dist/extensions/elements.esm.js +4 -2
- package/dist/extensions/elements.esm.js.map +1 -1
- package/dist/hooks/useInvertedThemeMode.esm.js +41 -0
- package/dist/hooks/useInvertedThemeMode.esm.js.map +1 -0
- package/dist/index.d.ts +20 -6
- package/dist/node_modules_dist/style-inject/dist/style-inject.es.esm.js +29 -0
- package/dist/node_modules_dist/style-inject/dist/style-inject.es.esm.js.map +1 -0
- package/dist/packages/core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.esm.js +7 -0
- package/dist/packages/core-app-api/src/apis/implementations/AlertApi/AlertApiForwarder.esm.js.map +1 -1
- package/dist/packages/core-app-api/src/apis/implementations/auth/saml/types.esm.js +1 -1
- package/dist/packages/core-app-api/src/apis/implementations/auth/saml/types.esm.js.map +1 -1
- package/dist/packages/core-app-api/src/app/AppRouter.esm.js +11 -10
- package/dist/packages/core-app-api/src/app/AppRouter.esm.js.map +1 -1
- package/dist/packages/frontend-app-api/src/apis/implementations/IconsApi/DefaultIconsApi.esm.js +39 -3
- package/dist/packages/frontend-app-api/src/apis/implementations/IconsApi/DefaultIconsApi.esm.js.map +1 -1
- package/dist/packages/frontend-internal/src/wiring/InternalExtensionDefinition.esm.js.map +1 -1
- package/dist/packages/frontend-internal/src/wiring/InternalFrontendPlugin.esm.js.map +1 -1
- package/dist/packages/ui/src/hooks/useBg.esm.js +19 -0
- package/dist/packages/ui/src/hooks/useBg.esm.js.map +1 -0
- package/dist/packages/ui/src/hooks/useBreakpoint.esm.js +17 -0
- package/dist/packages/ui/src/hooks/useBreakpoint.esm.js.map +1 -0
- package/dist/packages/ui/src/hooks/useDefinition/helpers.esm.js +4 -0
- package/dist/packages/ui/src/hooks/useDefinition/helpers.esm.js.map +1 -0
- package/dist/plugins/app/package.json.esm.js +9 -2
- package/dist/plugins/app/package.json.esm.js.map +1 -1
- package/package.json +24 -17
package/dist/packages/frontend-app-api/src/apis/implementations/IconsApi/DefaultIconsApi.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultIconsApi.esm.js","sources":["../../../../../../../../../packages/frontend-app-api/src/apis/implementations/IconsApi/DefaultIconsApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n IconComponent,\n IconElement,\n IconsApi,\n} from '@backstage/frontend-plugin-api';\nimport { createElement, isValidElement } from 'react';\n\n/**\n * Implementation for the {@link IconsApi}\n *\n * @internal\n */\nexport class DefaultIconsApi implements IconsApi {\n #icons: Map<string, IconElement>;\n #components = new Map<string, IconComponent>();\n\n constructor(icons: { [key in string]: IconComponent | IconElement }) {\n const deprecatedKeys: string[] = [];\n\n this.#icons = new Map(\n Object.entries(icons).map(([key, value]) => {\n if (value === null || isValidElement(value)) {\n return [key, value];\n }\n deprecatedKeys.push(key);\n return [key
|
|
1
|
+
{"version":3,"file":"DefaultIconsApi.esm.js","sources":["../../../../../../../../../packages/frontend-app-api/src/apis/implementations/IconsApi/DefaultIconsApi.ts"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n IconComponent,\n IconElement,\n IconsApi,\n} from '@backstage/frontend-plugin-api';\nimport { cloneElement, createElement, isValidElement } from 'react';\n\nconst legacyFontSizeMap = {\n inherit: 'inherit',\n small: '1.25rem',\n medium: '1.5rem',\n large: '2.1875rem',\n} as const;\n\nfunction mergeClassNames(...classNames: Array<string | undefined>) {\n const merged = classNames.filter(Boolean).join(' ');\n if (merged) {\n return merged;\n }\n return undefined;\n}\n\n/**\n * Implementation for the {@link IconsApi}\n *\n * @internal\n */\nexport class DefaultIconsApi implements IconsApi {\n #icons: Map<string, IconElement>;\n #components = new Map<string, IconComponent>();\n\n constructor(icons: { [key in string]: IconComponent | IconElement }) {\n const deprecatedKeys: string[] = [];\n\n this.#icons = new Map(\n Object.entries(icons).map(([key, value]) => {\n if (value === null || isValidElement(value)) {\n return [key, value];\n }\n deprecatedKeys.push(key);\n return [\n key,\n createElement(value as IconComponent, { fontSize: 'inherit' }),\n ];\n }),\n );\n\n if (deprecatedKeys.length > 0) {\n const keys = deprecatedKeys.join(', ');\n // eslint-disable-next-line no-console\n console.warn(\n `The following icons were registered as IconComponent, which is deprecated. Use IconElement instead by passing <MyIcon /> rather than MyIcon: ${keys}`,\n );\n }\n }\n\n icon(key: string): IconElement | undefined {\n return this.#icons.get(key);\n }\n\n getIcon(key: string): IconComponent | undefined {\n let component = this.#components.get(key);\n if (component) {\n return component;\n }\n const el = this.#icons.get(key);\n if (el === undefined) {\n return undefined;\n }\n component = props => {\n if (el === null) {\n return null;\n }\n\n const {\n fontSize = 'medium',\n className,\n style,\n ...rest\n } = props as {\n fontSize?: keyof typeof legacyFontSizeMap;\n className?: string;\n style?: Record<string, unknown>;\n } & Record<string, unknown>;\n\n const elementProps = el.props as {\n className?: string;\n style?: Record<string, unknown>;\n };\n\n return cloneElement(el, {\n ...rest,\n className: mergeClassNames(elementProps.className, className),\n style: {\n ...elementProps.style,\n fontSize: legacyFontSizeMap[fontSize],\n ...style,\n },\n });\n };\n this.#components.set(key, component);\n return component;\n }\n\n listIconKeys(): string[] {\n return Array.from(this.#icons.keys());\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InternalExtensionDefinition.esm.js","sources":["../../../../../../../packages/frontend-internal/src/wiring/InternalExtensionDefinition.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ApiHolder,\n AppNode,\n ExtensionDefinitionAttachTo,\n ExtensionDataValue,\n ExtensionDataRef,\n OverridableExtensionDefinition,\n ExtensionDefinitionParameters,\n ExtensionInput,\n PortableSchema,\n
|
|
1
|
+
{"version":3,"file":"InternalExtensionDefinition.esm.js","sources":["../../../../../../../packages/frontend-internal/src/wiring/InternalExtensionDefinition.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ApiHolder,\n AppNode,\n ExtensionDefinitionAttachTo,\n ExtensionDataValue,\n ExtensionDataRef,\n OverridableExtensionDefinition,\n ExtensionDefinitionParameters,\n ExtensionInput,\n PortableSchema,\n} from '@backstage/frontend-plugin-api';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { ResolvedExtensionInputs } from '../../../frontend-plugin-api/src/wiring/createExtension';\nimport { OpaqueType } from '@internal/opaque';\nimport { FilterPredicate } from '@backstage/filter-predicates';\n\nexport const OpaqueExtensionDefinition = OpaqueType.create<{\n public: OverridableExtensionDefinition<ExtensionDefinitionParameters>;\n versions:\n | {\n readonly version: 'v1';\n readonly kind?: string;\n readonly namespace?: string;\n readonly name?: string;\n readonly attachTo: ExtensionDefinitionAttachTo;\n readonly disabled: boolean;\n readonly configSchema?: PortableSchema<any, any>;\n readonly inputs: {\n [inputName in string]: {\n $$type: '@backstage/ExtensionInput';\n extensionData: {\n [name in string]: ExtensionDataRef;\n };\n config: { optional: boolean; singleton: boolean };\n };\n };\n readonly output: {\n [name in string]: ExtensionDataRef;\n };\n factory(context: {\n node: AppNode;\n apis: ApiHolder;\n config: object;\n inputs: {\n [inputName in string]: unknown;\n };\n }): {\n [inputName in string]: unknown;\n };\n }\n | {\n readonly version: 'v2';\n readonly kind?: string;\n readonly namespace?: string;\n readonly name?: string;\n readonly attachTo: ExtensionDefinitionAttachTo;\n readonly disabled: boolean;\n readonly if?: FilterPredicate;\n readonly configSchema?: PortableSchema<any, any>;\n readonly inputs: { [inputName in string]: ExtensionInput };\n readonly output: Array<ExtensionDataRef>;\n factory(context: {\n node: AppNode;\n apis: ApiHolder;\n config: object;\n inputs: ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput;\n }>;\n }): Iterable<ExtensionDataValue<any, any>>;\n };\n}>({\n type: '@backstage/ExtensionDefinition',\n versions: ['v1', 'v2'],\n});\n"],"names":[],"mappings":";;AAgCyC,WAAW,MAAA,CAsDjD;AAAA,EACD,IAAA,EAAM,gCAAA;AAAA,EACN,QAAA,EAAU,CAAC,IAAA,EAAM,IAAI;AACvB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InternalFrontendPlugin.esm.js","sources":["../../../../../../../packages/frontend-internal/src/wiring/InternalFrontendPlugin.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Extension,\n FeatureFlagConfig,\n IconElement,\n OverridableFrontendPlugin,\n} from '@backstage/frontend-plugin-api';\nimport { JsonObject } from '@backstage/types';\nimport { OpaqueType } from '@internal/opaque';\n\nexport const OpaqueFrontendPlugin = OpaqueType.create<{\n public: OverridableFrontendPlugin;\n versions: {\n readonly version: 'v1';\n readonly title?: string;\n readonly icon?: IconElement;\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n readonly infoOptions?: {\n packageJson?: () => Promise<JsonObject>;\n manifest?: () => Promise<JsonObject>;\n };\n };\n}>({\n type: '@backstage/FrontendPlugin',\n versions: ['v1'],\n});\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"InternalFrontendPlugin.esm.js","sources":["../../../../../../../packages/frontend-internal/src/wiring/InternalFrontendPlugin.ts"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Extension,\n FeatureFlagConfig,\n IconElement,\n OverridableFrontendPlugin,\n} from '@backstage/frontend-plugin-api';\nimport { FilterPredicate } from '@backstage/filter-predicates';\nimport { JsonObject } from '@backstage/types';\nimport { OpaqueType } from '@internal/opaque';\n\nexport const OpaqueFrontendPlugin = OpaqueType.create<{\n public: OverridableFrontendPlugin;\n versions: {\n readonly version: 'v1';\n readonly title?: string;\n readonly icon?: IconElement;\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n readonly if?: FilterPredicate;\n readonly infoOptions?: {\n packageJson?: () => Promise<JsonObject>;\n manifest?: () => Promise<JsonObject>;\n };\n };\n}>({\n type: '@backstage/FrontendPlugin',\n versions: ['v1'],\n});\n"],"names":[],"mappings":";;AA0BoC,WAAW,MAAA,CAc5C;AAAA,EACD,IAAA,EAAM,2BAAA;AAAA,EACN,QAAA,EAAU,CAAC,IAAI;AACjB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
import 'react';
|
|
3
|
+
import { createVersionedContext, createVersionedValueMap } from '@backstage/version-bridge';
|
|
4
|
+
import './useBreakpoint.esm.js';
|
|
5
|
+
import './useDefinition/helpers.esm.js';
|
|
6
|
+
|
|
7
|
+
const BgContext = createVersionedContext("bg-context");
|
|
8
|
+
const BgReset = ({ children }) => {
|
|
9
|
+
return /* @__PURE__ */ jsx(
|
|
10
|
+
BgContext.Provider,
|
|
11
|
+
{
|
|
12
|
+
value: createVersionedValueMap({ 1: { bg: void 0 } }),
|
|
13
|
+
children
|
|
14
|
+
}
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { BgReset };
|
|
19
|
+
//# sourceMappingURL=useBg.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBg.esm.js","sources":["../../../../../../../packages/ui/src/hooks/useBg.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useContext, ReactNode } from 'react';\nimport {\n createVersionedContext,\n createVersionedValueMap,\n} from '@backstage/version-bridge';\nimport { ContainerBg, ProviderBg, Responsive } from '../types';\nimport { useBreakpoint } from './useBreakpoint';\nimport { resolveResponsiveValue } from './useDefinition/helpers';\n\n/** @public */\nexport interface BgContextValue {\n bg: ContainerBg | undefined;\n}\n\n/** @public */\nexport interface BgProviderProps {\n bg: ContainerBg;\n children: ReactNode;\n}\n\nconst BgContext = createVersionedContext<{\n 1: BgContextValue;\n}>('bg-context');\n\n/**\n * Increments a neutral bg level by one, capping at 'neutral-3'.\n * Intent backgrounds (danger, warning, success) pass through unchanged.\n *\n * The 'neutral-4' level is reserved for consumer component CSS and is\n * never set on providers.\n *\n * @internal\n */\nfunction incrementNeutralBg(bg: ContainerBg | undefined): ContainerBg {\n if (!bg) return 'neutral-1';\n if (bg === 'neutral-1') return 'neutral-2';\n if (bg === 'neutral-2') return 'neutral-3';\n if (bg === 'neutral-3') return 'neutral-3'; // capped at neutral-3\n // Intent values pass through unchanged\n return bg;\n}\n\n/**\n * Provider component that establishes the bg context for child components.\n *\n * @public\n */\nexport const BgProvider = ({ bg, children }: BgProviderProps) => {\n return (\n <BgContext.Provider value={createVersionedValueMap({ 1: { bg } })}>\n {children}\n </BgContext.Provider>\n );\n};\n\n/**\n * Resets the bg context to undefined, cutting any inherited neutral chain.\n * Use this inside overlay components (Popover, Tooltip, Dialog, Menu) so\n * their content always starts from neutral-1 regardless of where the trigger\n * is placed in the tree.\n *\n * @internal\n */\nexport const BgReset = ({ children }: { children: ReactNode }) => {\n return (\n <BgContext.Provider\n value={createVersionedValueMap({ 1: { bg: undefined } })}\n >\n {children}\n </BgContext.Provider>\n );\n};\n\n/**\n * Hook for consumer components (e.g. Button) to read the parent bg context.\n *\n * Returns the parent container's bg unchanged. The consumer component's CSS\n * handles the visual step-up (e.g. on a neutral-1 surface, the consumer\n * uses neutral-2 tokens via `data-on-bg`).\n *\n * @public\n */\nexport function useBgConsumer(): BgContextValue {\n const value = useContext(BgContext)?.atVersion(1);\n return value ?? { bg: undefined };\n}\n\n/**\n * Hook for provider components (e.g. Box, Card) to resolve and provide bg context.\n *\n * **Resolution rules:**\n *\n * - `bg` is `undefined` -- transparent, no context change, returns `{ bg: undefined }`.\n * This is the default for Box, Flex, and Grid (they do **not** auto-increment).\n * - `bg` is `'neutral'` -- when the parent bg is neutral, increments the neutral\n * level from the parent context, capping at `neutral-3`. When the parent bg is\n * an intent (`'danger'` | `'warning'` | `'success'`), the intent passes through\n * unchanged (i.e. `bg: 'neutral'` does not override the parent intent). The\n * increment is always relative to the parent; it is not possible to pin a\n * container to an explicit neutral level.\n * - `bg` is `'danger'` | `'warning'` | `'success'` -- sets the bg to that intent\n * explicitly, regardless of the parent value.\n *\n * **Capping:**\n *\n * Provider components cap at `neutral-3`. The `neutral-4` level is **not** a valid\n * prop value -- it exists only in consumer component CSS (e.g. a Button on a\n * `neutral-3` surface renders with `neutral-4` tokens via `data-on-bg`).\n *\n * The caller is responsible for wrapping children with `BgProvider` when the\n * resolved bg is defined.\n *\n * @public\n */\nexport function useBgProvider(bg?: Responsive<ProviderBg>): BgContextValue {\n const { breakpoint } = useBreakpoint();\n const context = useBgConsumer();\n\n if (bg === undefined) {\n return { bg: undefined };\n }\n\n const resolved = resolveResponsiveValue(bg, breakpoint);\n\n if (resolved === 'neutral') {\n return { bg: incrementNeutralBg(context.bg) };\n }\n\n return { bg: resolved };\n}\n"],"names":[],"mappings":";;;;;;AAoCA,MAAM,SAAA,GAAY,uBAEf,YAAY,CAAA;AAyCR,MAAM,OAAA,GAAU,CAAC,EAAE,QAAA,EAAS,KAA+B;AAChE,EAAA,uBACE,GAAA;AAAA,IAAC,SAAA,CAAU,QAAA;AAAA,IAAV;AAAA,MACC,KAAA,EAAO,wBAAwB,EAAE,CAAA,EAAG,EAAE,EAAA,EAAI,MAAA,IAAa,CAAA;AAAA,MAEtD;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import 'react';
|
|
2
|
+
import 'use-sync-external-store/shim';
|
|
3
|
+
|
|
4
|
+
const breakpoints = [
|
|
5
|
+
{ name: "Initial", id: "initial", value: 0 },
|
|
6
|
+
{ name: "Extra Small", id: "xs", value: 640 },
|
|
7
|
+
{ name: "Small", id: "sm", value: 768 },
|
|
8
|
+
{ name: "Medium", id: "md", value: 1024 },
|
|
9
|
+
{ name: "Large", id: "lg", value: 1280 },
|
|
10
|
+
{ name: "Extra Large", id: "xl", value: 1536 }
|
|
11
|
+
];
|
|
12
|
+
new Map(
|
|
13
|
+
breakpoints.map((bp, i) => [bp.id, i])
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
export { breakpoints };
|
|
17
|
+
//# sourceMappingURL=useBreakpoint.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useBreakpoint.esm.js","sources":["../../../../../../../packages/ui/src/hooks/useBreakpoint.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { useMemo } from 'react';\nimport { useSyncExternalStore } from 'use-sync-external-store/shim';\nimport type { Breakpoint } from '../types';\n\nexport const breakpoints: { name: string; id: Breakpoint; value: number }[] = [\n { name: 'Initial', id: 'initial', value: 0 },\n { name: 'Extra Small', id: 'xs', value: 640 },\n { name: 'Small', id: 'sm', value: 768 },\n { name: 'Medium', id: 'md', value: 1024 },\n { name: 'Large', id: 'lg', value: 1280 },\n { name: 'Extra Large', id: 'xl', value: 1536 },\n];\n\nconst breakpointIndex = new Map<Breakpoint, number>(\n breakpoints.map((bp, i) => [bp.id, i]),\n);\n\nfunction bpIndex(key: Breakpoint): number {\n return breakpointIndex.get(key) ?? 0;\n}\n\nconst IS_SERVER =\n typeof window === 'undefined' || typeof window.matchMedia === 'undefined';\n\nfunction computeBreakpoint(): Breakpoint {\n if (IS_SERVER) {\n return 'initial';\n }\n for (let i = breakpoints.length - 1; i >= 0; i--) {\n if (window.matchMedia(`(min-width: ${breakpoints[i].value}px)`).matches) {\n return breakpoints[i].id;\n }\n }\n return 'initial';\n}\n\n// --- Module-scoped singleton store ---\n// This is intentionally not a global singleton. Multiple copies of this module\n// (e.g. different package versions or module federation remotes) each get their\n// own store. This avoids cross-version coupling at the cost of a few extra\n// listeners, which is a fine trade-off.\n// `current` is initialized lazily on first client-side access.\n\nlet current: Breakpoint | undefined;\nconst listeners = new Set<() => void>();\nlet initialized = false;\n\nfunction ensureInitialized(): void {\n if (initialized || IS_SERVER) {\n return;\n }\n initialized = true;\n current = computeBreakpoint();\n\n // Register one listener per breakpoint. When any query fires, re-evaluate\n // all breakpoints to find the new active one. Notify subscribers only if\n // the active breakpoint actually changed.\n for (const bp of breakpoints) {\n const mql = window.matchMedia(`(min-width: ${bp.value}px)`);\n mql.addEventListener('change', () => {\n const next = computeBreakpoint();\n if (next !== current) {\n current = next;\n for (const cb of listeners) {\n cb();\n }\n }\n });\n }\n}\n\nfunction subscribe(callback: () => void): () => void {\n ensureInitialized();\n listeners.add(callback);\n return () => {\n listeners.delete(callback);\n };\n}\n\nfunction getSnapshot(): Breakpoint {\n ensureInitialized();\n return current ?? 'initial';\n}\n\nfunction getServerSnapshot(): Breakpoint {\n return 'initial';\n}\n\n/** @public */\nexport const useBreakpoint = () => {\n const breakpoint = useSyncExternalStore(\n subscribe,\n getSnapshot,\n getServerSnapshot,\n );\n\n return useMemo(\n () => ({\n breakpoint,\n up: (key: Breakpoint): boolean => bpIndex(breakpoint) >= bpIndex(key),\n down: (key: Breakpoint): boolean => bpIndex(breakpoint) < bpIndex(key),\n }),\n [breakpoint],\n );\n};\n"],"names":[],"mappings":";;;AAmBO,MAAM,WAAA,GAAiE;AAAA,EAC5E,EAAE,IAAA,EAAM,SAAA,EAAW,EAAA,EAAI,SAAA,EAAW,OAAO,CAAA,EAAE;AAAA,EAC3C,EAAE,IAAA,EAAM,aAAA,EAAe,EAAA,EAAI,IAAA,EAAM,OAAO,GAAA,EAAI;AAAA,EAC5C,EAAE,IAAA,EAAM,OAAA,EAAS,EAAA,EAAI,IAAA,EAAM,OAAO,GAAA,EAAI;AAAA,EACtC,EAAE,IAAA,EAAM,QAAA,EAAU,EAAA,EAAI,IAAA,EAAM,OAAO,IAAA,EAAK;AAAA,EACxC,EAAE,IAAA,EAAM,OAAA,EAAS,EAAA,EAAI,IAAA,EAAM,OAAO,IAAA,EAAK;AAAA,EACvC,EAAE,IAAA,EAAM,aAAA,EAAe,EAAA,EAAI,IAAA,EAAM,OAAO,IAAA;AAC1C;AAEwB,IAAI,GAAA;AAAA,EAC1B,WAAA,CAAY,IAAI,CAAC,EAAA,EAAI,MAAM,CAAC,EAAA,CAAG,EAAA,EAAI,CAAC,CAAC;AACvC;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.esm.js","sources":["../../../../../../../../packages/ui/src/hooks/useDefinition/helpers.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { breakpoints } from '../useBreakpoint';\nimport { utilityClassMap } from '../../utils/utilityClassMap';\nimport type { ComponentConfig, UnwrapResponsive, UtilityStyle } from './types';\n\nconst namedBreakpoints = breakpoints.filter(b => b.id !== 'initial');\n\nfunction isResponsiveObject(value: unknown): value is Record<string, unknown> {\n return (\n typeof value === 'object' &&\n value !== null &&\n namedBreakpoints.some(b => b.id in value)\n );\n}\n\nexport function resolveResponsiveValue<T>(\n value: T,\n breakpoint: string,\n): UnwrapResponsive<T> {\n if (!isResponsiveObject(value)) {\n return value as UnwrapResponsive<T>;\n }\n\n const index = breakpoints.findIndex(b => b.id === breakpoint);\n\n // Look for value at current breakpoint or smaller\n for (let i = index; i >= 0; i--) {\n const key = breakpoints[i].id;\n if (key in value && value[key] !== undefined) {\n return value[key] as UnwrapResponsive<T>;\n }\n }\n\n // If no value found, check from smallest breakpoint up\n for (let i = 0; i < breakpoints.length; i++) {\n const key = breakpoints[i].id;\n if (key in value && value[key] !== undefined) {\n return value[key] as UnwrapResponsive<T>;\n }\n }\n\n return value as UnwrapResponsive<T>;\n}\n\nexport function resolveDefinitionProps<D extends ComponentConfig<any, any>>(\n definition: D,\n props: Record<string, any>,\n breakpoint: string,\n): {\n ownPropsResolved: Record<string, any>;\n restProps: Record<string, any>;\n} {\n const ownPropKeys = new Set(Object.keys(definition.propDefs));\n const utilityPropKeys = new Set(definition.utilityProps ?? []);\n\n const ownPropsRaw: Record<string, any> = {};\n const restProps: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(props)) {\n if (ownPropKeys.has(key)) {\n ownPropsRaw[key] = value;\n } else if (!(utilityPropKeys as Set<string>).has(key)) {\n restProps[key] = value;\n }\n }\n\n const ownPropsResolved: Record<string, any> = {};\n\n for (const [key, config] of Object.entries(definition.propDefs)) {\n const rawValue = ownPropsRaw[key];\n const resolvedValue = resolveResponsiveValue(rawValue, breakpoint);\n const finalValue = resolvedValue ?? (config as any).default;\n if (finalValue !== undefined) {\n ownPropsResolved[key] = finalValue;\n }\n }\n\n return { ownPropsResolved, restProps };\n}\n\nexport function processUtilityProps<Keys extends string>(\n props: Record<string, any>,\n utilityPropKeys: readonly Keys[],\n): { utilityClasses: string; utilityStyle: UtilityStyle<Keys> } {\n const utilityClassList: string[] = [];\n const generatedStyle: Record<string, unknown> = {};\n\n const handleUtilityValue = (\n key: string,\n val: unknown,\n prefix: string = '',\n ) => {\n // Get utility class configuration for this key\n const utilityConfig = utilityClassMap[key as keyof typeof utilityClassMap];\n\n if (!utilityConfig) {\n // Skip if no config found for this key\n return;\n }\n\n // Check if value is in the list of valid values for this utility\n const values = utilityConfig.values as readonly (string | number)[];\n if (values.length > 0 && values.includes(val as string | number)) {\n // Generate utility class with value suffix and optional breakpoint prefix\n const className = prefix\n ? `${prefix}${utilityConfig.class}-${val}`\n : `${utilityConfig.class}-${val}`;\n utilityClassList.push(className);\n } else if ('cssVar' in utilityConfig && utilityConfig.cssVar) {\n // Custom value - add CSS custom property AND utility class name\n // Only if cssVar is defined (properties with fixed values don't have cssVar)\n const cssVar = utilityConfig.cssVar;\n const cssVarKey = prefix ? `${cssVar}-${prefix.slice(0, -1)}` : cssVar;\n // CSS custom properties need to be set on the style object\n generatedStyle[cssVarKey] = val;\n\n // Add utility class name (without value suffix) with optional breakpoint prefix\n const className = prefix\n ? `${prefix}${utilityConfig.class}`\n : utilityConfig.class;\n utilityClassList.push(className);\n }\n // If no cssVar and value is not in valid values, skip (invalid value for fixed-value property)\n };\n\n for (const key of utilityPropKeys) {\n const value = props[key];\n if (value === undefined || value === null) {\n continue;\n }\n\n // Check if value is a responsive object\n if (typeof value === 'object' && value !== null) {\n const breakpointValues = value as { [key: string]: unknown };\n // Handle responsive object values\n for (const bp in breakpointValues) {\n const prefix = bp === 'initial' ? '' : `${bp}:`;\n handleUtilityValue(key, breakpointValues[bp], prefix);\n }\n } else {\n // Handle simple value\n handleUtilityValue(key, value);\n }\n }\n\n return {\n utilityClasses: utilityClassList.join(' '),\n utilityStyle: generatedStyle as UtilityStyle<Keys>,\n };\n}\n"],"names":[],"mappings":";;AAoByB,WAAA,CAAY,MAAA,CAAO,CAAA,CAAA,KAAK,CAAA,CAAE,OAAO,SAAS"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
var name = "@backstage/plugin-app";
|
|
2
|
-
var version = "0.4.
|
|
2
|
+
var version = "0.4.2";
|
|
3
3
|
var backstage = {
|
|
4
4
|
role: "frontend-plugin",
|
|
5
5
|
pluginId: "app",
|
|
@@ -52,6 +52,7 @@ var scripts = {
|
|
|
52
52
|
var dependencies = {
|
|
53
53
|
"@backstage/core-components": "workspace:^",
|
|
54
54
|
"@backstage/core-plugin-api": "workspace:^",
|
|
55
|
+
"@backstage/filter-predicates": "workspace:^",
|
|
55
56
|
"@backstage/frontend-plugin-api": "workspace:^",
|
|
56
57
|
"@backstage/integration-react": "workspace:^",
|
|
57
58
|
"@backstage/plugin-app-react": "workspace:^",
|
|
@@ -63,9 +64,15 @@ var dependencies = {
|
|
|
63
64
|
"@material-ui/core": "^4.9.13",
|
|
64
65
|
"@material-ui/icons": "^4.9.1",
|
|
65
66
|
"@material-ui/lab": "^4.0.0-alpha.61",
|
|
67
|
+
"@react-aria/button": "^3.14.3",
|
|
68
|
+
"@react-aria/toast": "^3.0.9",
|
|
66
69
|
"@react-hookz/web": "^24.0.0",
|
|
70
|
+
"@react-stately/toast": "^3.1.2",
|
|
71
|
+
"@remixicon/react": "^4.6.0",
|
|
72
|
+
motion: "^12.0.0",
|
|
67
73
|
"react-use": "^17.2.4",
|
|
68
|
-
|
|
74
|
+
"zen-observable": "^0.10.0",
|
|
75
|
+
zod: "^3.25.76 || ^4.0.0"
|
|
69
76
|
};
|
|
70
77
|
var devDependencies = {
|
|
71
78
|
"@backstage/cli": "workspace:^",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"package.json.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"package.json.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-app",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "frontend-plugin",
|
|
6
6
|
"pluginId": "app",
|
|
@@ -63,29 +63,36 @@
|
|
|
63
63
|
"test": "backstage-cli package test"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@backstage/core-components": "0.18.8
|
|
67
|
-
"@backstage/core-plugin-api": "1.12.4
|
|
68
|
-
"@backstage/
|
|
69
|
-
"@backstage/
|
|
70
|
-
"@backstage/
|
|
71
|
-
"@backstage/plugin-
|
|
72
|
-
"@backstage/
|
|
73
|
-
"@backstage/
|
|
74
|
-
"@backstage/
|
|
75
|
-
"@backstage/
|
|
66
|
+
"@backstage/core-components": "^0.18.8",
|
|
67
|
+
"@backstage/core-plugin-api": "^1.12.4",
|
|
68
|
+
"@backstage/filter-predicates": "^0.1.1",
|
|
69
|
+
"@backstage/frontend-plugin-api": "^0.15.1",
|
|
70
|
+
"@backstage/integration-react": "^1.2.16",
|
|
71
|
+
"@backstage/plugin-app-react": "^0.2.1",
|
|
72
|
+
"@backstage/plugin-permission-react": "^0.4.41",
|
|
73
|
+
"@backstage/theme": "^0.7.2",
|
|
74
|
+
"@backstage/types": "^1.2.2",
|
|
75
|
+
"@backstage/ui": "^0.13.1",
|
|
76
|
+
"@backstage/version-bridge": "^1.0.12",
|
|
76
77
|
"@material-ui/core": "^4.9.13",
|
|
77
78
|
"@material-ui/icons": "^4.9.1",
|
|
78
79
|
"@material-ui/lab": "^4.0.0-alpha.61",
|
|
80
|
+
"@react-aria/button": "^3.14.3",
|
|
81
|
+
"@react-aria/toast": "^3.0.9",
|
|
79
82
|
"@react-hookz/web": "^24.0.0",
|
|
83
|
+
"@react-stately/toast": "^3.1.2",
|
|
84
|
+
"@remixicon/react": "^4.6.0",
|
|
85
|
+
"motion": "^12.0.0",
|
|
80
86
|
"react-use": "^17.2.4",
|
|
81
|
-
"
|
|
87
|
+
"zen-observable": "^0.10.0",
|
|
88
|
+
"zod": "^3.25.76 || ^4.0.0"
|
|
82
89
|
},
|
|
83
90
|
"devDependencies": {
|
|
84
|
-
"@backstage/cli": "0.36.0
|
|
85
|
-
"@backstage/dev-utils": "1.1.21
|
|
86
|
-
"@backstage/frontend-defaults": "0.5.0
|
|
87
|
-
"@backstage/frontend-test-utils": "0.5.1
|
|
88
|
-
"@backstage/test-utils": "1.7.16
|
|
91
|
+
"@backstage/cli": "^0.36.0",
|
|
92
|
+
"@backstage/dev-utils": "^1.1.21",
|
|
93
|
+
"@backstage/frontend-defaults": "^0.5.0",
|
|
94
|
+
"@backstage/frontend-test-utils": "^0.5.1",
|
|
95
|
+
"@backstage/test-utils": "^1.7.16",
|
|
89
96
|
"@testing-library/jest-dom": "^6.0.0",
|
|
90
97
|
"@testing-library/react": "^16.0.0",
|
|
91
98
|
"@testing-library/user-event": "^14.0.0",
|