@backstage/core-components 0.15.0 → 0.15.1-next.1

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 CHANGED
@@ -1,5 +1,31 @@
1
1
  # @backstage/core-components
2
2
 
3
+ ## 0.15.1-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 3f76d0e: Correct size of FavoriteToggle and inherit non-starred color from parent
8
+ - e969dc7: Move `@types/react` to a peer dependency.
9
+ - 83e2887: Fixed a bug in the `SidebarSubmenu` core component that caused the nested menu to overlap with the sidebar when the user hovers over the pinned sidebar.
10
+ - Updated dependencies
11
+ - @backstage/core-plugin-api@1.10.0-next.1
12
+ - @backstage/version-bridge@1.0.10-next.0
13
+ - @backstage/theme@0.5.8-next.0
14
+ - @backstage/config@1.2.0
15
+ - @backstage/errors@1.2.4
16
+
17
+ ## 0.15.1-next.0
18
+
19
+ ### Patch Changes
20
+
21
+ - 46b5a20: `Link` component now accepts `externalLinkIcon` prop
22
+ - Updated dependencies
23
+ - @backstage/core-plugin-api@1.10.0-next.0
24
+ - @backstage/config@1.2.0
25
+ - @backstage/errors@1.2.4
26
+ - @backstage/theme@0.5.7
27
+ - @backstage/version-bridge@1.0.9
28
+
3
29
  ## 0.15.0
4
30
 
5
31
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/core-components__alpha",
3
- "version": "0.15.0",
3
+ "version": "0.15.1-next.1",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
@@ -6,14 +6,16 @@ import { makeStyles } from '@material-ui/core/styles';
6
6
  import { StarIcon, UnstarredIcon } from '../../icons/icons.esm.js';
7
7
 
8
8
  const useStyles = makeStyles(
9
- (theme) => ({
9
+ () => ({
10
10
  icon: {
11
11
  color: "#f3ba37",
12
- cursor: "pointer"
12
+ cursor: "pointer",
13
+ display: "inline-flex"
13
14
  },
14
15
  iconBorder: {
15
- color: theme.palette.text.primary,
16
- cursor: "pointer"
16
+ color: "inherit",
17
+ cursor: "pointer",
18
+ display: "inline-flex"
17
19
  }
18
20
  }),
19
21
  { name: "BackstageFavoriteToggleIcon" }
@@ -44,6 +46,7 @@ function FavoriteToggle(props) {
44
46
  "aria-label": title,
45
47
  id,
46
48
  onClick: () => onChange(!value),
49
+ color: "inherit",
47
50
  ...iconButtonProps
48
51
  },
49
52
  /* @__PURE__ */ React__default.createElement(FavoriteToggleIcon, { isFavorite: value })
@@ -1 +1 @@
1
- {"version":3,"file":"FavoriteToggle.esm.js","sources":["../../../src/components/FavoriteToggle/FavoriteToggle.tsx"],"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 */\nimport React, { ComponentProps } from 'react';\nimport IconButton from '@material-ui/core/IconButton';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport Typography from '@material-ui/core/Typography';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { StarIcon, UnstarredIcon } from '../../icons';\n\nconst useStyles = makeStyles<Theme>(\n theme => ({\n icon: {\n color: '#f3ba37',\n cursor: 'pointer',\n },\n iconBorder: {\n color: theme.palette.text.primary,\n cursor: 'pointer',\n },\n }),\n { name: 'BackstageFavoriteToggleIcon' },\n);\n\n/**\n * @public\n */\nexport type FavoriteToggleIconClassKey = 'icon' | 'iconBorder';\n\n/**\n * Icon used in FavoriteToggle component.\n *\n * Can be used independently, useful when used as {@link @material-table/core#MaterialTableProps.actions} in {@link @material-table/core#MaterialTable}\n *\n * @public\n */\nexport function FavoriteToggleIcon(props: { isFavorite: boolean }) {\n const { isFavorite } = props;\n const classes = useStyles();\n\n return (\n <Typography\n component=\"span\"\n className={isFavorite ? classes.icon : classes.iconBorder}\n >\n {isFavorite ? <StarIcon /> : <UnstarredIcon />}\n </Typography>\n );\n}\n\n/**\n * Toggle encapsulating logic for marking something as favorite,\n * primarily used in various instances of entity lists and cards but can be used elsewhere.\n *\n * This component can only be used in as a controlled toggle and does not keep internal state.\n *\n * @public\n */\nexport function FavoriteToggle(\n props: ComponentProps<typeof IconButton> & {\n id: string;\n title: string;\n isFavorite: boolean;\n onToggle: (value: boolean) => void;\n },\n) {\n const {\n id,\n title,\n isFavorite: value,\n onToggle: onChange,\n ...iconButtonProps\n } = props;\n return (\n <Tooltip id={id} title={title}>\n <IconButton\n aria-label={title}\n id={id}\n onClick={() => onChange(!value)}\n {...iconButtonProps}\n >\n <FavoriteToggleIcon isFavorite={value} />\n </IconButton>\n </Tooltip>\n );\n}\n"],"names":["React"],"mappings":";;;;;;;AAsBA,MAAM,SAAY,GAAA,UAAA;AAAA,EAChB,CAAU,KAAA,MAAA;AAAA,IACR,IAAM,EAAA;AAAA,MACJ,KAAO,EAAA,SAAA;AAAA,MACP,MAAQ,EAAA,SAAA;AAAA,KACV;AAAA,IACA,UAAY,EAAA;AAAA,MACV,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA,OAAA;AAAA,MAC1B,MAAQ,EAAA,SAAA;AAAA,KACV;AAAA,GACF,CAAA;AAAA,EACA,EAAE,MAAM,6BAA8B,EAAA;AACxC,CAAA,CAAA;AAcO,SAAS,mBAAmB,KAAgC,EAAA;AACjE,EAAM,MAAA,EAAE,YAAe,GAAA,KAAA,CAAA;AACvB,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAE1B,EACE,uBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,SAAU,EAAA,MAAA;AAAA,MACV,SAAW,EAAA,UAAA,GAAa,OAAQ,CAAA,IAAA,GAAO,OAAQ,CAAA,UAAA;AAAA,KAAA;AAAA,IAE9C,UAAa,mBAAAA,cAAA,CAAA,aAAA,CAAC,QAAS,EAAA,IAAA,CAAA,gDAAM,aAAc,EAAA,IAAA,CAAA;AAAA,GAC9C,CAAA;AAEJ,CAAA;AAUO,SAAS,eACd,KAMA,EAAA;AACA,EAAM,MAAA;AAAA,IACJ,EAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAY,EAAA,KAAA;AAAA,IACZ,QAAU,EAAA,QAAA;AAAA,IACV,GAAG,eAAA;AAAA,GACD,GAAA,KAAA,CAAA;AACJ,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,EAAA,EAAQ,KACf,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,YAAY,EAAA,KAAA;AAAA,MACZ,EAAA;AAAA,MACA,OAAS,EAAA,MAAM,QAAS,CAAA,CAAC,KAAK,CAAA;AAAA,MAC7B,GAAG,eAAA;AAAA,KAAA;AAAA,oBAEJA,cAAA,CAAA,aAAA,CAAC,kBAAmB,EAAA,EAAA,UAAA,EAAY,KAAO,EAAA,CAAA;AAAA,GAE3C,CAAA,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"FavoriteToggle.esm.js","sources":["../../../src/components/FavoriteToggle/FavoriteToggle.tsx"],"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 */\nimport React, { ComponentProps } from 'react';\nimport IconButton from '@material-ui/core/IconButton';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport Typography from '@material-ui/core/Typography';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { StarIcon, UnstarredIcon } from '../../icons';\n\nconst useStyles = makeStyles<Theme>(\n () => ({\n icon: {\n color: '#f3ba37',\n cursor: 'pointer',\n display: 'inline-flex',\n },\n iconBorder: {\n color: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n },\n }),\n { name: 'BackstageFavoriteToggleIcon' },\n);\n\n/**\n * @public\n */\nexport type FavoriteToggleIconClassKey = 'icon' | 'iconBorder';\n\n/**\n * Icon used in FavoriteToggle component.\n *\n * Can be used independently, useful when used as {@link @material-table/core#MaterialTableProps.actions} in {@link @material-table/core#MaterialTable}\n *\n * @public\n */\nexport function FavoriteToggleIcon(props: { isFavorite: boolean }) {\n const { isFavorite } = props;\n const classes = useStyles();\n\n return (\n <Typography\n component=\"span\"\n className={isFavorite ? classes.icon : classes.iconBorder}\n >\n {isFavorite ? <StarIcon /> : <UnstarredIcon />}\n </Typography>\n );\n}\n\n/**\n * Toggle encapsulating logic for marking something as favorite,\n * primarily used in various instances of entity lists and cards but can be used elsewhere.\n *\n * This component can only be used in as a controlled toggle and does not keep internal state.\n *\n * @public\n */\nexport function FavoriteToggle(\n props: ComponentProps<typeof IconButton> & {\n id: string;\n title: string;\n isFavorite: boolean;\n onToggle: (value: boolean) => void;\n },\n) {\n const {\n id,\n title,\n isFavorite: value,\n onToggle: onChange,\n ...iconButtonProps\n } = props;\n return (\n <Tooltip id={id} title={title}>\n <IconButton\n aria-label={title}\n id={id}\n onClick={() => onChange(!value)}\n color=\"inherit\"\n {...iconButtonProps}\n >\n <FavoriteToggleIcon isFavorite={value} />\n </IconButton>\n </Tooltip>\n );\n}\n"],"names":["React"],"mappings":";;;;;;;AAsBA,MAAM,SAAY,GAAA,UAAA;AAAA,EAChB,OAAO;AAAA,IACL,IAAM,EAAA;AAAA,MACJ,KAAO,EAAA,SAAA;AAAA,MACP,MAAQ,EAAA,SAAA;AAAA,MACR,OAAS,EAAA,aAAA;AAAA,KACX;AAAA,IACA,UAAY,EAAA;AAAA,MACV,KAAO,EAAA,SAAA;AAAA,MACP,MAAQ,EAAA,SAAA;AAAA,MACR,OAAS,EAAA,aAAA;AAAA,KACX;AAAA,GACF,CAAA;AAAA,EACA,EAAE,MAAM,6BAA8B,EAAA;AACxC,CAAA,CAAA;AAcO,SAAS,mBAAmB,KAAgC,EAAA;AACjE,EAAM,MAAA,EAAE,YAAe,GAAA,KAAA,CAAA;AACvB,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAE1B,EACE,uBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,SAAU,EAAA,MAAA;AAAA,MACV,SAAW,EAAA,UAAA,GAAa,OAAQ,CAAA,IAAA,GAAO,OAAQ,CAAA,UAAA;AAAA,KAAA;AAAA,IAE9C,UAAa,mBAAAA,cAAA,CAAA,aAAA,CAAC,QAAS,EAAA,IAAA,CAAA,gDAAM,aAAc,EAAA,IAAA,CAAA;AAAA,GAC9C,CAAA;AAEJ,CAAA;AAUO,SAAS,eACd,KAMA,EAAA;AACA,EAAM,MAAA;AAAA,IACJ,EAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAY,EAAA,KAAA;AAAA,IACZ,QAAU,EAAA,QAAA;AAAA,IACV,GAAG,eAAA;AAAA,GACD,GAAA,KAAA,CAAA;AACJ,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,OAAQ,EAAA,EAAA,EAAA,EAAQ,KACf,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,UAAA;AAAA,IAAA;AAAA,MACC,YAAY,EAAA,KAAA;AAAA,MACZ,EAAA;AAAA,MACA,OAAS,EAAA,MAAM,QAAS,CAAA,CAAC,KAAK,CAAA;AAAA,MAC9B,KAAM,EAAA,SAAA;AAAA,MACL,GAAG,eAAA;AAAA,KAAA;AAAA,oBAEJA,cAAA,CAAA,aAAA,CAAC,kBAAmB,EAAA,EAAA,UAAA,EAAY,KAAO,EAAA,CAAA;AAAA,GAE3C,CAAA,CAAA;AAEJ;;;;"}
@@ -1,4 +1,4 @@
1
- import { useAnalytics, useApi, configApiRef } from '@backstage/core-plugin-api';
1
+ import { useAnalytics, useApp, useApi, configApiRef } from '@backstage/core-plugin-api';
2
2
  import MaterialLink from '@material-ui/core/Link';
3
3
  import { makeStyles } from '@material-ui/core/styles';
4
4
  import Typography from '@material-ui/core/Typography';
@@ -6,13 +6,14 @@ import classNames from 'classnames';
6
6
  import { trimEnd } from 'lodash';
7
7
  import React__default from 'react';
8
8
  import { Link as Link$1, createRoutesFromChildren, Route } from 'react-router-dom';
9
+ import OpenInNew from '@material-ui/icons/OpenInNew';
9
10
 
10
11
  function isReactRouterBeta() {
11
12
  const [obj] = createRoutesFromChildren(/* @__PURE__ */ React__default.createElement(Route, { index: true, element: /* @__PURE__ */ React__default.createElement("div", null) }));
12
13
  return !obj.index;
13
14
  }
14
15
  const useStyles = makeStyles(
15
- {
16
+ (theme) => ({
16
17
  visuallyHidden: {
17
18
  clip: "rect(0 0 0 0)",
18
19
  clipPath: "inset(50%)",
@@ -25,10 +26,20 @@ const useStyles = makeStyles(
25
26
  },
26
27
  externalLink: {
27
28
  position: "relative"
29
+ },
30
+ externalLinkIcon: {
31
+ verticalAlign: "bottom",
32
+ marginLeft: theme.spacing(0.5)
28
33
  }
29
- },
34
+ }),
30
35
  { name: "Link" }
31
36
  );
37
+ const ExternalLinkIcon = () => {
38
+ const app = useApp();
39
+ const Icon = app.getSystemIcon("externalLink") || OpenInNew;
40
+ const classes = useStyles();
41
+ return /* @__PURE__ */ React__default.createElement(Icon, { className: classes.externalLinkIcon });
42
+ };
32
43
  const isExternalUri = (uri) => /^([a-z+.-]+):/.test(uri);
33
44
  const scriptProtocolPattern = (
34
45
  // eslint-disable-next-line no-control-regex
@@ -85,7 +96,7 @@ const getNodeText = (node) => {
85
96
  return "";
86
97
  };
87
98
  const Link = React__default.forwardRef(
88
- ({ onClick, noTrack, ...props }, ref) => {
99
+ ({ onClick, noTrack, externalLinkIcon, ...props }, ref) => {
89
100
  const classes = useStyles();
90
101
  const analytics = useAnalytics();
91
102
  const to = isReactRouterBeta() ? useResolvedPath(props.to) : props.to;
@@ -117,6 +128,7 @@ const Link = React__default.forwardRef(
117
128
  className: classNames(classes.externalLink, props.className)
118
129
  },
119
130
  props.children,
131
+ externalLinkIcon && /* @__PURE__ */ React__default.createElement(ExternalLinkIcon, null),
120
132
  /* @__PURE__ */ React__default.createElement(Typography, { component: "span", className: classes.visuallyHidden }, ", Opens in a new window")
121
133
  )
122
134
  ) : (
@@ -1 +1 @@
1
- {"version":3,"file":"Link.esm.js","sources":["../../../src/components/Link/Link.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';\n// eslint-disable-next-line no-restricted-imports\nimport MaterialLink, {\n LinkProps as MaterialLinkProps,\n} from '@material-ui/core/Link';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport classnames from 'classnames';\nimport { trimEnd } from 'lodash';\nimport React, { ElementType } from 'react';\nimport {\n createRoutesFromChildren,\n Link as RouterLink,\n LinkProps as RouterLinkProps,\n Route,\n} from 'react-router-dom';\n\nexport function isReactRouterBeta(): boolean {\n const [obj] = createRoutesFromChildren(<Route index element={<div />} />);\n return !obj.index;\n}\n\n/** @public */\nexport type LinkClassKey = 'visuallyHidden' | 'externalLink';\n\nconst useStyles = makeStyles(\n {\n visuallyHidden: {\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n overflow: 'hidden',\n position: 'absolute',\n userSelect: 'none',\n whiteSpace: 'nowrap',\n height: 1,\n width: 1,\n },\n externalLink: {\n position: 'relative',\n },\n },\n { name: 'Link' },\n);\n\nexport const isExternalUri = (uri: string) => /^([a-z+.-]+):/.test(uri);\n\n// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js\nconst scriptProtocolPattern =\n // eslint-disable-next-line no-control-regex\n /^[\\u0000-\\u001F ]*j[\\r\\n\\t]*a[\\r\\n\\t]*v[\\r\\n\\t]*a[\\r\\n\\t]*s[\\r\\n\\t]*c[\\r\\n\\t]*r[\\r\\n\\t]*i[\\r\\n\\t]*p[\\r\\n\\t]*t[\\r\\n\\t]*\\:/i;\n\n// We install this globally in order to prevent javascript: URL XSS attacks via window.open\nconst originalWindowOpen = window.open as typeof window.open & {\n __backstage?: true;\n};\nif (originalWindowOpen && !originalWindowOpen.__backstage) {\n const newOpen = function open(\n this: Window,\n ...args: Parameters<typeof window.open>\n ) {\n const url = String(args[0]);\n if (scriptProtocolPattern.test(url)) {\n throw new Error(\n 'Rejected window.open() with a javascript: URL as a security precaution',\n );\n }\n return originalWindowOpen.apply(this, args);\n };\n newOpen.__backstage = true;\n window.open = newOpen;\n}\n\nexport type LinkProps = Omit<MaterialLinkProps, 'to'> &\n Omit<RouterLinkProps, 'to'> & {\n to: string;\n component?: ElementType<any>;\n noTrack?: boolean;\n };\n\n/**\n * Returns the app base url that could be empty if the Config API is not properly implemented.\n * The only cases there would be no Config API are in tests and in storybook stories, and in those cases, it's unlikely that callers would rely on this subpath behavior.\n */\nconst useBaseUrl = () => {\n try {\n const config = useApi(configApiRef);\n return config.getOptionalString('app.baseUrl');\n } catch {\n return undefined;\n }\n};\n\n/**\n * Get the app base path from the configured app baseUrl.\n * The returned path does not have a trailing slash.\n */\nconst useBasePath = () => {\n // baseUrl can be specified as just a path\n const base = 'http://sample.dev';\n const url = useBaseUrl() ?? '/';\n const { pathname } = new URL(url, base);\n return trimEnd(pathname, '/');\n};\n\n/** @deprecated Remove once we no longer support React Router v6 beta */\nexport const useResolvedPath = (uri: LinkProps['to']) => {\n let resolvedPath = String(uri);\n\n const basePath = useBasePath();\n const external = isExternalUri(resolvedPath);\n const startsWithBasePath = resolvedPath.startsWith(basePath);\n\n if (!external && !startsWithBasePath) {\n resolvedPath = basePath.concat(resolvedPath);\n }\n\n return resolvedPath;\n};\n\n/**\n * Given a react node, try to retrieve its text content.\n */\nconst getNodeText = (node: React.ReactNode): string => {\n // If the node is an array of children, recurse and join.\n if (node instanceof Array) {\n return node.map(getNodeText).join(' ').trim();\n }\n\n // If the node is a react element, recurse on its children.\n if (typeof node === 'object' && node) {\n return getNodeText((node as React.ReactElement)?.props?.children);\n }\n\n // Base case: the node is just text. Return it.\n if (['string', 'number'].includes(typeof node)) {\n return String(node);\n }\n\n // Base case: just return an empty string.\n return '';\n};\n\n/**\n * Thin wrapper on top of material-ui's Link component, which...\n * - Makes the Link use react-router\n * - Captures Link clicks as analytics events.\n */\nexport const Link = React.forwardRef<any, LinkProps>(\n ({ onClick, noTrack, ...props }, ref) => {\n const classes = useStyles();\n const analytics = useAnalytics();\n\n // Adding the base path to URLs breaks react-router v6 stable, so we only\n // do it for beta. The react router version won't change at runtime so it is\n // fine to ignore the rules of hooks.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const to = isReactRouterBeta() ? useResolvedPath(props.to) : props.to;\n const linkText = getNodeText(props.children) || to;\n const external = isExternalUri(to);\n const newWindow = external && !!/^https?:/.exec(to);\n\n if (scriptProtocolPattern.test(to)) {\n throw new Error(\n 'Link component rejected javascript: URL as a security precaution',\n );\n }\n\n const handleClick = (event: React.MouseEvent<any, MouseEvent>) => {\n onClick?.(event);\n if (!noTrack) {\n analytics.captureEvent('click', linkText, { attributes: { to } });\n }\n };\n\n return external ? (\n // External links\n <MaterialLink\n {...(newWindow ? { target: '_blank', rel: 'noopener' } : {})}\n {...props}\n {...(props['aria-label']\n ? { 'aria-label': `${props['aria-label']}, Opens in a new window` }\n : {})}\n ref={ref}\n href={to}\n onClick={handleClick}\n className={classnames(classes.externalLink, props.className)}\n >\n {props.children}\n <Typography component=\"span\" className={classes.visuallyHidden}>\n , Opens in a new window\n </Typography>\n </MaterialLink>\n ) : (\n // Interact with React Router for internal links\n <MaterialLink\n {...props}\n ref={ref}\n component={RouterLink}\n to={to}\n onClick={handleClick}\n />\n );\n },\n) as (props: LinkProps) => JSX.Element;\n"],"names":["React","classnames","RouterLink"],"mappings":"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"}
1
+ {"version":3,"file":"Link.esm.js","sources":["../../../src/components/Link/Link.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 { configApiRef, useAnalytics, useApi } from '@backstage/core-plugin-api';\n// eslint-disable-next-line no-restricted-imports\nimport MaterialLink, {\n LinkProps as MaterialLinkProps,\n} from '@material-ui/core/Link';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport classnames from 'classnames';\nimport { trimEnd } from 'lodash';\nimport React, { ElementType } from 'react';\nimport {\n createRoutesFromChildren,\n Link as RouterLink,\n LinkProps as RouterLinkProps,\n Route,\n} from 'react-router-dom';\nimport OpenInNew from '@material-ui/icons/OpenInNew';\nimport { useApp } from '@backstage/core-plugin-api';\n\nexport function isReactRouterBeta(): boolean {\n const [obj] = createRoutesFromChildren(<Route index element={<div />} />);\n return !obj.index;\n}\n\n/** @public */\nexport type LinkClassKey = 'visuallyHidden' | 'externalLink';\n\nconst useStyles = makeStyles(\n theme => ({\n visuallyHidden: {\n clip: 'rect(0 0 0 0)',\n clipPath: 'inset(50%)',\n overflow: 'hidden',\n position: 'absolute',\n userSelect: 'none',\n whiteSpace: 'nowrap',\n height: 1,\n width: 1,\n },\n externalLink: {\n position: 'relative',\n },\n externalLinkIcon: {\n verticalAlign: 'bottom',\n marginLeft: theme.spacing(0.5),\n },\n }),\n { name: 'Link' },\n);\n\nconst ExternalLinkIcon = () => {\n const app = useApp();\n const Icon = app.getSystemIcon('externalLink') || OpenInNew;\n const classes = useStyles();\n return <Icon className={classes.externalLinkIcon} />;\n};\n\nexport const isExternalUri = (uri: string) => /^([a-z+.-]+):/.test(uri);\n\n// See https://github.com/facebook/react/blob/f0cf832e1d0c8544c36aa8b310960885a11a847c/packages/react-dom-bindings/src/shared/sanitizeURL.js\nconst scriptProtocolPattern =\n // eslint-disable-next-line no-control-regex\n /^[\\u0000-\\u001F ]*j[\\r\\n\\t]*a[\\r\\n\\t]*v[\\r\\n\\t]*a[\\r\\n\\t]*s[\\r\\n\\t]*c[\\r\\n\\t]*r[\\r\\n\\t]*i[\\r\\n\\t]*p[\\r\\n\\t]*t[\\r\\n\\t]*\\:/i;\n\n// We install this globally in order to prevent javascript: URL XSS attacks via window.open\nconst originalWindowOpen = window.open as typeof window.open & {\n __backstage?: true;\n};\nif (originalWindowOpen && !originalWindowOpen.__backstage) {\n const newOpen = function open(\n this: Window,\n ...args: Parameters<typeof window.open>\n ) {\n const url = String(args[0]);\n if (scriptProtocolPattern.test(url)) {\n throw new Error(\n 'Rejected window.open() with a javascript: URL as a security precaution',\n );\n }\n return originalWindowOpen.apply(this, args);\n };\n newOpen.__backstage = true;\n window.open = newOpen;\n}\n\nexport type LinkProps = Omit<MaterialLinkProps, 'to'> &\n Omit<RouterLinkProps, 'to'> & {\n to: string;\n component?: ElementType<any>;\n noTrack?: boolean;\n externalLinkIcon?: boolean;\n };\n\n/**\n * Returns the app base url that could be empty if the Config API is not properly implemented.\n * The only cases there would be no Config API are in tests and in storybook stories, and in those cases, it's unlikely that callers would rely on this subpath behavior.\n */\nconst useBaseUrl = () => {\n try {\n const config = useApi(configApiRef);\n return config.getOptionalString('app.baseUrl');\n } catch {\n return undefined;\n }\n};\n\n/**\n * Get the app base path from the configured app baseUrl.\n * The returned path does not have a trailing slash.\n */\nconst useBasePath = () => {\n // baseUrl can be specified as just a path\n const base = 'http://sample.dev';\n const url = useBaseUrl() ?? '/';\n const { pathname } = new URL(url, base);\n return trimEnd(pathname, '/');\n};\n\n/** @deprecated Remove once we no longer support React Router v6 beta */\nexport const useResolvedPath = (uri: LinkProps['to']) => {\n let resolvedPath = String(uri);\n\n const basePath = useBasePath();\n const external = isExternalUri(resolvedPath);\n const startsWithBasePath = resolvedPath.startsWith(basePath);\n\n if (!external && !startsWithBasePath) {\n resolvedPath = basePath.concat(resolvedPath);\n }\n\n return resolvedPath;\n};\n\n/**\n * Given a react node, try to retrieve its text content.\n */\nconst getNodeText = (node: React.ReactNode): string => {\n // If the node is an array of children, recurse and join.\n if (node instanceof Array) {\n return node.map(getNodeText).join(' ').trim();\n }\n\n // If the node is a react element, recurse on its children.\n if (typeof node === 'object' && node) {\n return getNodeText((node as React.ReactElement)?.props?.children);\n }\n\n // Base case: the node is just text. Return it.\n if (['string', 'number'].includes(typeof node)) {\n return String(node);\n }\n\n // Base case: just return an empty string.\n return '';\n};\n\n/**\n * Thin wrapper on top of material-ui's Link component, which...\n * - Makes the Link use react-router\n * - Captures Link clicks as analytics events.\n */\nexport const Link = React.forwardRef<any, LinkProps>(\n ({ onClick, noTrack, externalLinkIcon, ...props }, ref) => {\n const classes = useStyles();\n const analytics = useAnalytics();\n\n // Adding the base path to URLs breaks react-router v6 stable, so we only\n // do it for beta. The react router version won't change at runtime so it is\n // fine to ignore the rules of hooks.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const to = isReactRouterBeta() ? useResolvedPath(props.to) : props.to;\n const linkText = getNodeText(props.children) || to;\n const external = isExternalUri(to);\n const newWindow = external && !!/^https?:/.exec(to);\n\n if (scriptProtocolPattern.test(to)) {\n throw new Error(\n 'Link component rejected javascript: URL as a security precaution',\n );\n }\n\n const handleClick = (event: React.MouseEvent<any, MouseEvent>) => {\n onClick?.(event);\n if (!noTrack) {\n analytics.captureEvent('click', linkText, { attributes: { to } });\n }\n };\n\n return external ? (\n // External links\n <MaterialLink\n {...(newWindow ? { target: '_blank', rel: 'noopener' } : {})}\n {...props}\n {...(props['aria-label']\n ? { 'aria-label': `${props['aria-label']}, Opens in a new window` }\n : {})}\n ref={ref}\n href={to}\n onClick={handleClick}\n className={classnames(classes.externalLink, props.className)}\n >\n {props.children}\n {externalLinkIcon && <ExternalLinkIcon />}\n <Typography component=\"span\" className={classes.visuallyHidden}>\n , Opens in a new window\n </Typography>\n </MaterialLink>\n ) : (\n // Interact with React Router for internal links\n <MaterialLink\n {...props}\n ref={ref}\n component={RouterLink}\n to={to}\n onClick={handleClick}\n />\n );\n },\n) as (props: LinkProps) => JSX.Element;\n"],"names":["React","classnames","RouterLink"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -150,6 +150,7 @@ type LinkProps = Omit<LinkProps$1, 'to'> & Omit<LinkProps$2, 'to'> & {
150
150
  to: string;
151
151
  component?: ElementType<any>;
152
152
  noTrack?: boolean;
153
+ externalLinkIcon?: boolean;
153
154
  };
154
155
  /**
155
156
  * Thin wrapper on top of material-ui's Link component, which...
@@ -19,11 +19,12 @@ const useStyles = makeStyles(
19
19
  flexFlow: "column nowrap",
20
20
  alignItems: "flex-start",
21
21
  position: "fixed",
22
+ opacity: 0,
22
23
  [theme.breakpoints.up("sm")]: {
23
24
  marginLeft: props.left,
24
- transition: theme.transitions.create("margin-left", {
25
+ transition: theme.transitions.create(["margin-left", "opacity"], {
25
26
  easing: theme.transitions.easing.sharp,
26
- duration: theme.transitions.duration.shortest
27
+ duration: props.submenuConfig.defaultOpenDelayMs
27
28
  })
28
29
  },
29
30
  top: 0,
@@ -44,6 +45,8 @@ const useStyles = makeStyles(
44
45
  }
45
46
  }),
46
47
  drawerOpen: (props) => ({
48
+ marginLeft: props.left,
49
+ opacity: 1,
47
50
  width: props.submenuConfig.drawerWidthOpen,
48
51
  [theme.breakpoints.down("xs")]: {
49
52
  width: "100%",
@@ -1 +1 @@
1
- {"version":3,"file":"SidebarSubmenu.esm.js","sources":["../../../src/layout/Sidebar/SidebarSubmenu.tsx"],"sourcesContent":["/*\n * Copyright 2021 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 Box from '@material-ui/core/Box';\nimport { makeStyles, Theme } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport classnames from 'classnames';\nimport React, { ReactNode, useContext, useEffect, useState } from 'react';\n\nimport {\n SidebarConfigContext,\n SidebarItemWithSubmenuContext,\n SubmenuConfig,\n} from './config';\nimport { useSidebarOpenState } from './SidebarOpenStateContext';\n\n/** @public */\nexport type SidebarSubmenuClassKey = 'root' | 'drawer' | 'drawerOpen' | 'title';\n\nconst useStyles = makeStyles<\n Theme,\n { submenuConfig: SubmenuConfig; left: number }\n>(\n theme => ({\n root: {\n zIndex: 1000,\n position: 'relative',\n overflow: 'visible',\n width: theme.spacing(7) + 1,\n },\n drawer: props => ({\n display: 'flex',\n flexFlow: 'column nowrap',\n alignItems: 'flex-start',\n position: 'fixed',\n [theme.breakpoints.up('sm')]: {\n marginLeft: props.left,\n transition: theme.transitions.create('margin-left', {\n easing: theme.transitions.easing.sharp,\n duration: theme.transitions.duration.shortest,\n }),\n },\n top: 0,\n bottom: 0,\n padding: 0,\n background: theme.palette.navigation.submenu?.background ?? '#404040',\n overflowX: 'hidden',\n msOverflowStyle: 'none',\n scrollbarWidth: 'none',\n cursor: 'default',\n width: props.submenuConfig.drawerWidthClosed,\n transitionDelay: `${props.submenuConfig.defaultOpenDelayMs}ms`,\n '& > *': {\n flexShrink: 0,\n },\n '&::-webkit-scrollbar': {\n display: 'none',\n },\n }),\n drawerOpen: props => ({\n width: props.submenuConfig.drawerWidthOpen,\n [theme.breakpoints.down('xs')]: {\n width: '100%',\n position: 'relative',\n paddingLeft: theme.spacing(3),\n left: 0,\n top: 0,\n },\n }),\n title: {\n fontSize: theme.typography.h5.fontSize,\n fontWeight: theme.typography.fontWeightMedium,\n color: theme.palette.navigation.color,\n padding: theme.spacing(2.5),\n [theme.breakpoints.down('xs')]: {\n display: 'none',\n },\n },\n }),\n { name: 'BackstageSidebarSubmenu' },\n);\n\n/**\n * Holds a title for text Header of a sidebar submenu and children\n * components to be rendered inside SidebarSubmenu\n *\n * @public\n */\nexport type SidebarSubmenuProps = {\n title?: string;\n children: ReactNode;\n};\n\n/**\n * Used inside SidebarItem to display an expandable Submenu\n *\n * @public\n */\nexport const SidebarSubmenu = (props: SidebarSubmenuProps) => {\n const { isOpen } = useSidebarOpenState();\n const { sidebarConfig, submenuConfig } = useContext(SidebarConfigContext);\n const left = isOpen\n ? sidebarConfig.drawerWidthOpen\n : sidebarConfig.drawerWidthClosed;\n const classes = useStyles({ left, submenuConfig });\n\n const { isHoveredOn } = useContext(SidebarItemWithSubmenuContext);\n const [isSubmenuOpen, setIsSubmenuOpen] = useState(false);\n\n useEffect(() => {\n setIsSubmenuOpen(isHoveredOn);\n }, [isHoveredOn]);\n\n return (\n <Box\n className={classnames(classes.drawer, {\n [classes.drawerOpen]: isSubmenuOpen,\n })}\n >\n <Typography variant=\"h5\" component=\"span\" className={classes.title}>\n {props.title}\n </Typography>\n {props.children}\n </Box>\n );\n};\n"],"names":["React","classnames"],"mappings":"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"}
1
+ {"version":3,"file":"SidebarSubmenu.esm.js","sources":["../../../src/layout/Sidebar/SidebarSubmenu.tsx"],"sourcesContent":["/*\n * Copyright 2021 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 Box from '@material-ui/core/Box';\nimport { makeStyles, Theme } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport classnames from 'classnames';\nimport React, { ReactNode, useContext, useEffect, useState } from 'react';\n\nimport {\n SidebarConfigContext,\n SidebarItemWithSubmenuContext,\n SubmenuConfig,\n} from './config';\nimport { useSidebarOpenState } from './SidebarOpenStateContext';\n\n/** @public */\nexport type SidebarSubmenuClassKey = 'root' | 'drawer' | 'drawerOpen' | 'title';\n\nconst useStyles = makeStyles<\n Theme,\n { submenuConfig: SubmenuConfig; left: number }\n>(\n theme => ({\n root: {\n zIndex: 1000,\n position: 'relative',\n overflow: 'visible',\n width: theme.spacing(7) + 1,\n },\n drawer: props => ({\n display: 'flex',\n flexFlow: 'column nowrap',\n alignItems: 'flex-start',\n position: 'fixed',\n opacity: 0,\n [theme.breakpoints.up('sm')]: {\n marginLeft: props.left,\n transition: theme.transitions.create(['margin-left', 'opacity'], {\n easing: theme.transitions.easing.sharp,\n duration: props.submenuConfig.defaultOpenDelayMs,\n }),\n },\n top: 0,\n bottom: 0,\n padding: 0,\n background: theme.palette.navigation.submenu?.background ?? '#404040',\n overflowX: 'hidden',\n msOverflowStyle: 'none',\n scrollbarWidth: 'none',\n cursor: 'default',\n width: props.submenuConfig.drawerWidthClosed,\n transitionDelay: `${props.submenuConfig.defaultOpenDelayMs}ms`,\n '& > *': {\n flexShrink: 0,\n },\n '&::-webkit-scrollbar': {\n display: 'none',\n },\n }),\n drawerOpen: props => ({\n marginLeft: props.left,\n opacity: 1,\n width: props.submenuConfig.drawerWidthOpen,\n [theme.breakpoints.down('xs')]: {\n width: '100%',\n position: 'relative',\n paddingLeft: theme.spacing(3),\n left: 0,\n top: 0,\n },\n }),\n title: {\n fontSize: theme.typography.h5.fontSize,\n fontWeight: theme.typography.fontWeightMedium,\n color: theme.palette.navigation.color,\n padding: theme.spacing(2.5),\n [theme.breakpoints.down('xs')]: {\n display: 'none',\n },\n },\n }),\n { name: 'BackstageSidebarSubmenu' },\n);\n\n/**\n * Holds a title for text Header of a sidebar submenu and children\n * components to be rendered inside SidebarSubmenu\n *\n * @public\n */\nexport type SidebarSubmenuProps = {\n title?: string;\n children: ReactNode;\n};\n\n/**\n * Used inside SidebarItem to display an expandable Submenu\n *\n * @public\n */\nexport const SidebarSubmenu = (props: SidebarSubmenuProps) => {\n const { isOpen } = useSidebarOpenState();\n const { sidebarConfig, submenuConfig } = useContext(SidebarConfigContext);\n const left = isOpen\n ? sidebarConfig.drawerWidthOpen\n : sidebarConfig.drawerWidthClosed;\n const classes = useStyles({ left, submenuConfig });\n\n const { isHoveredOn } = useContext(SidebarItemWithSubmenuContext);\n const [isSubmenuOpen, setIsSubmenuOpen] = useState(false);\n\n useEffect(() => {\n setIsSubmenuOpen(isHoveredOn);\n }, [isHoveredOn]);\n\n return (\n <Box\n className={classnames(classes.drawer, {\n [classes.drawerOpen]: isSubmenuOpen,\n })}\n >\n <Typography variant=\"h5\" component=\"span\" className={classes.title}>\n {props.title}\n </Typography>\n {props.children}\n </Box>\n );\n};\n"],"names":["React","classnames"],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@backstage/core-components",
3
+ "version": "0.15.1-next.1",
3
4
  "description": "Core components used by Backstage plugins and apps",
4
- "version": "0.15.0",
5
- "publishConfig": {
6
- "access": "public"
7
- },
8
5
  "backstage": {
9
6
  "role": "web-library"
10
7
  },
8
+ "publishConfig": {
9
+ "access": "public"
10
+ },
11
11
  "keywords": [
12
12
  "backstage"
13
13
  ],
@@ -55,18 +55,17 @@
55
55
  "test": "backstage-cli package test"
56
56
  },
57
57
  "dependencies": {
58
- "@backstage/config": "^1.2.0",
59
- "@backstage/core-plugin-api": "^1.9.4",
60
- "@backstage/errors": "^1.2.4",
61
- "@backstage/theme": "^0.5.7",
62
- "@backstage/version-bridge": "^1.0.9",
58
+ "@backstage/config": "1.2.0",
59
+ "@backstage/core-plugin-api": "1.10.0-next.1",
60
+ "@backstage/errors": "1.2.4",
61
+ "@backstage/theme": "0.5.8-next.0",
62
+ "@backstage/version-bridge": "1.0.10-next.0",
63
63
  "@date-io/core": "^1.3.13",
64
64
  "@material-table/core": "^3.1.0",
65
65
  "@material-ui/core": "^4.12.2",
66
66
  "@material-ui/icons": "^4.9.1",
67
67
  "@material-ui/lab": "4.0.0-alpha.61",
68
68
  "@react-hookz/web": "^24.0.0",
69
- "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
70
69
  "@types/react-sparklines": "^1.7.0",
71
70
  "ansi-regex": "^6.0.1",
72
71
  "classnames": "^2.2.6",
@@ -94,10 +93,10 @@
94
93
  "zod": "^3.22.4"
95
94
  },
96
95
  "devDependencies": {
97
- "@backstage/app-defaults": "^1.5.11",
98
- "@backstage/cli": "^0.27.1",
99
- "@backstage/core-app-api": "^1.15.0",
100
- "@backstage/test-utils": "^1.6.0",
96
+ "@backstage/app-defaults": "1.5.12-next.1",
97
+ "@backstage/cli": "0.28.0-next.1",
98
+ "@backstage/core-app-api": "1.15.1-next.1",
99
+ "@backstage/test-utils": "1.6.1-next.1",
101
100
  "@testing-library/dom": "^10.0.0",
102
101
  "@testing-library/jest-dom": "^6.0.0",
103
102
  "@testing-library/react": "^16.0.0",
@@ -109,6 +108,7 @@
109
108
  "@types/d3-zoom": "^3.0.1",
110
109
  "@types/dagre": "^0.7.44",
111
110
  "@types/google-protobuf": "^3.7.2",
111
+ "@types/react": "^18.0.0",
112
112
  "@types/react-helmet": "^6.1.0",
113
113
  "@types/react-syntax-highlighter": "^15.0.0",
114
114
  "@types/react-virtualized-auto-sizer": "^1.0.1",
@@ -116,13 +116,22 @@
116
116
  "@types/zen-observable": "^0.8.0",
117
117
  "cross-fetch": "^4.0.0",
118
118
  "history": "^5.0.0",
119
- "msw": "^1.0.0"
119
+ "msw": "^1.0.0",
120
+ "react": "^18.0.2",
121
+ "react-dom": "^18.0.2",
122
+ "react-router-dom": "^6.3.0"
120
123
  },
121
124
  "peerDependencies": {
125
+ "@types/react": "^16.13.1 || ^17.0.0 || ^18.0.0",
122
126
  "react": "^16.13.1 || ^17.0.0 || ^18.0.0",
123
127
  "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0",
124
128
  "react-router-dom": "6.0.0-beta.0 || ^6.3.0"
125
129
  },
130
+ "peerDependenciesMeta": {
131
+ "@types/react": {
132
+ "optional": true
133
+ }
134
+ },
126
135
  "configSchema": "config.d.ts",
127
136
  "module": "./dist/index.esm.js"
128
137
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/core-components__testutils",
3
- "version": "0.15.0",
3
+ "version": "0.15.1-next.1",
4
4
  "main": "../dist/testUtils.esm.js",
5
5
  "module": "../dist/testUtils.esm.js",
6
6
  "types": "../dist/testUtils.d.ts"