@backstage/plugin-home 0.9.8-next.0 → 0.9.9-next.0

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/plugin-home
2
2
 
3
+ ## 0.9.9-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/core-components@0.18.13-next.0
9
+ - @backstage/plugin-catalog-react@3.2.1-next.0
10
+ - @backstage/plugin-home-react@0.1.41-next.0
11
+ - @backstage/core-app-api@1.20.4-next.0
12
+ - @backstage/core-compat-api@0.5.14-next.0
13
+
14
+ ## 0.9.8
15
+
16
+ ### Patch Changes
17
+
18
+ - e9776b0: Optionally prevent duplicate widget additions via prop and added empty state for Add Widget dialog
19
+ - Updated dependencies
20
+ - @backstage/frontend-plugin-api@0.17.3
21
+ - @backstage/plugin-catalog-react@3.2.0
22
+ - @backstage/core-components@0.18.12
23
+ - @backstage/core-app-api@1.20.3
24
+ - @backstage/catalog-client@1.16.1
25
+ - @backstage/core-compat-api@0.5.13
26
+ - @backstage/core-plugin-api@1.12.8
27
+ - @backstage/plugin-home-react@0.1.40
28
+
3
29
  ## 0.9.8-next.0
4
30
 
5
31
  ### Patch Changes
package/README.md CHANGED
@@ -132,6 +132,18 @@ const myWidget = HomePageWidgetBlueprint.make({
132
132
 
133
133
  > **Example**: See [dev/index.tsx](dev/index.tsx) for a comprehensive example of creating multiple homepage widgets and layouts.
134
134
 
135
+ ### Preventing Duplicate Widgets
136
+
137
+ The `CustomHomepageGrid` supports preventing duplicate widgets from being added to the homepage via the `preventDuplicateWidgets` prop (default: `false`):
138
+
139
+ ```tsx
140
+ <CustomHomepageGrid preventDuplicateWidgets={true}>
141
+ <HomePageSearchBar />
142
+ <HomePageRandomJoke />
143
+ <HomePageStarredEntities />
144
+ </CustomHomepageGrid>
145
+ ```
146
+
135
147
  ## Contributing
136
148
 
137
149
  ### Homepage Components
package/dist/alpha.d.ts CHANGED
@@ -120,6 +120,7 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
120
120
  declare const homeTranslationRef: _backstage_frontend_plugin_api.TranslationRef<"home", {
121
121
  readonly "starredEntities.noStarredEntitiesMessage": "Click the star beside an entity name to add it to this list!";
122
122
  readonly "addWidgetDialog.title": "Add new widget to dashboard";
123
+ readonly "addWidgetDialog.noAvailableWidgets": "All available widgets have been added to the dashboard.";
123
124
  readonly "customHomepageButtons.cancel": "Cancel";
124
125
  readonly "customHomepageButtons.clearAll": "Clear all";
125
126
  readonly "customHomepageButtons.edit": "Edit";
@@ -1,4 +1,5 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import Box from '@material-ui/core/Box';
2
3
  import List from '@material-ui/core/List';
3
4
  import ListItem from '@material-ui/core/ListItem';
4
5
  import DialogContent from '@material-ui/core/DialogContent';
@@ -18,7 +19,7 @@ const AddWidgetDialog = (props) => {
18
19
  const { t } = useTranslationRef(homeTranslationRef);
19
20
  return /* @__PURE__ */ jsxs(Fragment, { children: [
20
21
  /* @__PURE__ */ jsx(DialogTitle, { children: t("addWidgetDialog.title") }),
21
- /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsx(List, { dense: true, children: widgets.map((widget) => {
22
+ /* @__PURE__ */ jsx(DialogContent, { children: widgets.length === 0 ? /* @__PURE__ */ jsx(Box, { pb: 3, textAlign: "center", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", color: "textSecondary", children: t("addWidgetDialog.noAvailableWidgets") }) }) : /* @__PURE__ */ jsx(List, { dense: true, children: widgets.map((widget) => {
22
23
  return /* @__PURE__ */ jsxs(
23
24
  ListItem,
24
25
  {
@@ -1 +1 @@
1
- {"version":3,"file":"AddWidgetDialog.esm.js","sources":["../../../src/components/CustomHomepage/AddWidgetDialog.tsx"],"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 { Widget } from './types';\nimport List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport ListItemAvatar from '@material-ui/core/ListItemAvatar';\nimport AddIcon from '@material-ui/icons/Add';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport Typography from '@material-ui/core/Typography';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { homeTranslationRef } from '../../translation';\n\ninterface AddWidgetDialogProps {\n widgets: Widget[];\n handleAdd: (widget: Widget) => void;\n}\n\nconst getTitle = (widget: Widget) => {\n return widget.title || widget.name;\n};\n\nexport const AddWidgetDialog = (props: AddWidgetDialogProps) => {\n const { widgets, handleAdd } = props;\n const { t } = useTranslationRef(homeTranslationRef);\n return (\n <>\n <DialogTitle>{t('addWidgetDialog.title')}</DialogTitle>\n <DialogContent>\n <List dense>\n {widgets.map(widget => {\n return (\n <ListItem\n key={widget.name}\n button\n onClick={() => handleAdd(widget)}\n >\n <ListItemAvatar>\n <AddIcon />\n </ListItemAvatar>\n <ListItemText\n secondary={\n widget.description && (\n <Typography\n component=\"span\"\n variant=\"caption\"\n color=\"textPrimary\"\n >\n {widget.description}\n </Typography>\n )\n }\n primary={\n <Typography variant=\"body1\" color=\"textPrimary\">\n {getTitle(widget)}\n </Typography>\n }\n />\n </ListItem>\n );\n })}\n </List>\n </DialogContent>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;AAiCA,MAAM,QAAA,GAAW,CAAC,MAAA,KAAmB;AACnC,EAAA,OAAO,MAAA,CAAO,SAAS,MAAA,CAAO,IAAA;AAChC,CAAA;AAEO,MAAM,eAAA,GAAkB,CAAC,KAAA,KAAgC;AAC9D,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAU,GAAI,KAAA;AAC/B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,iBAAA,CAAkB,kBAAkB,CAAA;AAClD,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAA,EAAA,EAAa,QAAA,EAAA,CAAA,CAAE,uBAAuB,CAAA,EAAE,CAAA;AAAA,oBACzC,GAAA,CAAC,iBACC,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,OAAK,IAAA,EACR,QAAA,EAAA,OAAA,CAAQ,IAAI,CAAA,MAAA,KAAU;AACrB,MAAA,uBACE,IAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAEC,MAAA,EAAM,IAAA;AAAA,UACN,OAAA,EAAS,MAAM,SAAA,CAAU,MAAM,CAAA;AAAA,UAE/B,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,cAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,CAAA,EACX,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,YAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EACE,OAAO,WAAA,oBACL,GAAA;AAAA,kBAAC,UAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAU,MAAA;AAAA,oBACV,OAAA,EAAQ,SAAA;AAAA,oBACR,KAAA,EAAM,aAAA;AAAA,oBAEL,QAAA,EAAA,MAAA,CAAO;AAAA;AAAA,iBACV;AAAA,gBAGJ,OAAA,sBACG,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAQ,KAAA,EAAM,aAAA,EAC/B,QAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAClB;AAAA;AAAA;AAEJ;AAAA,SAAA;AAAA,QAxBK,MAAA,CAAO;AAAA,OAyBd;AAAA,IAEJ,CAAC,GACH,CAAA,EACF;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"AddWidgetDialog.esm.js","sources":["../../../src/components/CustomHomepage/AddWidgetDialog.tsx"],"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 { Widget } from './types';\nimport Box from '@material-ui/core/Box';\nimport List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport DialogContent from '@material-ui/core/DialogContent';\nimport DialogTitle from '@material-ui/core/DialogTitle';\nimport ListItemAvatar from '@material-ui/core/ListItemAvatar';\nimport AddIcon from '@material-ui/icons/Add';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport Typography from '@material-ui/core/Typography';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { homeTranslationRef } from '../../translation';\n\ninterface AddWidgetDialogProps {\n widgets: Widget[];\n handleAdd: (widget: Widget) => void;\n}\n\nconst getTitle = (widget: Widget) => {\n return widget.title || widget.name;\n};\n\nexport const AddWidgetDialog = (props: AddWidgetDialogProps) => {\n const { widgets, handleAdd } = props;\n const { t } = useTranslationRef(homeTranslationRef);\n return (\n <>\n <DialogTitle>{t('addWidgetDialog.title')}</DialogTitle>\n <DialogContent>\n {widgets.length === 0 ? (\n <Box pb={3} textAlign=\"center\">\n <Typography variant=\"body1\" color=\"textSecondary\">\n {t('addWidgetDialog.noAvailableWidgets')}\n </Typography>\n </Box>\n ) : (\n <List dense>\n {widgets.map(widget => {\n return (\n <ListItem\n key={widget.name}\n button\n onClick={() => handleAdd(widget)}\n >\n <ListItemAvatar>\n <AddIcon />\n </ListItemAvatar>\n <ListItemText\n secondary={\n widget.description && (\n <Typography\n component=\"span\"\n variant=\"caption\"\n color=\"textPrimary\"\n >\n {widget.description}\n </Typography>\n )\n }\n primary={\n <Typography variant=\"body1\" color=\"textPrimary\">\n {getTitle(widget)}\n </Typography>\n }\n />\n </ListItem>\n );\n })}\n </List>\n )}\n </DialogContent>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;AAkCA,MAAM,QAAA,GAAW,CAAC,MAAA,KAAmB;AACnC,EAAA,OAAO,MAAA,CAAO,SAAS,MAAA,CAAO,IAAA;AAChC,CAAA;AAEO,MAAM,eAAA,GAAkB,CAAC,KAAA,KAAgC;AAC9D,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAU,GAAI,KAAA;AAC/B,EAAA,MAAM,EAAE,CAAA,EAAE,GAAI,iBAAA,CAAkB,kBAAkB,CAAA;AAClD,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WAAA,EAAA,EAAa,QAAA,EAAA,CAAA,CAAE,uBAAuB,CAAA,EAAE,CAAA;AAAA,oBACzC,GAAA,CAAC,aAAA,EAAA,EACE,QAAA,EAAA,OAAA,CAAQ,MAAA,KAAW,CAAA,mBAClB,GAAA,CAAC,GAAA,EAAA,EAAI,EAAA,EAAI,CAAA,EAAG,SAAA,EAAU,QAAA,EACpB,QAAA,kBAAA,GAAA,CAAC,UAAA,EAAA,EAAW,OAAA,EAAQ,OAAA,EAAQ,KAAA,EAAM,eAAA,EAC/B,QAAA,EAAA,CAAA,CAAE,oCAAoC,CAAA,EACzC,CAAA,EACF,CAAA,mBAEA,GAAA,CAAC,IAAA,EAAA,EAAK,KAAA,EAAK,IAAA,EACR,QAAA,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,MAAA,KAAU;AACrB,MAAA,uBACE,IAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UAEC,MAAA,EAAM,IAAA;AAAA,UACN,OAAA,EAAS,MAAM,SAAA,CAAU,MAAM,CAAA;AAAA,UAE/B,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,cAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,CAAA,EACX,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,YAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EACE,OAAO,WAAA,oBACL,GAAA;AAAA,kBAAC,UAAA;AAAA,kBAAA;AAAA,oBACC,SAAA,EAAU,MAAA;AAAA,oBACV,OAAA,EAAQ,SAAA;AAAA,oBACR,KAAA,EAAM,aAAA;AAAA,oBAEL,QAAA,EAAA,MAAA,CAAO;AAAA;AAAA,iBACV;AAAA,gBAGJ,OAAA,sBACG,UAAA,EAAA,EAAW,OAAA,EAAQ,SAAQ,KAAA,EAAM,aAAA,EAC/B,QAAA,EAAA,QAAA,CAAS,MAAM,CAAA,EAClB;AAAA;AAAA;AAEJ;AAAA,SAAA;AAAA,QAxBK,MAAA,CAAO;AAAA,OAyBd;AAAA,IAEJ,CAAC,GACH,CAAA,EAEJ;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -153,6 +153,7 @@ const CustomHomepageGrid = (props) => {
153
153
  }, [props.config, availableWidgets]);
154
154
  const [storedWidgets, storeWidgets, isStorageLoading] = useHomeStorage(defaultLayout);
155
155
  const [widgets, setWidgets] = useState(storedWidgets);
156
+ const preventDuplicateWidgets = props.preventDuplicateWidgets ?? false;
156
157
  const [addWidgetDialogOpen, setAddWidgetDialogOpen] = useState(false);
157
158
  const editModeOn = widgets.find((w) => w.layout.isResizable) !== void 0;
158
159
  const [editMode, setEditMode] = useState(editModeOn);
@@ -166,6 +167,15 @@ const CustomHomepageGrid = (props) => {
166
167
  return key.split("__")[0];
167
168
  };
168
169
  const { t } = useTranslationRef(homeTranslationRef);
170
+ const getAvailableWidgets = () => {
171
+ if (!preventDuplicateWidgets) {
172
+ return availableWidgets;
173
+ }
174
+ const usedWidgetNames = new Set(
175
+ widgets.map((w) => getWidgetNameFromKey(w.id))
176
+ );
177
+ return availableWidgets.filter((widget) => !usedWidgetNames.has(widget.name));
178
+ };
169
179
  const handleAdd = (widget) => {
170
180
  const widgetId = `${widget.name}__${widgets.length + 1}${Math.random().toString(36).slice(2)}`;
171
181
  setWidgets([
@@ -278,7 +288,13 @@ const CustomHomepageGrid = (props) => {
278
288
  {
279
289
  open: addWidgetDialogOpen,
280
290
  onClose: () => setAddWidgetDialogOpen(false),
281
- children: /* @__PURE__ */ jsx(AddWidgetDialog, { widgets: availableWidgets, handleAdd })
291
+ children: addWidgetDialogOpen && /* @__PURE__ */ jsx(
292
+ AddWidgetDialog,
293
+ {
294
+ widgets: getAvailableWidgets(),
295
+ handleAdd
296
+ }
297
+ )
282
298
  }
283
299
  ),
284
300
  !editMode && widgets.length === 0 && /* @__PURE__ */ jsx(Typography, { variant: "h5", align: "center", children: t("customHomepage.noWidgets") }),
@@ -1 +1 @@
1
- {"version":3,"file":"CustomHomepageGrid.esm.js","sources":["../../../src/components/CustomHomepage/CustomHomepageGrid.tsx"],"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 isValidElement,\n useState,\n useCallback,\n useMemo,\n useEffect,\n} from 'react';\nimport { Layout, Layouts, Responsive, WidthProvider } from 'react-grid-layout';\nimport {\n ElementCollection,\n getComponentData,\n storageApiRef,\n useApi,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport 'react-grid-layout/css/styles.css';\nimport 'react-resizable/css/styles.css';\nimport Dialog from '@material-ui/core/Dialog';\nimport {\n createStyles,\n makeStyles,\n Theme,\n useTheme,\n} from '@material-ui/core/styles';\nimport { compact } from 'lodash';\nimport useObservable from 'react-use/esm/useObservable';\nimport {\n ContentHeader,\n ErrorBoundary,\n Progress,\n} from '@backstage/core-components';\nimport Typography from '@material-ui/core/Typography';\nimport { WidgetSettingsOverlay } from './WidgetSettingsOverlay';\nimport { AddWidgetDialog } from './AddWidgetDialog';\nimport { CustomHomepageButtons } from './CustomHomepageButtons';\nimport {\n CustomHomepageGridProps,\n CustomHomepageGridStateV1,\n CustomHomepageGridStateV1Schema,\n GridWidget,\n LayoutConfiguration,\n LayoutConfigurationSchema,\n Widget,\n WidgetSchema,\n} from './types';\nimport { CardConfig } from '@backstage/plugin-home-react';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { homeTranslationRef } from '../../translation';\n\n// eslint-disable-next-line new-cap\nconst ResponsiveGrid = WidthProvider(Responsive);\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n responsiveGrid: {\n '& .react-grid-item > .react-resizable-handle:after': {\n position: 'absolute',\n content: '\"\"',\n borderStyle: 'solid',\n borderWidth: '0 0 20px 20px',\n borderColor: `transparent transparent ${theme.palette.primary.light} transparent`,\n },\n },\n contentHeaderBtn: {\n marginLeft: theme.spacing(2),\n },\n widgetWrapper: {\n '& > div[class*=\"MuiCard-root\"]': {\n width: '100%',\n height: '100%',\n },\n '& div[class*=\"MuiCardContent-root\"]': {\n overflow: 'auto',\n },\n '& + .react-grid-placeholder': {\n backgroundColor: theme.palette.primary.light,\n },\n '&.edit > :active': {\n cursor: 'move',\n },\n },\n }),\n);\n\nfunction useHomeStorage(\n defaultWidgets: GridWidget[],\n): [GridWidget[], (value: GridWidget[]) => void, boolean] {\n const key = 'home';\n const storageApi = useApi(storageApiRef).forBucket('home.customHomepage');\n // TODO: Support multiple home pages\n const setWidgets = useCallback(\n (value: GridWidget[]) => {\n const grid: CustomHomepageGridStateV1 = {\n version: 1,\n pages: {\n default: value,\n },\n };\n storageApi.set(key, JSON.stringify(grid));\n },\n [key, storageApi],\n );\n const homeSnapshot = useObservable(\n storageApi.observe$<string>(key),\n storageApi.snapshot(key),\n );\n\n const isStorageLoading = homeSnapshot.presence === 'unknown' || !homeSnapshot;\n\n const widgets: GridWidget[] = useMemo(() => {\n if (homeSnapshot.presence === 'absent') {\n return defaultWidgets;\n }\n try {\n const grid: CustomHomepageGridStateV1 = JSON.parse(homeSnapshot.value!);\n return CustomHomepageGridStateV1Schema.parse(grid).pages.default;\n } catch (e) {\n return defaultWidgets;\n }\n }, [homeSnapshot, defaultWidgets]);\n\n return [widgets, setWidgets, isStorageLoading];\n}\n\nconst convertConfigToDefaultWidgets = (\n config: LayoutConfiguration[],\n availableWidgets: Widget[],\n): GridWidget[] => {\n const ret = config.map((conf, i) => {\n const c = LayoutConfigurationSchema.parse(conf);\n const name = isValidElement(c.component)\n ? getComponentData(c.component, 'core.extensionName')\n : (c.component as unknown as string);\n if (!name) {\n return null;\n }\n const widget = availableWidgets.find(w => w.name === name);\n if (!widget) {\n return null;\n }\n const widgetId = `${widget.name}__${i}${Math.random()\n .toString(36)\n .slice(2)}`;\n return {\n id: widgetId,\n layout: {\n i: widgetId,\n x: c.x,\n y: c.y,\n w: Math.min(widget.maxWidth ?? Number.MAX_VALUE, c.width),\n h: Math.min(widget.maxHeight ?? Number.MAX_VALUE, c.height),\n minW: widget.minWidth,\n maxW: widget.maxWidth,\n minH: widget.minHeight,\n maxH: widget.maxHeight,\n isDraggable: false,\n isResizable: false,\n },\n settings: {},\n movable: conf.movable,\n deletable: conf.deletable,\n resizable: conf.resizable,\n };\n });\n return compact(ret);\n};\n\nconst availableWidgetsFilter = (elements: ElementCollection) => {\n return elements\n .selectByComponentData({\n key: 'core.extensionName',\n })\n .getElements<Widget>()\n .flatMap(elem => {\n const config = getComponentData<CardConfig>(elem, 'home.widget.config');\n return [\n WidgetSchema.parse({\n component: elem,\n name: getComponentData<string>(elem, 'core.extensionName'),\n title: getComponentData<string>(elem, 'title'),\n description: getComponentData<string>(elem, 'description'),\n settingsSchema: config?.settings?.schema,\n uiSchema: config?.settings?.uiSchema,\n width: config?.layout?.width?.defaultColumns,\n minWidth: config?.layout?.width?.minColumns,\n maxWidth: config?.layout?.width?.maxColumns,\n height: config?.layout?.height?.defaultRows,\n minHeight: config?.layout?.height?.minRows,\n maxHeight: config?.layout?.height?.maxRows,\n }),\n ];\n });\n};\n\n/**\n * A component that allows customizing components in home grid layout.\n *\n * @public\n */\nexport const CustomHomepageGrid = (props: CustomHomepageGridProps) => {\n const styles = useStyles();\n const theme = useTheme();\n const availableWidgets = useElementFilter(\n props.children,\n availableWidgetsFilter,\n [props],\n );\n const defaultLayout = useMemo(() => {\n return props.config\n ? convertConfigToDefaultWidgets(props.config, availableWidgets)\n : [];\n }, [props.config, availableWidgets]);\n const [storedWidgets, storeWidgets, isStorageLoading] =\n useHomeStorage(defaultLayout);\n const [widgets, setWidgets] = useState(storedWidgets);\n\n const [addWidgetDialogOpen, setAddWidgetDialogOpen] = useState(false);\n const editModeOn = widgets.find(w => w.layout.isResizable) !== undefined;\n const [editMode, setEditMode] = useState(editModeOn);\n\n useEffect(() => {\n setWidgets(storedWidgets);\n }, [storedWidgets]);\n\n const getWidgetByName = (name: string) => {\n return availableWidgets.find(widget => widget.name === name);\n };\n\n const getWidgetNameFromKey = (key: string) => {\n return key.split('__')[0];\n };\n const { t } = useTranslationRef(homeTranslationRef);\n\n const handleAdd = (widget: Widget) => {\n const widgetId = `${widget.name}__${widgets.length + 1}${Math.random()\n .toString(36)\n .slice(2)}`;\n\n setWidgets([\n ...widgets,\n {\n id: widgetId,\n layout: {\n i: widgetId,\n x: 0,\n y: Math.max(...widgets.map(w => w.layout.y + w.layout.h)) + 1,\n w: Math.min(widget.maxWidth ?? Number.MAX_VALUE, widget.width ?? 12),\n h: Math.min(widget.maxHeight ?? Number.MAX_VALUE, widget.height ?? 4),\n minW: widget.minWidth,\n maxW: widget.maxWidth,\n minH: widget.minHeight,\n maxH: widget.maxHeight,\n isResizable: editMode,\n isDraggable: editMode,\n },\n settings: {},\n movable: widget.movable,\n deletable: widget.deletable,\n resizable: widget.resizable,\n },\n ]);\n setAddWidgetDialogOpen(false);\n };\n\n const handleRemove = (widgetId: string) => {\n setWidgets(widgets.filter(w => w.id !== widgetId));\n };\n\n const handleSettingsSave = (\n widgetId: string,\n widgetSettings: Record<string, any>,\n ) => {\n const idx = widgets.findIndex(w => w.id === widgetId);\n if (idx >= 0) {\n const widget = widgets[idx];\n widget.settings = widgetSettings;\n widgets[idx] = widget;\n setWidgets(widgets);\n }\n };\n\n const clearLayout = () => {\n setWidgets(widgets.filter(w => w.deletable === false));\n };\n\n const changeEditMode = (mode: boolean) => {\n setEditMode(mode);\n\n const newWidgets = widgets.map(w => {\n const resizable = w.resizable === false ? false : mode;\n const movable = w.movable === false ? false : mode;\n return {\n ...w,\n layout: { ...w.layout, isDraggable: movable, isResizable: resizable },\n };\n });\n\n if (mode) {\n setWidgets(newWidgets);\n } else {\n storeWidgets(newWidgets);\n }\n };\n\n const handleLayoutChange = (newLayout: Layout[], _: Layouts) => {\n if (editMode) {\n const newWidgets = newLayout.map(l => {\n const widget = widgets.find(w => w.id === l.i);\n return {\n ...widget,\n layout: l,\n } as GridWidget;\n });\n setWidgets(newWidgets);\n }\n };\n\n const handleRestoreDefaultConfig = () => {\n setWidgets(\n defaultLayout.map(w => {\n const resizable = w.resizable === false ? false : editMode;\n const movable = w.movable === false ? false : editMode;\n return {\n ...w,\n layout: {\n ...w.layout,\n isDraggable: movable,\n isResizable: resizable,\n },\n };\n }),\n );\n };\n\n const handleCancel = () => {\n setWidgets(storedWidgets);\n setEditMode(false);\n };\n\n if (isStorageLoading) {\n return <Progress />;\n }\n\n return (\n <>\n <ContentHeader title={props.title}>\n <CustomHomepageButtons\n editMode={editMode}\n numWidgets={widgets.length}\n clearLayout={clearLayout}\n setAddWidgetDialogOpen={setAddWidgetDialogOpen}\n changeEditMode={changeEditMode}\n defaultConfigAvailable={props.config !== undefined}\n restoreDefault={handleRestoreDefaultConfig}\n cancel={handleCancel}\n />\n </ContentHeader>\n <Dialog\n open={addWidgetDialogOpen}\n onClose={() => setAddWidgetDialogOpen(false)}\n >\n <AddWidgetDialog widgets={availableWidgets} handleAdd={handleAdd} />\n </Dialog>\n {!editMode && widgets.length === 0 && (\n <Typography variant=\"h5\" align=\"center\">\n {t('customHomepage.noWidgets')}\n </Typography>\n )}\n <ResponsiveGrid\n className={styles.responsiveGrid}\n measureBeforeMount\n compactType={props.compactType}\n style={props.style}\n allowOverlap={props.allowOverlap}\n preventCollision={props.preventCollision ?? true}\n draggableCancel=\".overlayGridItem,.widgetSettingsDialog,.disabled\"\n containerPadding={props.containerPadding}\n margin={props.containerMargin}\n breakpoints={\n props.breakpoints ? props.breakpoints : theme.breakpoints.values\n }\n cols={\n props.cols\n ? props.cols\n : { xl: 12, lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }\n }\n rowHeight={props.rowHeight ?? 60}\n onLayoutChange={handleLayoutChange}\n layouts={{ xl: widgets.map(w => w.layout) }}\n >\n {widgets.map((w: GridWidget) => {\n const l = w.layout;\n const widgetName = getWidgetNameFromKey(l.i);\n const widget = getWidgetByName(widgetName);\n if (!widget || !widget.component) {\n return null;\n }\n\n const widgetProps = {\n ...widget.component.props,\n ...(w.settings ?? {}),\n };\n\n return (\n <div\n key={l.i}\n className={`${styles.widgetWrapper} ${editMode && 'edit'} ${\n w.movable === false && 'disabled'\n }`}\n >\n <ErrorBoundary>\n <widget.component.type {...widgetProps} />\n </ErrorBoundary>\n {editMode && (\n <WidgetSettingsOverlay\n id={l.i}\n widget={widget}\n handleRemove={handleRemove}\n handleSettingsSave={handleSettingsSave}\n settings={w.settings}\n deletable={w.deletable}\n />\n )}\n </div>\n );\n })}\n </ResponsiveGrid>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CustomHomepageGrid.esm.js","sources":["../../../src/components/CustomHomepage/CustomHomepageGrid.tsx"],"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 isValidElement,\n useState,\n useCallback,\n useMemo,\n useEffect,\n} from 'react';\nimport { Layout, Layouts, Responsive, WidthProvider } from 'react-grid-layout';\nimport {\n ElementCollection,\n getComponentData,\n storageApiRef,\n useApi,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport 'react-grid-layout/css/styles.css';\nimport 'react-resizable/css/styles.css';\nimport Dialog from '@material-ui/core/Dialog';\nimport {\n createStyles,\n makeStyles,\n Theme,\n useTheme,\n} from '@material-ui/core/styles';\nimport { compact } from 'lodash';\nimport useObservable from 'react-use/esm/useObservable';\nimport {\n ContentHeader,\n ErrorBoundary,\n Progress,\n} from '@backstage/core-components';\nimport Typography from '@material-ui/core/Typography';\nimport { WidgetSettingsOverlay } from './WidgetSettingsOverlay';\nimport { AddWidgetDialog } from './AddWidgetDialog';\nimport { CustomHomepageButtons } from './CustomHomepageButtons';\nimport {\n CustomHomepageGridProps,\n CustomHomepageGridStateV1,\n CustomHomepageGridStateV1Schema,\n GridWidget,\n LayoutConfiguration,\n LayoutConfigurationSchema,\n Widget,\n WidgetSchema,\n} from './types';\nimport { CardConfig } from '@backstage/plugin-home-react';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { homeTranslationRef } from '../../translation';\n\n// eslint-disable-next-line new-cap\nconst ResponsiveGrid = WidthProvider(Responsive);\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n responsiveGrid: {\n '& .react-grid-item > .react-resizable-handle:after': {\n position: 'absolute',\n content: '\"\"',\n borderStyle: 'solid',\n borderWidth: '0 0 20px 20px',\n borderColor: `transparent transparent ${theme.palette.primary.light} transparent`,\n },\n },\n contentHeaderBtn: {\n marginLeft: theme.spacing(2),\n },\n widgetWrapper: {\n '& > div[class*=\"MuiCard-root\"]': {\n width: '100%',\n height: '100%',\n },\n '& div[class*=\"MuiCardContent-root\"]': {\n overflow: 'auto',\n },\n '& + .react-grid-placeholder': {\n backgroundColor: theme.palette.primary.light,\n },\n '&.edit > :active': {\n cursor: 'move',\n },\n },\n }),\n);\n\nfunction useHomeStorage(\n defaultWidgets: GridWidget[],\n): [GridWidget[], (value: GridWidget[]) => void, boolean] {\n const key = 'home';\n const storageApi = useApi(storageApiRef).forBucket('home.customHomepage');\n // TODO: Support multiple home pages\n const setWidgets = useCallback(\n (value: GridWidget[]) => {\n const grid: CustomHomepageGridStateV1 = {\n version: 1,\n pages: {\n default: value,\n },\n };\n storageApi.set(key, JSON.stringify(grid));\n },\n [key, storageApi],\n );\n const homeSnapshot = useObservable(\n storageApi.observe$<string>(key),\n storageApi.snapshot(key),\n );\n\n const isStorageLoading = homeSnapshot.presence === 'unknown' || !homeSnapshot;\n\n const widgets: GridWidget[] = useMemo(() => {\n if (homeSnapshot.presence === 'absent') {\n return defaultWidgets;\n }\n try {\n const grid: CustomHomepageGridStateV1 = JSON.parse(homeSnapshot.value!);\n return CustomHomepageGridStateV1Schema.parse(grid).pages.default;\n } catch (e) {\n return defaultWidgets;\n }\n }, [homeSnapshot, defaultWidgets]);\n\n return [widgets, setWidgets, isStorageLoading];\n}\n\nconst convertConfigToDefaultWidgets = (\n config: LayoutConfiguration[],\n availableWidgets: Widget[],\n): GridWidget[] => {\n const ret = config.map((conf, i) => {\n const c = LayoutConfigurationSchema.parse(conf);\n const name = isValidElement(c.component)\n ? getComponentData(c.component, 'core.extensionName')\n : (c.component as unknown as string);\n if (!name) {\n return null;\n }\n const widget = availableWidgets.find(w => w.name === name);\n if (!widget) {\n return null;\n }\n const widgetId = `${widget.name}__${i}${Math.random()\n .toString(36)\n .slice(2)}`;\n return {\n id: widgetId,\n layout: {\n i: widgetId,\n x: c.x,\n y: c.y,\n w: Math.min(widget.maxWidth ?? Number.MAX_VALUE, c.width),\n h: Math.min(widget.maxHeight ?? Number.MAX_VALUE, c.height),\n minW: widget.minWidth,\n maxW: widget.maxWidth,\n minH: widget.minHeight,\n maxH: widget.maxHeight,\n isDraggable: false,\n isResizable: false,\n },\n settings: {},\n movable: conf.movable,\n deletable: conf.deletable,\n resizable: conf.resizable,\n };\n });\n return compact(ret);\n};\n\nconst availableWidgetsFilter = (elements: ElementCollection) => {\n return elements\n .selectByComponentData({\n key: 'core.extensionName',\n })\n .getElements<Widget>()\n .flatMap(elem => {\n const config = getComponentData<CardConfig>(elem, 'home.widget.config');\n return [\n WidgetSchema.parse({\n component: elem,\n name: getComponentData<string>(elem, 'core.extensionName'),\n title: getComponentData<string>(elem, 'title'),\n description: getComponentData<string>(elem, 'description'),\n settingsSchema: config?.settings?.schema,\n uiSchema: config?.settings?.uiSchema,\n width: config?.layout?.width?.defaultColumns,\n minWidth: config?.layout?.width?.minColumns,\n maxWidth: config?.layout?.width?.maxColumns,\n height: config?.layout?.height?.defaultRows,\n minHeight: config?.layout?.height?.minRows,\n maxHeight: config?.layout?.height?.maxRows,\n }),\n ];\n });\n};\n\n/**\n * A component that allows customizing components in home grid layout.\n *\n * @public\n */\nexport const CustomHomepageGrid = (props: CustomHomepageGridProps) => {\n const styles = useStyles();\n const theme = useTheme();\n const availableWidgets = useElementFilter(\n props.children,\n availableWidgetsFilter,\n [props],\n );\n const defaultLayout = useMemo(() => {\n return props.config\n ? convertConfigToDefaultWidgets(props.config, availableWidgets)\n : [];\n }, [props.config, availableWidgets]);\n const [storedWidgets, storeWidgets, isStorageLoading] =\n useHomeStorage(defaultLayout);\n const [widgets, setWidgets] = useState(storedWidgets);\n\n const preventDuplicateWidgets = props.preventDuplicateWidgets ?? false;\n\n const [addWidgetDialogOpen, setAddWidgetDialogOpen] = useState(false);\n const editModeOn = widgets.find(w => w.layout.isResizable) !== undefined;\n const [editMode, setEditMode] = useState(editModeOn);\n\n useEffect(() => {\n setWidgets(storedWidgets);\n }, [storedWidgets]);\n\n const getWidgetByName = (name: string) => {\n return availableWidgets.find(widget => widget.name === name);\n };\n\n const getWidgetNameFromKey = (key: string) => {\n return key.split('__')[0];\n };\n const { t } = useTranslationRef(homeTranslationRef);\n\n const getAvailableWidgets = () => {\n if (!preventDuplicateWidgets) {\n return availableWidgets;\n }\n const usedWidgetNames = new Set(\n widgets.map(w => getWidgetNameFromKey(w.id)),\n );\n return availableWidgets.filter(widget => !usedWidgetNames.has(widget.name));\n };\n\n const handleAdd = (widget: Widget) => {\n const widgetId = `${widget.name}__${widgets.length + 1}${Math.random()\n .toString(36)\n .slice(2)}`;\n\n setWidgets([\n ...widgets,\n {\n id: widgetId,\n layout: {\n i: widgetId,\n x: 0,\n y: Math.max(...widgets.map(w => w.layout.y + w.layout.h)) + 1,\n w: Math.min(widget.maxWidth ?? Number.MAX_VALUE, widget.width ?? 12),\n h: Math.min(widget.maxHeight ?? Number.MAX_VALUE, widget.height ?? 4),\n minW: widget.minWidth,\n maxW: widget.maxWidth,\n minH: widget.minHeight,\n maxH: widget.maxHeight,\n isResizable: editMode,\n isDraggable: editMode,\n },\n settings: {},\n movable: widget.movable,\n deletable: widget.deletable,\n resizable: widget.resizable,\n },\n ]);\n setAddWidgetDialogOpen(false);\n };\n\n const handleRemove = (widgetId: string) => {\n setWidgets(widgets.filter(w => w.id !== widgetId));\n };\n\n const handleSettingsSave = (\n widgetId: string,\n widgetSettings: Record<string, any>,\n ) => {\n const idx = widgets.findIndex(w => w.id === widgetId);\n if (idx >= 0) {\n const widget = widgets[idx];\n widget.settings = widgetSettings;\n widgets[idx] = widget;\n setWidgets(widgets);\n }\n };\n\n const clearLayout = () => {\n setWidgets(widgets.filter(w => w.deletable === false));\n };\n\n const changeEditMode = (mode: boolean) => {\n setEditMode(mode);\n\n const newWidgets = widgets.map(w => {\n const resizable = w.resizable === false ? false : mode;\n const movable = w.movable === false ? false : mode;\n return {\n ...w,\n layout: { ...w.layout, isDraggable: movable, isResizable: resizable },\n };\n });\n\n if (mode) {\n setWidgets(newWidgets);\n } else {\n storeWidgets(newWidgets);\n }\n };\n\n const handleLayoutChange = (newLayout: Layout[], _: Layouts) => {\n if (editMode) {\n const newWidgets = newLayout.map(l => {\n const widget = widgets.find(w => w.id === l.i);\n return {\n ...widget,\n layout: l,\n } as GridWidget;\n });\n setWidgets(newWidgets);\n }\n };\n\n const handleRestoreDefaultConfig = () => {\n setWidgets(\n defaultLayout.map(w => {\n const resizable = w.resizable === false ? false : editMode;\n const movable = w.movable === false ? false : editMode;\n return {\n ...w,\n layout: {\n ...w.layout,\n isDraggable: movable,\n isResizable: resizable,\n },\n };\n }),\n );\n };\n\n const handleCancel = () => {\n setWidgets(storedWidgets);\n setEditMode(false);\n };\n\n if (isStorageLoading) {\n return <Progress />;\n }\n\n return (\n <>\n <ContentHeader title={props.title}>\n <CustomHomepageButtons\n editMode={editMode}\n numWidgets={widgets.length}\n clearLayout={clearLayout}\n setAddWidgetDialogOpen={setAddWidgetDialogOpen}\n changeEditMode={changeEditMode}\n defaultConfigAvailable={props.config !== undefined}\n restoreDefault={handleRestoreDefaultConfig}\n cancel={handleCancel}\n />\n </ContentHeader>\n <Dialog\n open={addWidgetDialogOpen}\n onClose={() => setAddWidgetDialogOpen(false)}\n >\n {/* Only mount when open so the list does not update (e.g. remove the added widget) before the modal closes */}\n {addWidgetDialogOpen && (\n <AddWidgetDialog\n widgets={getAvailableWidgets()}\n handleAdd={handleAdd}\n />\n )}\n </Dialog>\n {!editMode && widgets.length === 0 && (\n <Typography variant=\"h5\" align=\"center\">\n {t('customHomepage.noWidgets')}\n </Typography>\n )}\n <ResponsiveGrid\n className={styles.responsiveGrid}\n measureBeforeMount\n compactType={props.compactType}\n style={props.style}\n allowOverlap={props.allowOverlap}\n preventCollision={props.preventCollision ?? true}\n draggableCancel=\".overlayGridItem,.widgetSettingsDialog,.disabled\"\n containerPadding={props.containerPadding}\n margin={props.containerMargin}\n breakpoints={\n props.breakpoints ? props.breakpoints : theme.breakpoints.values\n }\n cols={\n props.cols\n ? props.cols\n : { xl: 12, lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 }\n }\n rowHeight={props.rowHeight ?? 60}\n onLayoutChange={handleLayoutChange}\n layouts={{ xl: widgets.map(w => w.layout) }}\n >\n {widgets.map((w: GridWidget) => {\n const l = w.layout;\n const widgetName = getWidgetNameFromKey(l.i);\n const widget = getWidgetByName(widgetName);\n if (!widget || !widget.component) {\n return null;\n }\n\n const widgetProps = {\n ...widget.component.props,\n ...(w.settings ?? {}),\n };\n\n return (\n <div\n key={l.i}\n className={`${styles.widgetWrapper} ${editMode && 'edit'} ${\n w.movable === false && 'disabled'\n }`}\n >\n <ErrorBoundary>\n <widget.component.type {...widgetProps} />\n </ErrorBoundary>\n {editMode && (\n <WidgetSettingsOverlay\n id={l.i}\n widget={widget}\n handleRemove={handleRemove}\n handleSettingsSave={handleSettingsSave}\n settings={w.settings}\n deletable={w.deletable}\n />\n )}\n </div>\n );\n })}\n </ResponsiveGrid>\n </>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.esm.js","sources":["../../../src/components/CustomHomepage/types.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 { CSSProperties, ReactElement, ReactNode } from 'react';\nimport { Layout } from 'react-grid-layout';\nimport { z } from 'zod/v3';\nimport { RJSFSchema, UiSchema } from '@rjsf/utils';\n\nconst RSJFTypeSchema: z.ZodType<RJSFSchema> = z.any();\nconst RSJFTypeUiSchema: z.ZodType<UiSchema> = z.any();\nconst ReactElementSchema: z.ZodType<ReactElement> = z.any();\nconst LayoutSchema: z.ZodType<Layout> = z.any();\n\n/**\n * Breakpoint options for <CustomHomepageGridProps/>\n *\n * @public\n */\nexport type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\n/**\n * Props customizing the <CustomHomepageGrid/> component.\n *\n * @public\n */\nexport type CustomHomepageGridProps = {\n /**\n * Children contain all widgets user can configure on their own homepage.\n */\n children?: ReactNode;\n /**\n * Default layout for the homepage before users have modified it.\n */\n config?: LayoutConfiguration[];\n /**\n * Title displayed in the header of the grid. If not provided, no title will be shown.\n */\n title?: string;\n /**\n * Height of grid row in pixels.\n * @defaultValue 60\n */\n rowHeight?: number;\n /**\n * Screen width in pixels for different breakpoints.\n * @defaultValue theme breakpoints\n */\n breakpoints?: Record<Breakpoint, number>;\n /**\n * Number of grid columns for different breakpoints.\n * @defaultValue \\{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 \\}\n */\n cols?: Record<Breakpoint, number>;\n /**\n * Grid container padding (x, y) in pixels for all or specific breakpoints.\n * @defaultValue [0, 0]\n * @example [10, 10]\n * @example \\{ lg: [10, 10] \\}\n */\n containerPadding?: [number, number] | Record<Breakpoint, [number, number]>;\n /**\n * Grid container margin (x, y) in pixels for all or specific breakpoints.\n * @defaultValue [0, 0]\n * @example [10, 10]\n * @example \\{ lg: [10, 10] \\}\n */\n containerMargin?: [number, number] | Record<Breakpoint, [number, number]>;\n /**\n * Maximum number of rows user can have in the grid.\n * @defaultValue unlimited\n */\n maxRows?: number;\n /**\n * Custom style for grid.\n */\n style?: CSSProperties;\n /**\n * Compaction type of widgets in the grid. This controls where widgets are moved in case\n * they are overlapping in the grid.\n */\n compactType?: 'vertical' | 'horizontal' | null;\n /**\n * Controls if widgets can overlap in the grid. If true, grid can be placed one over the other.\n * @defaultValue false\n */\n allowOverlap?: boolean;\n /**\n * Controls if widgets can collide with each other. If true, grid items won't change position when being dragged over.\n * @defaultValue true\n */\n preventCollision?: boolean;\n};\n\nexport const LayoutConfigurationSchema = z.object({\n component: ReactElementSchema,\n x: z.number().nonnegative('x must be positive number'),\n y: z.number().nonnegative('y must be positive number'),\n width: z.number().positive('width must be positive number'),\n height: z.number().positive('height must be positive number'),\n movable: z.boolean().optional(),\n deletable: z.boolean().optional(),\n resizable: z.boolean().optional(),\n});\n\n/**\n * Layout configuration that can be passed to the custom home page.\n *\n * @public\n */\nexport type LayoutConfiguration = {\n component: ReactElement | string;\n x: number;\n y: number;\n width: number;\n height: number;\n movable?: boolean;\n deletable?: boolean;\n resizable?: boolean;\n};\n\nexport const WidgetSchema = z.object({\n name: z.string(),\n title: z.string().optional(),\n description: z.string().optional(),\n component: ReactElementSchema,\n width: z.number().positive('width must be positive number').optional(),\n height: z.number().positive('height must be positive number').optional(),\n minWidth: z.number().positive('minWidth must be positive number').optional(),\n maxWidth: z.number().positive('maxWidth must be positive number').optional(),\n minHeight: z\n .number()\n .positive('minHeight must be positive number')\n .optional(),\n maxHeight: z\n .number()\n .positive('maxHeight must be positive number')\n .optional(),\n settingsSchema: RSJFTypeSchema.optional(),\n uiSchema: RSJFTypeUiSchema.optional(),\n movable: z.boolean().optional(),\n deletable: z.boolean().optional(),\n resizable: z.boolean().optional(),\n});\n\nexport type Widget = z.infer<typeof WidgetSchema>;\n\nconst GridWidgetSchema = z.object({\n id: z.string(),\n layout: LayoutSchema,\n settings: z.record(z.string(), z.any()),\n movable: z.boolean().optional(),\n deletable: z.boolean().optional(),\n resizable: z.boolean().optional(),\n});\n\nexport type GridWidget = z.infer<typeof GridWidgetSchema>;\n\nexport const CustomHomepageGridStateV1Schema = z.object({\n version: z.literal(1),\n pages: z.record(z.string(), z.array(GridWidgetSchema)),\n});\n\nexport type CustomHomepageGridStateV1 = z.infer<\n typeof CustomHomepageGridStateV1Schema\n>;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.esm.js","sources":["../../../src/components/CustomHomepage/types.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 { CSSProperties, ReactElement, ReactNode } from 'react';\nimport { Layout } from 'react-grid-layout';\nimport { z } from 'zod/v3';\nimport { RJSFSchema, UiSchema } from '@rjsf/utils';\n\nconst RSJFTypeSchema: z.ZodType<RJSFSchema> = z.any();\nconst RSJFTypeUiSchema: z.ZodType<UiSchema> = z.any();\nconst ReactElementSchema: z.ZodType<ReactElement> = z.any();\nconst LayoutSchema: z.ZodType<Layout> = z.any();\n\n/**\n * Breakpoint options for <CustomHomepageGridProps/>\n *\n * @public\n */\nexport type Breakpoint = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\n/**\n * Props customizing the <CustomHomepageGrid/> component.\n *\n * @public\n */\nexport type CustomHomepageGridProps = {\n /**\n * Children contain all widgets user can configure on their own homepage.\n */\n children?: ReactNode;\n /**\n * Default layout for the homepage before users have modified it.\n */\n config?: LayoutConfiguration[];\n /**\n * Title displayed in the header of the grid. If not provided, no title will be shown.\n */\n title?: string;\n /**\n * Height of grid row in pixels.\n * @defaultValue 60\n */\n rowHeight?: number;\n /**\n * Screen width in pixels for different breakpoints.\n * @defaultValue theme breakpoints\n */\n breakpoints?: Record<Breakpoint, number>;\n /**\n * Number of grid columns for different breakpoints.\n * @defaultValue \\{ lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 \\}\n */\n cols?: Record<Breakpoint, number>;\n /**\n * Grid container padding (x, y) in pixels for all or specific breakpoints.\n * @defaultValue [0, 0]\n * @example [10, 10]\n * @example \\{ lg: [10, 10] \\}\n */\n containerPadding?: [number, number] | Record<Breakpoint, [number, number]>;\n /**\n * Grid container margin (x, y) in pixels for all or specific breakpoints.\n * @defaultValue [0, 0]\n * @example [10, 10]\n * @example \\{ lg: [10, 10] \\}\n */\n containerMargin?: [number, number] | Record<Breakpoint, [number, number]>;\n /**\n * Maximum number of rows user can have in the grid.\n * @defaultValue unlimited\n */\n maxRows?: number;\n /**\n * Custom style for grid.\n */\n style?: CSSProperties;\n /**\n * Compaction type of widgets in the grid. This controls where widgets are moved in case\n * they are overlapping in the grid.\n */\n compactType?: 'vertical' | 'horizontal' | null;\n /**\n * Controls if widgets can overlap in the grid. If true, grid can be placed one over the other.\n * @defaultValue false\n */\n allowOverlap?: boolean;\n /**\n * Controls if widgets can collide with each other. If true, grid items won't change position when being dragged over.\n * @defaultValue true\n */\n preventCollision?: boolean;\n /**\n * Controls if widgets can be added to the grid if they already exist. If true, widgets already present on the grid are excluded from the Add Widget dialog (preventing duplicates)\n * @defaultValue false\n */\n preventDuplicateWidgets?: boolean;\n};\n\nexport const LayoutConfigurationSchema = z.object({\n component: ReactElementSchema,\n x: z.number().nonnegative('x must be positive number'),\n y: z.number().nonnegative('y must be positive number'),\n width: z.number().positive('width must be positive number'),\n height: z.number().positive('height must be positive number'),\n movable: z.boolean().optional(),\n deletable: z.boolean().optional(),\n resizable: z.boolean().optional(),\n});\n\n/**\n * Layout configuration that can be passed to the custom home page.\n *\n * @public\n */\nexport type LayoutConfiguration = {\n component: ReactElement | string;\n x: number;\n y: number;\n width: number;\n height: number;\n movable?: boolean;\n deletable?: boolean;\n resizable?: boolean;\n};\n\nexport const WidgetSchema = z.object({\n name: z.string(),\n title: z.string().optional(),\n description: z.string().optional(),\n component: ReactElementSchema,\n width: z.number().positive('width must be positive number').optional(),\n height: z.number().positive('height must be positive number').optional(),\n minWidth: z.number().positive('minWidth must be positive number').optional(),\n maxWidth: z.number().positive('maxWidth must be positive number').optional(),\n minHeight: z\n .number()\n .positive('minHeight must be positive number')\n .optional(),\n maxHeight: z\n .number()\n .positive('maxHeight must be positive number')\n .optional(),\n settingsSchema: RSJFTypeSchema.optional(),\n uiSchema: RSJFTypeUiSchema.optional(),\n movable: z.boolean().optional(),\n deletable: z.boolean().optional(),\n resizable: z.boolean().optional(),\n});\n\nexport type Widget = z.infer<typeof WidgetSchema>;\n\nconst GridWidgetSchema = z.object({\n id: z.string(),\n layout: LayoutSchema,\n settings: z.record(z.string(), z.any()),\n movable: z.boolean().optional(),\n deletable: z.boolean().optional(),\n resizable: z.boolean().optional(),\n});\n\nexport type GridWidget = z.infer<typeof GridWidgetSchema>;\n\nexport const CustomHomepageGridStateV1Schema = z.object({\n version: z.literal(1),\n pages: z.record(z.string(), z.array(GridWidgetSchema)),\n});\n\nexport type CustomHomepageGridStateV1 = z.infer<\n typeof CustomHomepageGridStateV1Schema\n>;\n"],"names":[],"mappings":";;AAqBA,MAAM,cAAA,GAAwC,EAAE,GAAA,EAAI;AACpD,MAAM,gBAAA,GAAwC,EAAE,GAAA,EAAI;AACpD,MAAM,kBAAA,GAA8C,EAAE,GAAA,EAAI;AAC1D,MAAM,YAAA,GAAkC,EAAE,GAAA,EAAI;AAuFvC,MAAM,yBAAA,GAA4B,EAAE,MAAA,CAAO;AAAA,EAChD,SAAA,EAAW,kBAAA;AAAA,EACX,CAAA,EAAG,CAAA,CAAE,MAAA,EAAO,CAAE,YAAY,2BAA2B,CAAA;AAAA,EACrD,CAAA,EAAG,CAAA,CAAE,MAAA,EAAO,CAAE,YAAY,2BAA2B,CAAA;AAAA,EACrD,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,SAAS,+BAA+B,CAAA;AAAA,EAC1D,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAO,CAAE,SAAS,gCAAgC,CAAA;AAAA,EAC5D,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAC9B,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAChC,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA;AACzB,CAAC;AAkBM,MAAM,YAAA,GAAe,EAAE,MAAA,CAAO;AAAA,EACnC,IAAA,EAAM,EAAE,MAAA,EAAO;AAAA,EACf,KAAA,EAAO,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EAC3B,WAAA,EAAa,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS;AAAA,EACjC,SAAA,EAAW,kBAAA;AAAA,EACX,OAAO,CAAA,CAAE,MAAA,GAAS,QAAA,CAAS,+BAA+B,EAAE,QAAA,EAAS;AAAA,EACrE,QAAQ,CAAA,CAAE,MAAA,GAAS,QAAA,CAAS,gCAAgC,EAAE,QAAA,EAAS;AAAA,EACvE,UAAU,CAAA,CAAE,MAAA,GAAS,QAAA,CAAS,kCAAkC,EAAE,QAAA,EAAS;AAAA,EAC3E,UAAU,CAAA,CAAE,MAAA,GAAS,QAAA,CAAS,kCAAkC,EAAE,QAAA,EAAS;AAAA,EAC3E,WAAW,CAAA,CACR,MAAA,GACA,QAAA,CAAS,mCAAmC,EAC5C,QAAA,EAAS;AAAA,EACZ,WAAW,CAAA,CACR,MAAA,GACA,QAAA,CAAS,mCAAmC,EAC5C,QAAA,EAAS;AAAA,EACZ,cAAA,EAAgB,eAAe,QAAA,EAAS;AAAA,EACxC,QAAA,EAAU,iBAAiB,QAAA,EAAS;AAAA,EACpC,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAC9B,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAChC,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA;AACzB,CAAC;AAID,MAAM,gBAAA,GAAmB,EAAE,MAAA,CAAO;AAAA,EAChC,EAAA,EAAI,EAAE,MAAA,EAAO;AAAA,EACb,MAAA,EAAQ,YAAA;AAAA,EACR,QAAA,EAAU,EAAE,MAAA,CAAO,CAAA,CAAE,QAAO,EAAG,CAAA,CAAE,KAAK,CAAA;AAAA,EACtC,OAAA,EAAS,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAC9B,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,EAChC,SAAA,EAAW,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA;AACzB,CAAC,CAAA;AAIM,MAAM,+BAAA,GAAkC,EAAE,MAAA,CAAO;AAAA,EACtD,OAAA,EAAS,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,KAAA,EAAO,EAAE,MAAA,CAAO,CAAA,CAAE,QAAO,EAAG,CAAA,CAAE,KAAA,CAAM,gBAAgB,CAAC;AACvD,CAAC;;;;"}
package/dist/index.d.ts CHANGED
@@ -479,6 +479,11 @@ type CustomHomepageGridProps = {
479
479
  * @defaultValue true
480
480
  */
481
481
  preventCollision?: boolean;
482
+ /**
483
+ * Controls if widgets can be added to the grid if they already exist. If true, widgets already present on the grid are excluded from the Add Widget dialog (preventing duplicates)
484
+ * @defaultValue false
485
+ */
486
+ preventDuplicateWidgets?: boolean;
482
487
  };
483
488
  /**
484
489
  * Layout configuration that can be passed to the custom home page.
@@ -627,6 +632,7 @@ declare const SettingsModal: (props: {
627
632
  declare const homeTranslationRef: _backstage_frontend_plugin_api.TranslationRef<"home", {
628
633
  readonly "starredEntities.noStarredEntitiesMessage": "Click the star beside an entity name to add it to this list!";
629
634
  readonly "addWidgetDialog.title": "Add new widget to dashboard";
635
+ readonly "addWidgetDialog.noAvailableWidgets": "All available widgets have been added to the dashboard.";
630
636
  readonly "customHomepageButtons.cancel": "Cancel";
631
637
  readonly "customHomepageButtons.clearAll": "Clear all";
632
638
  readonly "customHomepageButtons.edit": "Edit";
@@ -1,5 +1,5 @@
1
1
  var name = "@backstage/plugin-home";
2
- var version = "0.9.8-next.0";
2
+ var version = "0.9.9-next.0";
3
3
  var description = "A Backstage plugin that helps you build a home page";
4
4
  var backstage = {
5
5
  role: "frontend-plugin",
@@ -4,7 +4,8 @@ const homeTranslationRef = createTranslationRef({
4
4
  id: "home",
5
5
  messages: {
6
6
  addWidgetDialog: {
7
- title: "Add new widget to dashboard"
7
+ title: "Add new widget to dashboard",
8
+ noAvailableWidgets: "All available widgets have been added to the dashboard."
8
9
  },
9
10
  customHomepageButtons: {
10
11
  edit: "Edit",
@@ -1 +1 @@
1
- {"version":3,"file":"translation.esm.js","sources":["../src/translation.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 { createTranslationRef } from '@backstage/frontend-plugin-api';\n\n/**\n * Translation reference for the home plugin.\n * Contains localized text strings for home page components and widgets.\n *\n * @public\n */\nexport const homeTranslationRef = createTranslationRef({\n id: 'home',\n messages: {\n addWidgetDialog: {\n title: 'Add new widget to dashboard',\n },\n customHomepageButtons: {\n edit: 'Edit',\n restoreDefaults: 'Restore defaults',\n clearAll: 'Clear all',\n addWidget: 'Add widget',\n save: 'Save',\n cancel: 'Cancel',\n },\n customHomepage: {\n noWidgets: \"No widgets added. Start by clicking the 'Add widget' button.\",\n },\n widgetSettingsOverlay: {\n editSettingsTooltip: 'Edit settings',\n /**\n * @deprecated Use `editSettingsTooltip` instead. This was a typo in the original key.\n */\n editSettingsTooptip: 'Edit settings',\n deleteWidgetTooltip: 'Delete widget',\n submitButtonTitle: 'Submit',\n cancelButtonTitle: 'Cancel',\n },\n starredEntityListItem: {\n removeFavoriteEntityTitle: 'Remove entity from favorites',\n },\n visitList: {\n empty: {\n title: 'There are no visits to show yet.',\n description:\n 'Once you start using Backstage, your visits will appear here as a quick link to carry on where you left off.',\n },\n few: {\n title: 'The more pages you visit, the more pages will appear here.',\n },\n },\n quickStart: {\n title: 'Onboarding',\n description: 'Get started with Backstage',\n learnMoreLinkTitle: 'Learn more',\n },\n starredEntities: {\n noStarredEntitiesMessage:\n 'Click the star beside an entity name to add it to this list!',\n },\n visitedByType: {\n action: {\n viewMore: 'View more',\n viewLess: 'View less',\n },\n },\n featuredDocsCard: {\n learnMoreTitle: 'LEARN MORE',\n empty: {\n title: 'No documents to show',\n description:\n 'Create your own document. Check out our Getting Started Information',\n learnMoreLinkTitle: 'DOCS',\n },\n },\n },\n});\n"],"names":[],"mappings":";;AAuBO,MAAM,qBAAqB,oBAAA,CAAqB;AAAA,EACrD,EAAA,EAAI,MAAA;AAAA,EACJ,QAAA,EAAU;AAAA,IACR,eAAA,EAAiB;AAAA,MACf,KAAA,EAAO;AAAA,KACT;AAAA,IACA,qBAAA,EAAuB;AAAA,MACrB,IAAA,EAAM,MAAA;AAAA,MACN,eAAA,EAAiB,kBAAA;AAAA,MACjB,QAAA,EAAU,WAAA;AAAA,MACV,SAAA,EAAW,YAAA;AAAA,MACX,IAAA,EAAM,MAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,cAAA,EAAgB;AAAA,MACd,SAAA,EAAW;AAAA,KACb;AAAA,IACA,qBAAA,EAAuB;AAAA,MACrB,mBAAA,EAAqB,eAAA;AAAA;AAAA;AAAA;AAAA,MAIrB,mBAAA,EAAqB,eAAA;AAAA,MACrB,mBAAA,EAAqB,eAAA;AAAA,MACrB,iBAAA,EAAmB,QAAA;AAAA,MACnB,iBAAA,EAAmB;AAAA,KACrB;AAAA,IACA,qBAAA,EAAuB;AAAA,MACrB,yBAAA,EAA2B;AAAA,KAC7B;AAAA,IACA,SAAA,EAAW;AAAA,MACT,KAAA,EAAO;AAAA,QACL,KAAA,EAAO,kCAAA;AAAA,QACP,WAAA,EACE;AAAA,OACJ;AAAA,MACA,GAAA,EAAK;AAAA,QACH,KAAA,EAAO;AAAA;AACT,KACF;AAAA,IACA,UAAA,EAAY;AAAA,MACV,KAAA,EAAO,YAAA;AAAA,MACP,WAAA,EAAa,4BAAA;AAAA,MACb,kBAAA,EAAoB;AAAA,KACtB;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,wBAAA,EACE;AAAA,KACJ;AAAA,IACA,aAAA,EAAe;AAAA,MACb,MAAA,EAAQ;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,QAAA,EAAU;AAAA;AACZ,KACF;AAAA,IACA,gBAAA,EAAkB;AAAA,MAChB,cAAA,EAAgB,YAAA;AAAA,MAChB,KAAA,EAAO;AAAA,QACL,KAAA,EAAO,sBAAA;AAAA,QACP,WAAA,EACE,qEAAA;AAAA,QACF,kBAAA,EAAoB;AAAA;AACtB;AACF;AAEJ,CAAC;;;;"}
1
+ {"version":3,"file":"translation.esm.js","sources":["../src/translation.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 { createTranslationRef } from '@backstage/frontend-plugin-api';\n\n/**\n * Translation reference for the home plugin.\n * Contains localized text strings for home page components and widgets.\n *\n * @public\n */\nexport const homeTranslationRef = createTranslationRef({\n id: 'home',\n messages: {\n addWidgetDialog: {\n title: 'Add new widget to dashboard',\n noAvailableWidgets:\n 'All available widgets have been added to the dashboard.',\n },\n customHomepageButtons: {\n edit: 'Edit',\n restoreDefaults: 'Restore defaults',\n clearAll: 'Clear all',\n addWidget: 'Add widget',\n save: 'Save',\n cancel: 'Cancel',\n },\n customHomepage: {\n noWidgets: \"No widgets added. Start by clicking the 'Add widget' button.\",\n },\n widgetSettingsOverlay: {\n editSettingsTooltip: 'Edit settings',\n /**\n * @deprecated Use `editSettingsTooltip` instead. This was a typo in the original key.\n */\n editSettingsTooptip: 'Edit settings',\n deleteWidgetTooltip: 'Delete widget',\n submitButtonTitle: 'Submit',\n cancelButtonTitle: 'Cancel',\n },\n starredEntityListItem: {\n removeFavoriteEntityTitle: 'Remove entity from favorites',\n },\n visitList: {\n empty: {\n title: 'There are no visits to show yet.',\n description:\n 'Once you start using Backstage, your visits will appear here as a quick link to carry on where you left off.',\n },\n few: {\n title: 'The more pages you visit, the more pages will appear here.',\n },\n },\n quickStart: {\n title: 'Onboarding',\n description: 'Get started with Backstage',\n learnMoreLinkTitle: 'Learn more',\n },\n starredEntities: {\n noStarredEntitiesMessage:\n 'Click the star beside an entity name to add it to this list!',\n },\n visitedByType: {\n action: {\n viewMore: 'View more',\n viewLess: 'View less',\n },\n },\n featuredDocsCard: {\n learnMoreTitle: 'LEARN MORE',\n empty: {\n title: 'No documents to show',\n description:\n 'Create your own document. Check out our Getting Started Information',\n learnMoreLinkTitle: 'DOCS',\n },\n },\n },\n});\n"],"names":[],"mappings":";;AAuBO,MAAM,qBAAqB,oBAAA,CAAqB;AAAA,EACrD,EAAA,EAAI,MAAA;AAAA,EACJ,QAAA,EAAU;AAAA,IACR,eAAA,EAAiB;AAAA,MACf,KAAA,EAAO,6BAAA;AAAA,MACP,kBAAA,EACE;AAAA,KACJ;AAAA,IACA,qBAAA,EAAuB;AAAA,MACrB,IAAA,EAAM,MAAA;AAAA,MACN,eAAA,EAAiB,kBAAA;AAAA,MACjB,QAAA,EAAU,WAAA;AAAA,MACV,SAAA,EAAW,YAAA;AAAA,MACX,IAAA,EAAM,MAAA;AAAA,MACN,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,cAAA,EAAgB;AAAA,MACd,SAAA,EAAW;AAAA,KACb;AAAA,IACA,qBAAA,EAAuB;AAAA,MACrB,mBAAA,EAAqB,eAAA;AAAA;AAAA;AAAA;AAAA,MAIrB,mBAAA,EAAqB,eAAA;AAAA,MACrB,mBAAA,EAAqB,eAAA;AAAA,MACrB,iBAAA,EAAmB,QAAA;AAAA,MACnB,iBAAA,EAAmB;AAAA,KACrB;AAAA,IACA,qBAAA,EAAuB;AAAA,MACrB,yBAAA,EAA2B;AAAA,KAC7B;AAAA,IACA,SAAA,EAAW;AAAA,MACT,KAAA,EAAO;AAAA,QACL,KAAA,EAAO,kCAAA;AAAA,QACP,WAAA,EACE;AAAA,OACJ;AAAA,MACA,GAAA,EAAK;AAAA,QACH,KAAA,EAAO;AAAA;AACT,KACF;AAAA,IACA,UAAA,EAAY;AAAA,MACV,KAAA,EAAO,YAAA;AAAA,MACP,WAAA,EAAa,4BAAA;AAAA,MACb,kBAAA,EAAoB;AAAA,KACtB;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,wBAAA,EACE;AAAA,KACJ;AAAA,IACA,aAAA,EAAe;AAAA,MACb,MAAA,EAAQ;AAAA,QACN,QAAA,EAAU,WAAA;AAAA,QACV,QAAA,EAAU;AAAA;AACZ,KACF;AAAA,IACA,gBAAA,EAAkB;AAAA,MAChB,cAAA,EAAgB,YAAA;AAAA,MAChB,KAAA,EAAO;AAAA,QACL,KAAA,EAAO,sBAAA;AAAA,QACP,WAAA,EACE,qEAAA;AAAA,QACF,kBAAA,EAAoB;AAAA;AACtB;AACF;AAEJ,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-home",
3
- "version": "0.9.8-next.0",
3
+ "version": "0.9.9-next.0",
4
4
  "description": "A Backstage plugin that helps you build a home page",
5
5
  "backstage": {
6
6
  "role": "frontend-plugin",
@@ -68,16 +68,16 @@
68
68
  "test": "backstage-cli package test"
69
69
  },
70
70
  "dependencies": {
71
- "@backstage/catalog-client": "1.16.1-next.0",
71
+ "@backstage/catalog-client": "1.16.1",
72
72
  "@backstage/catalog-model": "1.9.0",
73
73
  "@backstage/config": "1.3.8",
74
- "@backstage/core-app-api": "1.20.3-next.0",
75
- "@backstage/core-compat-api": "0.5.13-next.0",
76
- "@backstage/core-components": "0.18.12-next.0",
77
- "@backstage/core-plugin-api": "1.12.8-next.0",
78
- "@backstage/frontend-plugin-api": "0.17.3-next.0",
79
- "@backstage/plugin-catalog-react": "3.2.0-next.0",
80
- "@backstage/plugin-home-react": "0.1.40-next.0",
74
+ "@backstage/core-app-api": "1.20.4-next.0",
75
+ "@backstage/core-compat-api": "0.5.14-next.0",
76
+ "@backstage/core-components": "0.18.13-next.0",
77
+ "@backstage/core-plugin-api": "1.12.8",
78
+ "@backstage/frontend-plugin-api": "0.17.3",
79
+ "@backstage/plugin-catalog-react": "3.2.1-next.0",
80
+ "@backstage/plugin-home-react": "0.1.41-next.0",
81
81
  "@backstage/theme": "0.7.3",
82
82
  "@material-ui/core": "^4.12.2",
83
83
  "@material-ui/icons": "^4.9.1",
@@ -94,11 +94,11 @@
94
94
  "zod": "^3.25.76 || ^4.0.0"
95
95
  },
96
96
  "devDependencies": {
97
- "@backstage/cli": "0.36.4-next.0",
98
- "@backstage/dev-utils": "1.1.25-next.0",
99
- "@backstage/frontend-defaults": "0.5.4-next.0",
100
- "@backstage/plugin-catalog": "2.0.7-next.0",
101
- "@backstage/test-utils": "1.7.20-next.0",
97
+ "@backstage/cli": "0.36.4",
98
+ "@backstage/dev-utils": "1.1.26-next.0",
99
+ "@backstage/frontend-defaults": "0.5.5-next.0",
100
+ "@backstage/plugin-catalog": "2.0.8-next.0",
101
+ "@backstage/test-utils": "1.7.21-next.0",
102
102
  "@testing-library/dom": "^10.0.0",
103
103
  "@testing-library/jest-dom": "^6.0.0",
104
104
  "@testing-library/react": "^16.0.0",