@backstage/plugin-home 0.5.9-next.2 → 0.5.10-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/dist/index.esm.js CHANGED
@@ -1,31 +1,34 @@
1
- import { createRouteRef, createApiRef, createPlugin, createApiFactory, storageApiRef, identityApiRef, createRoutableExtension, createComponentExtension, useElementFilter, useApi, getComponentData } from '@backstage/core-plugin-api';
1
+ import { createRouteRef, createPlugin, createApiFactory, storageApiRef, identityApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
2
2
  import { createCardExtension as createCardExtension$1, SettingsModal as SettingsModal$1 } from '@backstage/plugin-home-react';
3
3
  import { WebStorage } from '@backstage/core-app-api';
4
- import React, { useCallback, useMemo, useEffect } from 'react';
5
- import { useLocation } from 'react-router-dom';
6
- import { WidthProvider, Responsive } from 'react-grid-layout';
4
+ import { v as visitsApiRef } from './esm/VisitListener-fa6f752b.esm.js';
5
+ export { C as CustomHomepageGrid, V as VisitListener, v as visitsApiRef } from './esm/VisitListener-fa6f752b.esm.js';
6
+ import React from 'react';
7
+ import 'react-router-dom';
8
+ import { makeStyles } from '@material-ui/core';
9
+ import 'react-grid-layout';
7
10
  import 'react-grid-layout/css/styles.css';
8
11
  import 'react-resizable/css/styles.css';
9
- import { makeStyles, createStyles, Dialog, DialogContent, Grid, Tooltip, DialogTitle, ListItemAvatar, useTheme } from '@material-ui/core';
10
- import { compact } from 'lodash';
11
- import useObservable from 'react-use/lib/useObservable';
12
- import { ContentHeader, ErrorBoundary } from '@backstage/core-components';
13
- import Typography from '@material-ui/core/Typography';
14
- import IconButton from '@material-ui/core/IconButton';
15
- import SettingsIcon from '@material-ui/icons/Settings';
16
- import DeleteIcon from '@material-ui/icons/Delete';
17
- import { withTheme } from '@rjsf/core-v5';
18
- import validator from '@rjsf/validator-ajv8';
19
- import List from '@material-ui/core/List';
20
- import ListItem from '@material-ui/core/ListItem';
21
- import AddIcon from '@material-ui/icons/Add';
22
- import ListItemText from '@material-ui/core/ListItemText';
23
- import Button from '@material-ui/core/Button';
24
- import SaveIcon from '@material-ui/icons/Save';
25
- import EditIcon from '@material-ui/icons/Edit';
26
- import CancelIcon from '@material-ui/icons/Cancel';
27
- import { z } from 'zod';
28
- import { stringifyEntityRef } from '@backstage/catalog-model';
12
+ import 'lodash';
13
+ import 'react-use/lib/useObservable';
14
+ import '@backstage/core-components';
15
+ import '@material-ui/core/Typography';
16
+ import '@material-ui/core/IconButton';
17
+ import '@material-ui/icons/Settings';
18
+ import '@material-ui/icons/Delete';
19
+ import '@rjsf/core';
20
+ import '@rjsf/material-ui';
21
+ import '@rjsf/validator-ajv8';
22
+ import '@material-ui/core/List';
23
+ import '@material-ui/core/ListItem';
24
+ import '@material-ui/icons/Add';
25
+ import '@material-ui/core/ListItemText';
26
+ import '@material-ui/core/Button';
27
+ import '@material-ui/icons/Save';
28
+ import '@material-ui/icons/Edit';
29
+ import '@material-ui/icons/Cancel';
30
+ import 'zod';
31
+ import '@backstage/catalog-model';
29
32
 
30
33
  const rootRouteRef = createRouteRef({
31
34
  id: "home"
@@ -143,10 +146,6 @@ class VisitsWebStorageApi {
143
146
  }
144
147
  }
145
148
 
146
- const visitsApiRef = createApiRef({
147
- id: "homepage.visits"
148
- });
149
-
150
149
  const homePlugin = createPlugin({
151
150
  id: "home",
152
151
  apis: [
@@ -166,7 +165,7 @@ const homePlugin = createPlugin({
166
165
  const HomepageCompositionRoot = homePlugin.provide(
167
166
  createRoutableExtension({
168
167
  name: "HomepageCompositionRoot",
169
- component: () => import('./esm/index-20932a73.esm.js').then((m) => m.HomepageCompositionRoot),
168
+ component: () => import('./esm/index-20e7c88d.esm.js').then((m) => m.HomepageCompositionRoot),
170
169
  mountPoint: rootRouteRef
171
170
  })
172
171
  );
@@ -263,593 +262,15 @@ const HeaderWorldClock = homePlugin.provide(
263
262
  const HomePageTopVisited = homePlugin.provide(
264
263
  createCardExtension$1({
265
264
  name: "HomePageTopVisited",
266
- components: () => import('./esm/TopVisited-918c6b5f.esm.js')
265
+ components: () => import('./esm/TopVisited-f4e8def1.esm.js')
267
266
  })
268
267
  );
269
268
  const HomePageRecentlyVisited = homePlugin.provide(
270
269
  createCardExtension$1({
271
270
  name: "HomePageRecentlyVisited",
272
- components: () => import('./esm/RecentlyVisited-618bf2be.esm.js')
273
- })
274
- );
275
-
276
- const Form = withTheme(require("@rjsf/material-ui-v5").Theme);
277
- const useStyles$3 = makeStyles(
278
- (theme) => createStyles({
279
- iconGrid: {
280
- height: "100%",
281
- "& *": {
282
- padding: 0
283
- }
284
- },
285
- settingsOverlay: {
286
- position: "absolute",
287
- backgroundColor: "rgba(40, 40, 40, 0.93)",
288
- width: "100%",
289
- height: "100%",
290
- top: 0,
291
- left: 0,
292
- padding: theme.spacing(2),
293
- color: "white"
294
- }
295
- })
296
- );
297
- const WidgetSettingsOverlay = (props) => {
298
- const { id, widget, settings, handleRemove, handleSettingsSave, deletable } = props;
299
- const [settingsDialogOpen, setSettingsDialogOpen] = React.useState(false);
300
- const styles = useStyles$3();
301
- return /* @__PURE__ */ React.createElement("div", { className: styles.settingsOverlay }, widget.settingsSchema && /* @__PURE__ */ React.createElement(
302
- Dialog,
303
- {
304
- open: settingsDialogOpen,
305
- className: "widgetSettingsDialog",
306
- onClose: () => setSettingsDialogOpen(false)
307
- },
308
- /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(
309
- Form,
310
- {
311
- validator,
312
- showErrorList: false,
313
- schema: widget.settingsSchema,
314
- uiSchema: widget.uiSchema,
315
- noHtml5Validate: true,
316
- formData: settings,
317
- formContext: { settings },
318
- onSubmit: ({ formData, errors }) => {
319
- if (errors.length === 0) {
320
- handleSettingsSave(id, formData);
321
- setSettingsDialogOpen(false);
322
- }
323
- }
324
- }
325
- ))
326
- ), /* @__PURE__ */ React.createElement(
327
- Grid,
328
- {
329
- container: true,
330
- className: styles.iconGrid,
331
- alignItems: "center",
332
- justifyContent: "center"
333
- },
334
- widget.settingsSchema && /* @__PURE__ */ React.createElement(Grid, { item: true, className: "overlayGridItem" }, /* @__PURE__ */ React.createElement(Tooltip, { title: "Edit settings" }, /* @__PURE__ */ React.createElement(
335
- IconButton,
336
- {
337
- color: "primary",
338
- onClick: () => setSettingsDialogOpen(true)
339
- },
340
- /* @__PURE__ */ React.createElement(SettingsIcon, { fontSize: "large" })
341
- ))),
342
- deletable !== false && /* @__PURE__ */ React.createElement(Grid, { item: true, className: "overlayGridItem" }, /* @__PURE__ */ React.createElement(Tooltip, { title: "Delete widget" }, /* @__PURE__ */ React.createElement(IconButton, { color: "secondary", onClick: () => handleRemove(id) }, /* @__PURE__ */ React.createElement(DeleteIcon, { fontSize: "large" }))))
343
- ));
344
- };
345
-
346
- const getTitle = (widget) => {
347
- return widget.title || widget.name;
348
- };
349
- const AddWidgetDialog = (props) => {
350
- const { widgets, handleAdd } = props;
351
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(DialogTitle, null, "Add new widget to dashboard"), /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(List, { dense: true }, widgets.map((widget) => {
352
- return /* @__PURE__ */ React.createElement(
353
- ListItem,
354
- {
355
- key: widget.name,
356
- button: true,
357
- onClick: () => handleAdd(widget)
358
- },
359
- /* @__PURE__ */ React.createElement(ListItemAvatar, null, /* @__PURE__ */ React.createElement(AddIcon, null)),
360
- /* @__PURE__ */ React.createElement(
361
- ListItemText,
362
- {
363
- secondary: widget.description && /* @__PURE__ */ React.createElement(
364
- Typography,
365
- {
366
- component: "span",
367
- variant: "caption",
368
- color: "textPrimary"
369
- },
370
- widget.description
371
- ),
372
- primary: /* @__PURE__ */ React.createElement(Typography, { variant: "body1", color: "textPrimary" }, getTitle(widget))
373
- }
374
- )
375
- );
376
- }))));
377
- };
378
-
379
- const useStyles$2 = makeStyles(
380
- (theme) => createStyles({
381
- contentHeaderBtn: {
382
- marginLeft: theme.spacing(2)
383
- },
384
- widgetWrapper: {
385
- "& > *:first-child": {
386
- width: "100%",
387
- height: "100%"
388
- }
389
- }
390
- })
391
- );
392
- const CustomHomepageButtons = (props) => {
393
- const {
394
- editMode,
395
- numWidgets,
396
- clearLayout,
397
- setAddWidgetDialogOpen,
398
- changeEditMode,
399
- defaultConfigAvailable,
400
- restoreDefault
401
- } = props;
402
- const styles = useStyles$2();
403
- return /* @__PURE__ */ React.createElement(React.Fragment, null, !editMode && numWidgets > 0 ? /* @__PURE__ */ React.createElement(
404
- Button,
405
- {
406
- variant: "contained",
407
- color: "primary",
408
- onClick: () => changeEditMode(true),
409
- size: "small",
410
- startIcon: /* @__PURE__ */ React.createElement(EditIcon, null)
411
- },
412
- "Edit"
413
- ) : /* @__PURE__ */ React.createElement(React.Fragment, null, defaultConfigAvailable && /* @__PURE__ */ React.createElement(
414
- Button,
415
- {
416
- variant: "contained",
417
- className: styles.contentHeaderBtn,
418
- onClick: restoreDefault,
419
- size: "small",
420
- startIcon: /* @__PURE__ */ React.createElement(CancelIcon, null)
421
- },
422
- "Restore defaults"
423
- ), numWidgets > 0 && /* @__PURE__ */ React.createElement(
424
- Button,
425
- {
426
- variant: "contained",
427
- color: "secondary",
428
- className: styles.contentHeaderBtn,
429
- onClick: clearLayout,
430
- size: "small",
431
- startIcon: /* @__PURE__ */ React.createElement(DeleteIcon, null)
432
- },
433
- "Clear all"
434
- ), /* @__PURE__ */ React.createElement(
435
- Button,
436
- {
437
- variant: "contained",
438
- className: styles.contentHeaderBtn,
439
- onClick: () => setAddWidgetDialogOpen(true),
440
- size: "small",
441
- startIcon: /* @__PURE__ */ React.createElement(AddIcon, null)
442
- },
443
- "Add widget"
444
- ), numWidgets > 0 && /* @__PURE__ */ React.createElement(
445
- Button,
446
- {
447
- className: styles.contentHeaderBtn,
448
- variant: "contained",
449
- color: "primary",
450
- onClick: () => changeEditMode(false),
451
- size: "small",
452
- startIcon: /* @__PURE__ */ React.createElement(SaveIcon, null)
453
- },
454
- "Save"
455
- )));
456
- };
457
-
458
- const RSJFTypeSchema = z.any();
459
- const RSJFTypeUiSchema = z.any();
460
- const ReactElementSchema = z.any();
461
- const LayoutSchema = z.any();
462
- const LayoutConfigurationSchema = z.object({
463
- component: ReactElementSchema,
464
- x: z.number().nonnegative("x must be positive number"),
465
- y: z.number().nonnegative("y must be positive number"),
466
- width: z.number().positive("width must be positive number"),
467
- height: z.number().positive("height must be positive number"),
468
- movable: z.boolean().optional(),
469
- deletable: z.boolean().optional(),
470
- resizable: z.boolean().optional()
471
- });
472
- const WidgetSchema = z.object({
473
- name: z.string(),
474
- title: z.string().optional(),
475
- description: z.string().optional(),
476
- component: ReactElementSchema,
477
- width: z.number().positive("width must be positive number").optional(),
478
- height: z.number().positive("height must be positive number").optional(),
479
- minWidth: z.number().positive("minWidth must be positive number").optional(),
480
- maxWidth: z.number().positive("maxWidth must be positive number").optional(),
481
- minHeight: z.number().positive("minHeight must be positive number").optional(),
482
- maxHeight: z.number().positive("maxHeight must be positive number").optional(),
483
- settingsSchema: RSJFTypeSchema.optional(),
484
- uiSchema: RSJFTypeUiSchema.optional(),
485
- movable: z.boolean().optional(),
486
- deletable: z.boolean().optional(),
487
- resizable: z.boolean().optional()
488
- });
489
- const GridWidgetSchema = z.object({
490
- id: z.string(),
491
- layout: LayoutSchema,
492
- settings: z.record(z.string(), z.any()),
493
- movable: z.boolean().optional(),
494
- deletable: z.boolean().optional(),
495
- resizable: z.boolean().optional()
496
- });
497
- const CustomHomepageGridStateV1Schema = z.object({
498
- version: z.literal(1),
499
- pages: z.record(z.string(), z.array(GridWidgetSchema))
500
- });
501
-
502
- const ResponsiveGrid = WidthProvider(Responsive);
503
- const useStyles$1 = makeStyles(
504
- (theme) => createStyles({
505
- responsiveGrid: {
506
- "& .react-grid-item > .react-resizable-handle:after": {
507
- position: "absolute",
508
- content: '""',
509
- borderStyle: "solid",
510
- borderWidth: "0 0 20px 20px",
511
- borderColor: `transparent transparent ${theme.palette.primary.light} transparent`
512
- }
513
- },
514
- contentHeaderBtn: {
515
- marginLeft: theme.spacing(2)
516
- },
517
- widgetWrapper: {
518
- '& > div[class*="MuiCard-root"]': {
519
- width: "100%",
520
- height: "100%"
521
- },
522
- '& div[class*="MuiCardContent-root"]': {
523
- overflow: "auto"
524
- },
525
- "& + .react-grid-placeholder": {
526
- backgroundColor: theme.palette.primary.light
527
- },
528
- "&.edit > :active": {
529
- cursor: "move"
530
- }
531
- }
271
+ components: () => import('./esm/RecentlyVisited-3a78670a.esm.js')
532
272
  })
533
273
  );
534
- function useHomeStorage(defaultWidgets) {
535
- const key = "home";
536
- const storageApi = useApi(storageApiRef).forBucket("home.customHomepage");
537
- const setWidgets = useCallback(
538
- (value) => {
539
- const grid = {
540
- version: 1,
541
- pages: {
542
- default: value
543
- }
544
- };
545
- storageApi.set(key, JSON.stringify(grid));
546
- },
547
- [key, storageApi]
548
- );
549
- const homeSnapshot = useObservable(
550
- storageApi.observe$(key),
551
- storageApi.snapshot(key)
552
- );
553
- const widgets = useMemo(() => {
554
- if (homeSnapshot.presence === "absent") {
555
- return defaultWidgets;
556
- }
557
- try {
558
- const grid = JSON.parse(homeSnapshot.value);
559
- return CustomHomepageGridStateV1Schema.parse(grid).pages.default;
560
- } catch (e) {
561
- return defaultWidgets;
562
- }
563
- }, [homeSnapshot, defaultWidgets]);
564
- return [widgets, setWidgets];
565
- }
566
- const convertConfigToDefaultWidgets = (config, availableWidgets) => {
567
- const ret = config.map((conf, i) => {
568
- var _a, _b;
569
- const c = LayoutConfigurationSchema.parse(conf);
570
- const name = React.isValidElement(c.component) ? getComponentData(c.component, "core.extensionName") : c.component;
571
- if (!name) {
572
- return null;
573
- }
574
- const widget = availableWidgets.find((w) => w.name === name);
575
- if (!widget) {
576
- return null;
577
- }
578
- const widgetId = `${widget.name}__${i}${Math.random().toString(36).slice(2)}`;
579
- return {
580
- id: widgetId,
581
- layout: {
582
- i: widgetId,
583
- x: c.x,
584
- y: c.y,
585
- w: Math.min((_a = widget.maxWidth) != null ? _a : Number.MAX_VALUE, c.width),
586
- h: Math.min((_b = widget.maxHeight) != null ? _b : Number.MAX_VALUE, c.height),
587
- minW: widget.minWidth,
588
- maxW: widget.maxWidth,
589
- minH: widget.minHeight,
590
- maxH: widget.maxHeight,
591
- isDraggable: false,
592
- isResizable: false
593
- },
594
- settings: {},
595
- movable: conf.movable,
596
- deletable: conf.deletable,
597
- resizable: conf.resizable
598
- };
599
- });
600
- return compact(ret);
601
- };
602
- const availableWidgetsFilter = (elements) => {
603
- return elements.selectByComponentData({
604
- key: "core.extensionName"
605
- }).getElements().flatMap((elem) => {
606
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
607
- const config = getComponentData(elem, "home.widget.config");
608
- return [
609
- WidgetSchema.parse({
610
- component: elem,
611
- name: getComponentData(elem, "core.extensionName"),
612
- title: getComponentData(elem, "title"),
613
- description: getComponentData(elem, "description"),
614
- settingsSchema: (_a = config == null ? void 0 : config.settings) == null ? void 0 : _a.schema,
615
- uiSchema: (_b = config == null ? void 0 : config.settings) == null ? void 0 : _b.uiSchema,
616
- width: (_d = (_c = config == null ? void 0 : config.layout) == null ? void 0 : _c.width) == null ? void 0 : _d.defaultColumns,
617
- minWidth: (_f = (_e = config == null ? void 0 : config.layout) == null ? void 0 : _e.width) == null ? void 0 : _f.minColumns,
618
- maxWidth: (_h = (_g = config == null ? void 0 : config.layout) == null ? void 0 : _g.width) == null ? void 0 : _h.maxColumns,
619
- height: (_j = (_i = config == null ? void 0 : config.layout) == null ? void 0 : _i.height) == null ? void 0 : _j.defaultRows,
620
- minHeight: (_l = (_k = config == null ? void 0 : config.layout) == null ? void 0 : _k.height) == null ? void 0 : _l.minRows,
621
- maxHeight: (_n = (_m = config == null ? void 0 : config.layout) == null ? void 0 : _m.height) == null ? void 0 : _n.maxRows
622
- })
623
- ];
624
- });
625
- };
626
- const CustomHomepageGrid = (props) => {
627
- var _a;
628
- const styles = useStyles$1();
629
- const theme = useTheme();
630
- const availableWidgets = useElementFilter(
631
- props.children,
632
- availableWidgetsFilter,
633
- [props]
634
- );
635
- const defaultLayout = props.config ? convertConfigToDefaultWidgets(props.config, availableWidgets) : [];
636
- const [widgets, setWidgets] = useHomeStorage(defaultLayout);
637
- const [addWidgetDialogOpen, setAddWidgetDialogOpen] = React.useState(false);
638
- const editModeOn = widgets.find((w) => w.layout.isResizable) !== void 0;
639
- const [editMode, setEditMode] = React.useState(editModeOn);
640
- const getWidgetByName = (name) => {
641
- return availableWidgets.find((widget) => widget.name === name);
642
- };
643
- const getWidgetNameFromKey = (key) => {
644
- return key.split("__")[0];
645
- };
646
- const handleAdd = (widget) => {
647
- var _a2, _b, _c, _d;
648
- const widgetId = `${widget.name}__${widgets.length + 1}${Math.random().toString(36).slice(2)}`;
649
- setWidgets([
650
- ...widgets,
651
- {
652
- id: widgetId,
653
- layout: {
654
- i: widgetId,
655
- x: 0,
656
- y: Math.max(...widgets.map((w) => w.layout.y + w.layout.h)) + 1,
657
- w: Math.min((_a2 = widget.maxWidth) != null ? _a2 : Number.MAX_VALUE, (_b = widget.width) != null ? _b : 12),
658
- h: Math.min((_c = widget.maxHeight) != null ? _c : Number.MAX_VALUE, (_d = widget.height) != null ? _d : 4),
659
- minW: widget.minWidth,
660
- maxW: widget.maxWidth,
661
- minH: widget.minHeight,
662
- maxH: widget.maxHeight,
663
- isResizable: editMode,
664
- isDraggable: editMode
665
- },
666
- settings: {},
667
- movable: widget.movable,
668
- deletable: widget.deletable,
669
- resizable: widget.resizable
670
- }
671
- ]);
672
- setAddWidgetDialogOpen(false);
673
- };
674
- const handleRemove = (widgetId) => {
675
- setWidgets(widgets.filter((w) => w.id !== widgetId));
676
- };
677
- const handleSettingsSave = (widgetId, widgetSettings) => {
678
- const idx = widgets.findIndex((w) => w.id === widgetId);
679
- if (idx >= 0) {
680
- const widget = widgets[idx];
681
- widget.settings = widgetSettings;
682
- widgets[idx] = widget;
683
- setWidgets(widgets);
684
- }
685
- };
686
- const clearLayout = () => {
687
- setWidgets([]);
688
- };
689
- const changeEditMode = (mode) => {
690
- setEditMode(mode);
691
- setWidgets(
692
- widgets.map((w) => {
693
- const resizable = w.resizable === false ? false : mode;
694
- const movable = w.movable === false ? false : mode;
695
- return {
696
- ...w,
697
- layout: { ...w.layout, isDraggable: movable, isResizable: resizable }
698
- };
699
- })
700
- );
701
- };
702
- const handleLayoutChange = (newLayout, _) => {
703
- if (editMode) {
704
- const newWidgets = newLayout.map((l) => {
705
- const widget = widgets.find((w) => w.id === l.i);
706
- return {
707
- ...widget,
708
- layout: l
709
- };
710
- });
711
- setWidgets(newWidgets);
712
- }
713
- };
714
- const handleRestoreDefaultConfig = () => {
715
- setWidgets(
716
- defaultLayout.map((w) => {
717
- const resizable = w.resizable === false ? false : editMode;
718
- const movable = w.movable === false ? false : editMode;
719
- return {
720
- ...w,
721
- layout: {
722
- ...w.layout,
723
- isDraggable: movable,
724
- isResizable: resizable
725
- }
726
- };
727
- })
728
- );
729
- };
730
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ContentHeader, { title: "" }, /* @__PURE__ */ React.createElement(
731
- CustomHomepageButtons,
732
- {
733
- editMode,
734
- numWidgets: widgets.length,
735
- clearLayout,
736
- setAddWidgetDialogOpen,
737
- changeEditMode,
738
- defaultConfigAvailable: props.config !== void 0,
739
- restoreDefault: handleRestoreDefaultConfig
740
- }
741
- )), /* @__PURE__ */ React.createElement(
742
- Dialog,
743
- {
744
- open: addWidgetDialogOpen,
745
- onClose: () => setAddWidgetDialogOpen(false)
746
- },
747
- /* @__PURE__ */ React.createElement(AddWidgetDialog, { widgets: availableWidgets, handleAdd })
748
- ), !editMode && widgets.length === 0 && /* @__PURE__ */ React.createElement(Typography, { variant: "h5", align: "center" }, "No widgets added. Start by clicking the 'Add widget' button."), /* @__PURE__ */ React.createElement(
749
- ResponsiveGrid,
750
- {
751
- className: styles.responsiveGrid,
752
- measureBeforeMount: true,
753
- compactType: props.compactType,
754
- style: props.style,
755
- allowOverlap: props.allowOverlap,
756
- preventCollision: props.preventCollision,
757
- draggableCancel: ".overlayGridItem,.widgetSettingsDialog,.disabled",
758
- containerPadding: props.containerPadding,
759
- margin: props.containerMargin,
760
- breakpoints: props.breakpoints ? props.breakpoints : theme.breakpoints.values,
761
- cols: props.cols ? props.cols : { xl: 12, lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },
762
- rowHeight: (_a = props.rowHeight) != null ? _a : 60,
763
- onLayoutChange: handleLayoutChange,
764
- layouts: { xl: widgets.map((w) => w.layout) }
765
- },
766
- widgets.map((w) => {
767
- var _a2;
768
- const l = w.layout;
769
- const widgetName = getWidgetNameFromKey(l.i);
770
- const widget = getWidgetByName(widgetName);
771
- if (!widget || !widget.component) {
772
- return null;
773
- }
774
- const widgetProps = {
775
- ...widget.component.props,
776
- ...(_a2 = w.settings) != null ? _a2 : {}
777
- };
778
- return /* @__PURE__ */ React.createElement(
779
- "div",
780
- {
781
- key: l.i,
782
- className: `${styles.widgetWrapper} ${editMode && "edit"} ${w.movable === false && "disabled"}`
783
- },
784
- /* @__PURE__ */ React.createElement(ErrorBoundary, null, /* @__PURE__ */ React.createElement(widget.component.type, { ...widgetProps })),
785
- editMode && /* @__PURE__ */ React.createElement(
786
- WidgetSettingsOverlay,
787
- {
788
- id: l.i,
789
- widget,
790
- handleRemove,
791
- handleSettingsSave,
792
- settings: w.settings,
793
- deletable: w.deletable
794
- }
795
- )
796
- );
797
- })
798
- ));
799
- };
800
-
801
- const getToEntityRef = ({
802
- rootPath = "catalog",
803
- stringifyEntityRefImpl = stringifyEntityRef
804
- } = {}) => ({ pathname }) => {
805
- const regex = new RegExp(
806
- `^/${rootPath}/(?<namespace>[^/]+)/(?<kind>[^/]+)/(?<name>[^/]+)`
807
- );
808
- const result = regex.exec(pathname);
809
- if (!result || !(result == null ? void 0 : result.groups))
810
- return void 0;
811
- const entity = {
812
- namespace: result.groups.namespace,
813
- kind: result.groups.kind,
814
- name: result.groups.name
815
- };
816
- return stringifyEntityRefImpl(entity);
817
- };
818
- const getVisitName = ({ rootPath = "catalog", document = global.document } = {}) => ({ pathname }) => {
819
- const regex = new RegExp(
820
- `^/${rootPath}/(?<namespace>[^/]+)/(?<kind>[^/]+)/(?<name>[^/]+)`
821
- );
822
- let result = regex.exec(pathname);
823
- if (result && (result == null ? void 0 : result.groups))
824
- return result.groups.name;
825
- result = /^\/(?<name>[^\/]+)$/.exec(pathname);
826
- if (result && (result == null ? void 0 : result.groups))
827
- return result.groups.name;
828
- return document.title;
829
- };
830
- const VisitListener = ({
831
- children,
832
- toEntityRef,
833
- visitName
834
- }) => {
835
- const visitsApi = useApi(visitsApiRef);
836
- const { pathname } = useLocation();
837
- const toEntityRefImpl = toEntityRef != null ? toEntityRef : getToEntityRef();
838
- const visitNameImpl = visitName != null ? visitName : getVisitName();
839
- useEffect(() => {
840
- const requestId = requestAnimationFrame(() => {
841
- visitsApi.save({
842
- visit: {
843
- name: visitNameImpl({ pathname }),
844
- pathname,
845
- entityRef: toEntityRefImpl({ pathname })
846
- }
847
- });
848
- });
849
- return () => cancelAnimationFrame(requestId);
850
- }, [visitsApi, pathname, toEntityRefImpl, visitNameImpl]);
851
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
852
- };
853
274
 
854
275
  const TemplateBackstageLogo = (props) => {
855
276
  return /* @__PURE__ */ React.createElement(
@@ -900,5 +321,5 @@ const TemplateBackstageLogoIcon = () => {
900
321
  const createCardExtension = createCardExtension$1;
901
322
  const SettingsModal = SettingsModal$1;
902
323
 
903
- export { ComponentAccordion, ComponentTab, ComponentTabs, CustomHomepageGrid, HeaderWorldClock, HomePageCompanyLogo, HomePageRandomJoke, HomePageRecentlyVisited, HomePageStarredEntities, HomePageToolkit, HomePageTopVisited, HomepageCompositionRoot, SettingsModal, TemplateBackstageLogo, TemplateBackstageLogoIcon, VisitListener, VisitsStorageApi, VisitsWebStorageApi, WelcomeTitle, createCardExtension, homePlugin, visitsApiRef };
324
+ export { ComponentAccordion, ComponentTab, ComponentTabs, HeaderWorldClock, HomePageCompanyLogo, HomePageRandomJoke, HomePageRecentlyVisited, HomePageStarredEntities, HomePageToolkit, HomePageTopVisited, HomepageCompositionRoot, SettingsModal, TemplateBackstageLogo, TemplateBackstageLogoIcon, VisitsStorageApi, VisitsWebStorageApi, WelcomeTitle, createCardExtension, homePlugin };
904
325
  //# sourceMappingURL=index.esm.js.map