@richardmcquiston01/dashboard-widgets-toolkit 0.8.0 → 0.10.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/core.cjs +605 -14
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +134 -3
- package/dist/core.d.ts +134 -3
- package/dist/core.js +583 -15
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +605 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +583 -15
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1202 -136
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +80 -3
- package/dist/react.d.ts +80 -3
- package/dist/react.js +1202 -136
- package/dist/react.js.map +1 -1
- package/dist/{scale-CrXxawQn.d.cts → scale-N69bo7wo.d.cts} +36 -1
- package/dist/{scale-CrXxawQn.d.ts → scale-N69bo7wo.d.ts} +36 -1
- package/dist/styles.css +173 -0
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -427,21 +427,36 @@ function fillColumnSpans(items, columns, largeSpan = 2) {
|
|
|
427
427
|
function fillWidthSpans(items) {
|
|
428
428
|
return placeAndFill(items, WIDTH_COLUMNS, itemWidth);
|
|
429
429
|
}
|
|
430
|
+
function placeRows(items) {
|
|
431
|
+
return placeAndFillRows(items, WIDTH_COLUMNS, itemWidth).rows;
|
|
432
|
+
}
|
|
430
433
|
function placeAndFill(items, columns, spanOf) {
|
|
434
|
+
return placeAndFillRows(items, columns, spanOf).spans;
|
|
435
|
+
}
|
|
436
|
+
function placeAndFillRows(items, columns, spanOf) {
|
|
431
437
|
const trackCount = Math.max(1, Math.floor(columns));
|
|
432
438
|
const spans = /* @__PURE__ */ new Map();
|
|
439
|
+
const rows = [];
|
|
433
440
|
let row = [];
|
|
434
441
|
let used = 0;
|
|
435
442
|
function closeRow() {
|
|
443
|
+
if (row.length === 0) return;
|
|
436
444
|
const fillers = row.filter(({ item }) => fillsWidth(item.fill));
|
|
437
445
|
const leftover = trackCount - used;
|
|
446
|
+
const finalSpans = /* @__PURE__ */ new Map();
|
|
438
447
|
if (fillers.length > 0) {
|
|
439
448
|
const share = Math.floor(leftover / fillers.length);
|
|
440
449
|
const remainder = leftover % fillers.length;
|
|
441
450
|
fillers.forEach(({ item, span }, index) => {
|
|
442
|
-
|
|
451
|
+
const grown = span + share + (index < remainder ? 1 : 0);
|
|
452
|
+
spans.set(item.key, grown);
|
|
453
|
+
finalSpans.set(item.key, grown);
|
|
443
454
|
});
|
|
444
455
|
}
|
|
456
|
+
rows.push({
|
|
457
|
+
keys: row.map(({ item }) => item.key),
|
|
458
|
+
spans: row.map(({ item, span }) => finalSpans.get(item.key) ?? span)
|
|
459
|
+
});
|
|
445
460
|
row = [];
|
|
446
461
|
used = 0;
|
|
447
462
|
}
|
|
@@ -452,7 +467,7 @@ function placeAndFill(items, columns, spanOf) {
|
|
|
452
467
|
used += span;
|
|
453
468
|
}
|
|
454
469
|
closeRow();
|
|
455
|
-
return spans;
|
|
470
|
+
return { spans, rows };
|
|
456
471
|
}
|
|
457
472
|
|
|
458
473
|
// src/core/scale.ts
|
|
@@ -522,6 +537,40 @@ var DEFAULT_LABELS = {
|
|
|
522
537
|
moveLater: (title) => `Move ${title} later`,
|
|
523
538
|
hiddenWidgets: "Hidden:",
|
|
524
539
|
minimizedWidgets: "Minimized:",
|
|
540
|
+
customize: "Customize",
|
|
541
|
+
done: "Done",
|
|
542
|
+
reset: "Reset layout",
|
|
543
|
+
revertChanges: "Revert changes",
|
|
544
|
+
confirmReset: "Reset the layout to the default?",
|
|
545
|
+
confirmRevert: "Revert to how this looked before you started editing?",
|
|
546
|
+
confirmYes: "Yes",
|
|
547
|
+
confirmNo: "No",
|
|
548
|
+
editingOn: "Editing dashboard. Use the buttons on each card to reorder or hide it.",
|
|
549
|
+
editingOff: "Finished editing.",
|
|
550
|
+
dashboardControls: "Dashboard controls",
|
|
551
|
+
locked: (title) => `${title} is locked`,
|
|
552
|
+
lockedForViewers: (title) => `${title} is locked for viewers`,
|
|
553
|
+
pageBar: "Pages",
|
|
554
|
+
pageTabName: (index, count, title) => `Page ${index} of ${count}: ${title}`,
|
|
555
|
+
previousPageButton: "Previous page",
|
|
556
|
+
nextPageButton: "Next page",
|
|
557
|
+
managePages: "Manage pages",
|
|
558
|
+
addPage: "Add page",
|
|
559
|
+
renamePage: (title) => `Rename ${title}`,
|
|
560
|
+
pageTitle: "Page title",
|
|
561
|
+
savePageTitle: "Save page title",
|
|
562
|
+
cancelPageTitle: "Cancel renaming",
|
|
563
|
+
deletePage: (title) => `Delete ${title}`,
|
|
564
|
+
confirmDeletePage: (title) => `Delete the page "${title}" and move its widgets to another page?`,
|
|
565
|
+
movePageLeft: (title) => `Move ${title} page left`,
|
|
566
|
+
movePageRight: (title) => `Move ${title} page right`,
|
|
567
|
+
moveToPage: (title) => `Move ${title} to another page`,
|
|
568
|
+
moveToPagePlaceholder: "Move to page\u2026",
|
|
569
|
+
moveToPageOption: (title, rowsFree) => `${title} (${rowsFree} ${rowsFree === 1 ? "row" : "rows"} free)`,
|
|
570
|
+
newPageOption: "New page\u2026",
|
|
571
|
+
movedToPage: (title, pageTitle) => `${title} moved to ${pageTitle}`,
|
|
572
|
+
pageFull: (pageTitle, maxRows) => `Page "${pageTitle}" is full (${maxRows} rows). Move or hide a widget first.`,
|
|
573
|
+
emptyPage: "This page has no widgets. Move one here from another page.",
|
|
525
574
|
opensInNewTab: "(opens in a new tab)",
|
|
526
575
|
view: (title) => `View ${title}`,
|
|
527
576
|
close: "Close",
|
|
@@ -1392,6 +1441,7 @@ function WidgetCard({
|
|
|
1392
1441
|
columnSpan,
|
|
1393
1442
|
width,
|
|
1394
1443
|
widgetKey,
|
|
1444
|
+
editing = false,
|
|
1395
1445
|
headingLevel = 2,
|
|
1396
1446
|
className,
|
|
1397
1447
|
children
|
|
@@ -1436,6 +1486,7 @@ function WidgetCard({
|
|
|
1436
1486
|
"dwt-card",
|
|
1437
1487
|
`dwt-card--${status}`,
|
|
1438
1488
|
minimized && "dwt-card--minimized",
|
|
1489
|
+
editing && "dwt-card--editing",
|
|
1439
1490
|
size !== void 0 && `dwt-card--size-${size}`,
|
|
1440
1491
|
fillsHeight(fill) && "dwt-card--fill-height",
|
|
1441
1492
|
fillsWidth(fill) && "dwt-card--fill-width",
|
|
@@ -1608,6 +1659,9 @@ function isWidgetVisibleTo(definition, roles) {
|
|
|
1608
1659
|
}
|
|
1609
1660
|
|
|
1610
1661
|
// src/core/layout.ts
|
|
1662
|
+
var MAX_PAGE_TITLE_LENGTH = 30;
|
|
1663
|
+
var MAX_PARSED_PAGES = 50;
|
|
1664
|
+
var MAX_PAGE_ROWS = 20;
|
|
1611
1665
|
var EMPTY_LAYOUT = Object.freeze({
|
|
1612
1666
|
order: Object.freeze([]),
|
|
1613
1667
|
hidden: Object.freeze([]),
|
|
@@ -1722,6 +1776,22 @@ function restoreWidget(layout, key) {
|
|
|
1722
1776
|
function toggleMinimized(layout, key) {
|
|
1723
1777
|
return isMinimized(layout, key) ? restoreWidget(layout, key) : minimizeWidget(layout, key);
|
|
1724
1778
|
}
|
|
1779
|
+
function mapLayoutLists(layout, change) {
|
|
1780
|
+
const top = change(layout);
|
|
1781
|
+
const pages = layout.pages?.map((page) => {
|
|
1782
|
+
const next = change(page);
|
|
1783
|
+
return next.order === page.order && next.hidden === page.hidden && next.minimized === page.minimized ? page : { ...page, ...next };
|
|
1784
|
+
});
|
|
1785
|
+
const pagesChanged = pages !== void 0 && pages.some((page, i) => page !== layout.pages?.[i]);
|
|
1786
|
+
if (top.order === layout.order && top.hidden === layout.hidden && top.minimized === layout.minimized && !pagesChanged) {
|
|
1787
|
+
return layout;
|
|
1788
|
+
}
|
|
1789
|
+
return {
|
|
1790
|
+
...layout,
|
|
1791
|
+
...top,
|
|
1792
|
+
...pages === void 0 ? {} : { pages }
|
|
1793
|
+
};
|
|
1794
|
+
}
|
|
1725
1795
|
function enforceLocks(definitions, layout, options = {}) {
|
|
1726
1796
|
if (options.overrideLocks === true) return layout;
|
|
1727
1797
|
const noMove = /* @__PURE__ */ new Set();
|
|
@@ -1733,11 +1803,337 @@ function enforceLocks(definitions, layout, options = {}) {
|
|
|
1733
1803
|
if (lock.hide) noHide.add(definition.key);
|
|
1734
1804
|
if (lock.minimize) noMinimize.add(definition.key);
|
|
1735
1805
|
}
|
|
1736
|
-
const
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1806
|
+
const without2 = (keys, drop) => keys.some((key) => drop.has(key)) ? keys.filter((key) => !drop.has(key)) : keys;
|
|
1807
|
+
return mapLayoutLists(layout, (lists) => ({
|
|
1808
|
+
order: without2(lists.order, noMove),
|
|
1809
|
+
hidden: without2(lists.hidden, noHide),
|
|
1810
|
+
minimized: without2(lists.minimized, noMinimize)
|
|
1811
|
+
}));
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
// src/core/pages.ts
|
|
1815
|
+
var DEFAULT_PAGE_KEY = "default";
|
|
1816
|
+
var DEFAULT_PAGE_ROWS = 4;
|
|
1817
|
+
function rowsAllowed(page, options) {
|
|
1818
|
+
const rows = page.maxRows ?? options.maxRows ?? DEFAULT_PAGE_ROWS;
|
|
1819
|
+
return Math.max(1, Math.min(MAX_PAGE_ROWS, Math.floor(rows)));
|
|
1820
|
+
}
|
|
1821
|
+
function hasPages(layout) {
|
|
1822
|
+
return layout.pages !== void 0 && layout.pages.length > 0;
|
|
1823
|
+
}
|
|
1824
|
+
function pageList(layout) {
|
|
1825
|
+
if (layout.pages !== void 0 && layout.pages.length > 0) {
|
|
1826
|
+
return layout.pages;
|
|
1827
|
+
}
|
|
1828
|
+
return [
|
|
1829
|
+
{
|
|
1830
|
+
key: DEFAULT_PAGE_KEY,
|
|
1831
|
+
title: "Page 1",
|
|
1832
|
+
order: layout.order,
|
|
1833
|
+
hidden: layout.hidden,
|
|
1834
|
+
minimized: layout.minimized
|
|
1835
|
+
}
|
|
1836
|
+
];
|
|
1837
|
+
}
|
|
1838
|
+
function withExplicitPages(layout) {
|
|
1839
|
+
if (hasPages(layout)) return layout;
|
|
1840
|
+
return {
|
|
1841
|
+
...layout,
|
|
1842
|
+
order: [],
|
|
1843
|
+
hidden: [],
|
|
1844
|
+
minimized: [],
|
|
1845
|
+
pages: pageList(layout)
|
|
1846
|
+
};
|
|
1847
|
+
}
|
|
1848
|
+
function sameKeys(a, b) {
|
|
1849
|
+
return a === b || a.length === b.length && a.every((k, i) => k === b[i]);
|
|
1850
|
+
}
|
|
1851
|
+
function pageLayout(layout, pageKey) {
|
|
1852
|
+
if (!hasPages(layout))
|
|
1853
|
+
return pageKey === DEFAULT_PAGE_KEY ? layout : void 0;
|
|
1854
|
+
const page = layout.pages?.find(
|
|
1855
|
+
(p) => p.key === pageKey
|
|
1856
|
+
);
|
|
1857
|
+
if (page === void 0) return void 0;
|
|
1858
|
+
const { pages, ...rest } = layout;
|
|
1859
|
+
return {
|
|
1860
|
+
...rest,
|
|
1861
|
+
order: page.order,
|
|
1862
|
+
hidden: page.hidden,
|
|
1863
|
+
minimized: page.minimized
|
|
1864
|
+
};
|
|
1865
|
+
}
|
|
1866
|
+
function withPageLayout(layout, pageKey, next) {
|
|
1867
|
+
const current = pageLayout(layout, pageKey);
|
|
1868
|
+
if (current === void 0 || sameKeys(current.order, next.order) && sameKeys(current.hidden, next.hidden) && sameKeys(current.minimized, next.minimized)) {
|
|
1869
|
+
return layout;
|
|
1870
|
+
}
|
|
1871
|
+
if (!hasPages(layout)) {
|
|
1872
|
+
return {
|
|
1873
|
+
...layout,
|
|
1874
|
+
order: next.order,
|
|
1875
|
+
hidden: next.hidden,
|
|
1876
|
+
minimized: next.minimized
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
return {
|
|
1880
|
+
...layout,
|
|
1881
|
+
pages: (layout.pages ?? []).map(
|
|
1882
|
+
(page) => page.key === pageKey ? {
|
|
1883
|
+
...page,
|
|
1884
|
+
order: next.order,
|
|
1885
|
+
hidden: next.hidden,
|
|
1886
|
+
minimized: next.minimized
|
|
1887
|
+
} : page
|
|
1888
|
+
)
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1891
|
+
function normalizedTitle(title) {
|
|
1892
|
+
return title.trim().normalize("NFKC").toLowerCase();
|
|
1893
|
+
}
|
|
1894
|
+
function resolvePageKey(layout, reference) {
|
|
1895
|
+
if (reference === void 0 || reference === "") return void 0;
|
|
1896
|
+
const pages = pageList(layout);
|
|
1897
|
+
const byKey = pages.find((p) => p.key === reference);
|
|
1898
|
+
if (byKey !== void 0) return byKey.key;
|
|
1899
|
+
const wanted = normalizedTitle(reference);
|
|
1900
|
+
return pages.find((p) => normalizedTitle(p.title) === wanted)?.key;
|
|
1901
|
+
}
|
|
1902
|
+
function homePageKey(layout, item) {
|
|
1903
|
+
return resolvePageKey(layout, item.page) ?? pageList(layout)[0].key;
|
|
1904
|
+
}
|
|
1905
|
+
function assignPages(definitions, layout) {
|
|
1906
|
+
const pages = pageList(layout);
|
|
1907
|
+
const assigned = new Map(pages.map((p) => [p.key, []]));
|
|
1908
|
+
for (const definition of definitions) {
|
|
1909
|
+
let pageKey;
|
|
1910
|
+
if (!resolveWidgetLock(definition).move) {
|
|
1911
|
+
pageKey = pages.find(
|
|
1912
|
+
(p) => p.order.includes(definition.key) || p.hidden.includes(definition.key)
|
|
1913
|
+
)?.key;
|
|
1914
|
+
}
|
|
1915
|
+
assigned.get(pageKey ?? homePageKey(layout, definition))?.push(definition);
|
|
1916
|
+
}
|
|
1917
|
+
return assigned;
|
|
1918
|
+
}
|
|
1919
|
+
function pageOf(definitions, layout, key) {
|
|
1920
|
+
for (const [pageKey, widgets] of assignPages(definitions, layout)) {
|
|
1921
|
+
if (widgets.some((w) => w.key === key)) return pageKey;
|
|
1922
|
+
}
|
|
1923
|
+
return void 0;
|
|
1924
|
+
}
|
|
1925
|
+
function pageWidgets(definitions, layout, pageKey) {
|
|
1926
|
+
const onPage = assignPages(definitions, layout).get(pageKey) ?? [];
|
|
1927
|
+
const view = pageLayout(layout, pageKey);
|
|
1928
|
+
return view === void 0 ? [] : visibleWidgets(onPage, view);
|
|
1929
|
+
}
|
|
1930
|
+
function pageRoom(definitions, layout, pageKey, options = {}) {
|
|
1931
|
+
const page = pageList(layout).find(
|
|
1932
|
+
(p) => p.key === pageKey
|
|
1933
|
+
);
|
|
1934
|
+
if (page === void 0) return void 0;
|
|
1935
|
+
const maxRows = rowsAllowed(page, options);
|
|
1936
|
+
const rowsUsed = placeRows(
|
|
1937
|
+
pageWidgets(definitions, layout, pageKey)
|
|
1938
|
+
).length;
|
|
1939
|
+
return { maxRows, rowsUsed, rowsFree: Math.max(0, maxRows - rowsUsed) };
|
|
1940
|
+
}
|
|
1941
|
+
function describePage(page) {
|
|
1942
|
+
return `Page "${page.title}"`;
|
|
1943
|
+
}
|
|
1944
|
+
function titleOf(item) {
|
|
1945
|
+
return item.title ?? item.key;
|
|
1946
|
+
}
|
|
1947
|
+
function checkTitle(layout, title, exceptKey) {
|
|
1948
|
+
const trimmed = title.trim();
|
|
1949
|
+
if (trimmed === "") return err("A page title must not be empty.");
|
|
1950
|
+
if (trimmed.length > MAX_PAGE_TITLE_LENGTH) {
|
|
1951
|
+
return err(
|
|
1952
|
+
`Page title "${trimmed}" is ${trimmed.length} characters; the most is ${MAX_PAGE_TITLE_LENGTH}.`
|
|
1953
|
+
);
|
|
1954
|
+
}
|
|
1955
|
+
const wanted = normalizedTitle(trimmed);
|
|
1956
|
+
const clash = pageList(layout).find(
|
|
1957
|
+
(p) => p.key !== exceptKey && normalizedTitle(p.title) === wanted
|
|
1958
|
+
);
|
|
1959
|
+
if (clash !== void 0) {
|
|
1960
|
+
return err(`Another page is already called "${clash.title}".`);
|
|
1961
|
+
}
|
|
1962
|
+
return ok(trimmed);
|
|
1963
|
+
}
|
|
1964
|
+
function nextPageKey(layout) {
|
|
1965
|
+
const keys = new Set(pageList(layout).map((p) => p.key));
|
|
1966
|
+
let n = 1;
|
|
1967
|
+
while (keys.has(`page-${n}`)) n += 1;
|
|
1968
|
+
return `page-${n}`;
|
|
1969
|
+
}
|
|
1970
|
+
function nextPageTitle(layout) {
|
|
1971
|
+
const used = new Set(
|
|
1972
|
+
pageList(layout).map((p) => normalizedTitle(p.title))
|
|
1973
|
+
);
|
|
1974
|
+
let n = pageList(layout).length + 1;
|
|
1975
|
+
while (used.has(normalizedTitle(`Page ${n}`))) n += 1;
|
|
1976
|
+
return `Page ${n}`;
|
|
1977
|
+
}
|
|
1978
|
+
function addPage(layout, options = {}) {
|
|
1979
|
+
if (pageList(layout).length >= MAX_PARSED_PAGES) {
|
|
1980
|
+
return err(
|
|
1981
|
+
`The layout already has ${MAX_PARSED_PAGES} pages, the most it can keep.`
|
|
1982
|
+
);
|
|
1983
|
+
}
|
|
1984
|
+
const key = options.key ?? nextPageKey(layout);
|
|
1985
|
+
if (pageList(layout).some((p) => p.key === key)) {
|
|
1986
|
+
return err(`A page with the key "${key}" already exists.`);
|
|
1987
|
+
}
|
|
1988
|
+
const title = checkTitle(
|
|
1989
|
+
layout,
|
|
1990
|
+
options.title ?? nextPageTitle(layout)
|
|
1991
|
+
);
|
|
1992
|
+
if (!title.ok) return title;
|
|
1993
|
+
const base = withExplicitPages(layout);
|
|
1994
|
+
const page = {
|
|
1995
|
+
key,
|
|
1996
|
+
title: title.value,
|
|
1997
|
+
order: [],
|
|
1998
|
+
hidden: [],
|
|
1999
|
+
minimized: []
|
|
2000
|
+
};
|
|
2001
|
+
return ok({ ...base, pages: [...base.pages ?? [], page] });
|
|
2002
|
+
}
|
|
2003
|
+
function renamePage(layout, pageKey, title) {
|
|
2004
|
+
const page = pageList(layout).find(
|
|
2005
|
+
(p) => p.key === pageKey
|
|
2006
|
+
);
|
|
2007
|
+
if (page === void 0) return err(`Page "${pageKey}" doesn't exist.`);
|
|
2008
|
+
const checked = checkTitle(layout, title, pageKey);
|
|
2009
|
+
if (!checked.ok) return checked;
|
|
2010
|
+
if (checked.value === page.title) return ok(layout);
|
|
2011
|
+
const base = withExplicitPages(layout);
|
|
2012
|
+
return ok({
|
|
2013
|
+
...base,
|
|
2014
|
+
pages: (base.pages ?? []).map(
|
|
2015
|
+
(p) => p.key === pageKey ? { ...p, title: checked.value } : p
|
|
2016
|
+
)
|
|
2017
|
+
});
|
|
2018
|
+
}
|
|
2019
|
+
function movePage(layout, pageKey, offset) {
|
|
2020
|
+
const pages = layout.pages ?? [];
|
|
2021
|
+
const from = pages.findIndex((p) => p.key === pageKey);
|
|
2022
|
+
if (from === -1) return layout;
|
|
2023
|
+
const to = Math.max(
|
|
2024
|
+
0,
|
|
2025
|
+
Math.min(pages.length - 1, from + Math.trunc(offset))
|
|
2026
|
+
);
|
|
2027
|
+
if (to === from) return layout;
|
|
2028
|
+
const next = [...pages];
|
|
2029
|
+
const [moved] = next.splice(from, 1);
|
|
2030
|
+
next.splice(to, 0, moved);
|
|
2031
|
+
return { ...layout, pages: next };
|
|
2032
|
+
}
|
|
2033
|
+
function overflowing(definitions, layout, options) {
|
|
2034
|
+
return pageList(layout).find(
|
|
2035
|
+
(page) => placeRows(pageWidgets(definitions, layout, page.key)).length > rowsAllowed(page, options)
|
|
2036
|
+
);
|
|
2037
|
+
}
|
|
2038
|
+
function removePage(definitions, layout, pageKey, options = {}) {
|
|
2039
|
+
const pages = pageList(layout);
|
|
2040
|
+
const index = pages.findIndex((p) => p.key === pageKey);
|
|
2041
|
+
const page = pages[index];
|
|
2042
|
+
if (page === void 0) return err(`Page "${pageKey}" doesn't exist.`);
|
|
2043
|
+
if (pages.length === 1) {
|
|
2044
|
+
return err(
|
|
2045
|
+
`${describePage(page)} is the only page, so it can't be removed.`
|
|
2046
|
+
);
|
|
2047
|
+
}
|
|
2048
|
+
const target = pages[index > 0 ? index - 1 : 1];
|
|
2049
|
+
const merged = {
|
|
2050
|
+
...layout,
|
|
2051
|
+
pages: pages.filter((p) => p.key !== pageKey).map(
|
|
2052
|
+
(p) => p.key === target.key ? {
|
|
2053
|
+
...p,
|
|
2054
|
+
order: index > 0 ? [...p.order, ...page.order] : [...page.order, ...p.order],
|
|
2055
|
+
hidden: [...p.hidden, ...page.hidden],
|
|
2056
|
+
minimized: [...p.minimized, ...page.minimized]
|
|
2057
|
+
} : p
|
|
2058
|
+
)
|
|
2059
|
+
};
|
|
2060
|
+
const full = overflowing(
|
|
2061
|
+
definitions,
|
|
2062
|
+
merged,
|
|
2063
|
+
options
|
|
2064
|
+
);
|
|
2065
|
+
if (full !== void 0) {
|
|
2066
|
+
return err(
|
|
2067
|
+
`${describePage(page)} has widgets that don't fit on the other pages (${describePage(full)} would need more than ${rowsAllowed(full, options)} rows). Move or hide some first.`
|
|
2068
|
+
);
|
|
2069
|
+
}
|
|
2070
|
+
return ok(merged);
|
|
2071
|
+
}
|
|
2072
|
+
function without(keys, key) {
|
|
2073
|
+
return keys.includes(key) ? keys.filter((k) => k !== key) : keys;
|
|
2074
|
+
}
|
|
2075
|
+
function moveWidgetToPage(definitions, layout, widgetKey, targetKey, options = {}) {
|
|
2076
|
+
const widget = definitions.find((d) => d.key === widgetKey);
|
|
2077
|
+
if (widget === void 0) {
|
|
2078
|
+
return err(
|
|
2079
|
+
`Widget "${widgetKey}" isn't one of the widgets, so it can't be moved to a page.`
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2082
|
+
const pages = pageList(layout);
|
|
2083
|
+
const target = pages.find((p) => p.key === targetKey);
|
|
2084
|
+
if (target === void 0) return err(`Page "${targetKey}" doesn't exist.`);
|
|
2085
|
+
const sourceKey = pageOf(definitions, layout, widgetKey);
|
|
2086
|
+
if (sourceKey === targetKey) return ok(layout);
|
|
2087
|
+
if (resolveWidgetLock(widget).move) {
|
|
2088
|
+
return err(
|
|
2089
|
+
`Widget "${titleOf(widget)}" is locked against moving, so it can't be moved to ${describePage(target)}.`
|
|
2090
|
+
);
|
|
2091
|
+
}
|
|
2092
|
+
const base = withExplicitPages(layout);
|
|
2093
|
+
const source = (base.pages ?? []).find(
|
|
2094
|
+
(p) => p.key === sourceKey
|
|
2095
|
+
);
|
|
2096
|
+
const hidden = source.hidden.includes(widgetKey);
|
|
2097
|
+
const minimized = source.minimized.includes(widgetKey);
|
|
2098
|
+
const targetOrder = pageWidgets(
|
|
2099
|
+
definitions,
|
|
2100
|
+
base,
|
|
2101
|
+
targetKey
|
|
2102
|
+
).map((d) => d.key);
|
|
2103
|
+
const moved = {
|
|
2104
|
+
...base,
|
|
2105
|
+
pages: (base.pages ?? []).map((p) => {
|
|
2106
|
+
if (p.key === sourceKey) {
|
|
2107
|
+
return {
|
|
2108
|
+
...p,
|
|
2109
|
+
order: without(p.order, widgetKey),
|
|
2110
|
+
hidden: without(p.hidden, widgetKey),
|
|
2111
|
+
minimized: without(p.minimized, widgetKey)
|
|
2112
|
+
};
|
|
2113
|
+
}
|
|
2114
|
+
if (p.key === targetKey) {
|
|
2115
|
+
return {
|
|
2116
|
+
...p,
|
|
2117
|
+
order: hidden ? p.order : [...targetOrder, widgetKey],
|
|
2118
|
+
hidden: hidden ? [...p.hidden, widgetKey] : p.hidden,
|
|
2119
|
+
minimized: minimized ? [...p.minimized, widgetKey] : p.minimized
|
|
2120
|
+
};
|
|
2121
|
+
}
|
|
2122
|
+
return p;
|
|
2123
|
+
})
|
|
2124
|
+
};
|
|
2125
|
+
if (!hidden) {
|
|
2126
|
+
const allowed = rowsAllowed(target, options);
|
|
2127
|
+
const needed = placeRows(
|
|
2128
|
+
pageWidgets(definitions, moved, targetKey)
|
|
2129
|
+
).length;
|
|
2130
|
+
if (needed > allowed) {
|
|
2131
|
+
return err(
|
|
2132
|
+
`${describePage(target)} has no room for "${titleOf(widget)}": it would need row ${needed}, and the page allows ${allowed}.`
|
|
2133
|
+
);
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
return ok(moved);
|
|
1741
2137
|
}
|
|
1742
2138
|
function nextSort(current, column) {
|
|
1743
2139
|
if (current?.column !== column) return { column, direction: "asc" };
|
|
@@ -2018,6 +2414,25 @@ function useDetailData(definition, load, enabled, fallback) {
|
|
|
2018
2414
|
}, [enabled, load, fallback, definition, attempt]);
|
|
2019
2415
|
return { state, reload: () => setAttempt((count) => count + 1) };
|
|
2020
2416
|
}
|
|
2417
|
+
var NEW_PAGE_VALUE = "__new-page__";
|
|
2418
|
+
function PagePanel({
|
|
2419
|
+
paged,
|
|
2420
|
+
id,
|
|
2421
|
+
labelledBy,
|
|
2422
|
+
children
|
|
2423
|
+
}) {
|
|
2424
|
+
if (!paged) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
2425
|
+
return /* @__PURE__ */ jsx(
|
|
2426
|
+
"div",
|
|
2427
|
+
{
|
|
2428
|
+
role: "tabpanel",
|
|
2429
|
+
id,
|
|
2430
|
+
"aria-labelledby": labelledBy,
|
|
2431
|
+
className: "dwt-page-panel",
|
|
2432
|
+
children
|
|
2433
|
+
}
|
|
2434
|
+
);
|
|
2435
|
+
}
|
|
2021
2436
|
var NARROW_VIEWPORT_QUERY = "(max-width: 640px)";
|
|
2022
2437
|
var WIDE_GRID_PX = 900;
|
|
2023
2438
|
function useFillSpans(definitions, gridRef, twelve) {
|
|
@@ -2137,6 +2552,232 @@ function DetailHost({
|
|
|
2137
2552
|
}
|
|
2138
2553
|
) });
|
|
2139
2554
|
}
|
|
2555
|
+
function InlineConfirm({
|
|
2556
|
+
message,
|
|
2557
|
+
onAnswer
|
|
2558
|
+
}) {
|
|
2559
|
+
const slot = useSlotClassName();
|
|
2560
|
+
const { labels } = useWidgetSettings();
|
|
2561
|
+
const noRef = useRef(null);
|
|
2562
|
+
useEffect(() => {
|
|
2563
|
+
noRef.current?.focus();
|
|
2564
|
+
}, []);
|
|
2565
|
+
return /* @__PURE__ */ jsxs(
|
|
2566
|
+
"span",
|
|
2567
|
+
{
|
|
2568
|
+
role: "group",
|
|
2569
|
+
"aria-label": message,
|
|
2570
|
+
className: "dwt-confirm",
|
|
2571
|
+
onKeyDown: (event) => {
|
|
2572
|
+
if (event.key === "Escape") {
|
|
2573
|
+
event.stopPropagation();
|
|
2574
|
+
onAnswer(false);
|
|
2575
|
+
}
|
|
2576
|
+
},
|
|
2577
|
+
children: [
|
|
2578
|
+
/* @__PURE__ */ jsx("span", { role: "alert", className: "dwt-confirm-message", children: message }),
|
|
2579
|
+
/* @__PURE__ */ jsx(
|
|
2580
|
+
"button",
|
|
2581
|
+
{
|
|
2582
|
+
type: "button",
|
|
2583
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
2584
|
+
"aria-label": labels.confirmYes,
|
|
2585
|
+
title: labels.confirmYes,
|
|
2586
|
+
onClick: () => onAnswer(true),
|
|
2587
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2713" })
|
|
2588
|
+
}
|
|
2589
|
+
),
|
|
2590
|
+
/* @__PURE__ */ jsx(
|
|
2591
|
+
"button",
|
|
2592
|
+
{
|
|
2593
|
+
ref: noRef,
|
|
2594
|
+
type: "button",
|
|
2595
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
2596
|
+
"aria-label": labels.confirmNo,
|
|
2597
|
+
title: labels.confirmNo,
|
|
2598
|
+
onClick: () => onAnswer(false),
|
|
2599
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2715" })
|
|
2600
|
+
}
|
|
2601
|
+
)
|
|
2602
|
+
]
|
|
2603
|
+
}
|
|
2604
|
+
);
|
|
2605
|
+
}
|
|
2606
|
+
function PageTabs({
|
|
2607
|
+
pages,
|
|
2608
|
+
activeKey,
|
|
2609
|
+
idPrefix,
|
|
2610
|
+
panelId,
|
|
2611
|
+
announcement,
|
|
2612
|
+
onSelect
|
|
2613
|
+
}) {
|
|
2614
|
+
const slot = useSlotClassName();
|
|
2615
|
+
const { labels } = useWidgetSettings();
|
|
2616
|
+
const tabs = useRef(/* @__PURE__ */ new Map());
|
|
2617
|
+
const activeIndex = pages.findIndex((p) => p.key === activeKey);
|
|
2618
|
+
function onKeyDown(event, index) {
|
|
2619
|
+
const last = pages.length - 1;
|
|
2620
|
+
let next;
|
|
2621
|
+
switch (event.key) {
|
|
2622
|
+
case "ArrowRight":
|
|
2623
|
+
case "ArrowDown":
|
|
2624
|
+
next = index === last ? 0 : index + 1;
|
|
2625
|
+
break;
|
|
2626
|
+
case "ArrowLeft":
|
|
2627
|
+
case "ArrowUp":
|
|
2628
|
+
next = index === 0 ? last : index - 1;
|
|
2629
|
+
break;
|
|
2630
|
+
case "Home":
|
|
2631
|
+
next = 0;
|
|
2632
|
+
break;
|
|
2633
|
+
case "End":
|
|
2634
|
+
next = last;
|
|
2635
|
+
break;
|
|
2636
|
+
default:
|
|
2637
|
+
return;
|
|
2638
|
+
}
|
|
2639
|
+
event.preventDefault();
|
|
2640
|
+
const target = pages[next];
|
|
2641
|
+
if (target === void 0) return;
|
|
2642
|
+
onSelect(target.key);
|
|
2643
|
+
tabs.current.get(target.key)?.focus();
|
|
2644
|
+
}
|
|
2645
|
+
return /* @__PURE__ */ jsxs("div", { className: slot("pageBar", "dwt-pages"), children: [
|
|
2646
|
+
/* @__PURE__ */ jsx(
|
|
2647
|
+
"button",
|
|
2648
|
+
{
|
|
2649
|
+
type: "button",
|
|
2650
|
+
className: slot(
|
|
2651
|
+
"button",
|
|
2652
|
+
"dwt-button",
|
|
2653
|
+
"dwt-icon-button",
|
|
2654
|
+
"dwt-page-nav"
|
|
2655
|
+
),
|
|
2656
|
+
"aria-label": labels.previousPageButton,
|
|
2657
|
+
disabled: activeIndex <= 0,
|
|
2658
|
+
onClick: () => onSelect(pages[activeIndex - 1].key),
|
|
2659
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2039" })
|
|
2660
|
+
}
|
|
2661
|
+
),
|
|
2662
|
+
/* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": labels.pageBar, className: "dwt-page-tabs", children: pages.map((page, index) => {
|
|
2663
|
+
const selected = page.key === activeKey;
|
|
2664
|
+
return /* @__PURE__ */ jsxs(
|
|
2665
|
+
"button",
|
|
2666
|
+
{
|
|
2667
|
+
ref: (element) => {
|
|
2668
|
+
if (element === null) tabs.current.delete(page.key);
|
|
2669
|
+
else tabs.current.set(page.key, element);
|
|
2670
|
+
},
|
|
2671
|
+
type: "button",
|
|
2672
|
+
role: "tab",
|
|
2673
|
+
id: `${idPrefix}-tab-${index}`,
|
|
2674
|
+
"aria-selected": selected,
|
|
2675
|
+
"aria-controls": panelId,
|
|
2676
|
+
"aria-label": labels.pageTabName(
|
|
2677
|
+
index + 1,
|
|
2678
|
+
pages.length,
|
|
2679
|
+
page.title
|
|
2680
|
+
),
|
|
2681
|
+
title: page.title,
|
|
2682
|
+
tabIndex: selected ? 0 : -1,
|
|
2683
|
+
className: slot("button", "dwt-page-tab"),
|
|
2684
|
+
onClick: () => onSelect(page.key),
|
|
2685
|
+
onKeyDown: (event) => onKeyDown(event, index),
|
|
2686
|
+
children: [
|
|
2687
|
+
/* @__PURE__ */ jsx("span", { className: "dwt-page-tab-title", children: page.title }),
|
|
2688
|
+
/* @__PURE__ */ jsx("span", { className: "dwt-page-dot", "aria-hidden": "true" })
|
|
2689
|
+
]
|
|
2690
|
+
},
|
|
2691
|
+
page.key
|
|
2692
|
+
);
|
|
2693
|
+
}) }),
|
|
2694
|
+
/* @__PURE__ */ jsx(
|
|
2695
|
+
"button",
|
|
2696
|
+
{
|
|
2697
|
+
type: "button",
|
|
2698
|
+
className: slot(
|
|
2699
|
+
"button",
|
|
2700
|
+
"dwt-button",
|
|
2701
|
+
"dwt-icon-button",
|
|
2702
|
+
"dwt-page-nav"
|
|
2703
|
+
),
|
|
2704
|
+
"aria-label": labels.nextPageButton,
|
|
2705
|
+
disabled: activeIndex === pages.length - 1,
|
|
2706
|
+
onClick: () => onSelect(pages[activeIndex + 1].key),
|
|
2707
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u203A" })
|
|
2708
|
+
}
|
|
2709
|
+
),
|
|
2710
|
+
/* @__PURE__ */ jsx("span", { className: "dwt-visually-hidden", "aria-live": "polite", children: announcement })
|
|
2711
|
+
] });
|
|
2712
|
+
}
|
|
2713
|
+
function PageRenameForm({
|
|
2714
|
+
initial,
|
|
2715
|
+
onSubmit,
|
|
2716
|
+
onCancel
|
|
2717
|
+
}) {
|
|
2718
|
+
const slot = useSlotClassName();
|
|
2719
|
+
const { labels } = useWidgetSettings();
|
|
2720
|
+
const [title, setTitle] = useState(initial);
|
|
2721
|
+
const [error, setError] = useState(void 0);
|
|
2722
|
+
const inputRef = useRef(null);
|
|
2723
|
+
useEffect(() => {
|
|
2724
|
+
inputRef.current?.focus();
|
|
2725
|
+
inputRef.current?.select();
|
|
2726
|
+
}, []);
|
|
2727
|
+
return /* @__PURE__ */ jsxs(
|
|
2728
|
+
"form",
|
|
2729
|
+
{
|
|
2730
|
+
className: "dwt-page-rename",
|
|
2731
|
+
onSubmit: (event) => {
|
|
2732
|
+
event.preventDefault();
|
|
2733
|
+
setError(onSubmit(title));
|
|
2734
|
+
},
|
|
2735
|
+
onKeyDown: (event) => {
|
|
2736
|
+
if (event.key === "Escape") {
|
|
2737
|
+
event.stopPropagation();
|
|
2738
|
+
onCancel();
|
|
2739
|
+
}
|
|
2740
|
+
},
|
|
2741
|
+
children: [
|
|
2742
|
+
/* @__PURE__ */ jsx(
|
|
2743
|
+
"input",
|
|
2744
|
+
{
|
|
2745
|
+
ref: inputRef,
|
|
2746
|
+
type: "text",
|
|
2747
|
+
className: "dwt-page-title-input",
|
|
2748
|
+
"aria-label": labels.pageTitle,
|
|
2749
|
+
"aria-invalid": error !== void 0,
|
|
2750
|
+
maxLength: MAX_PAGE_TITLE_LENGTH,
|
|
2751
|
+
value: title,
|
|
2752
|
+
onChange: (event) => setTitle(event.target.value)
|
|
2753
|
+
}
|
|
2754
|
+
),
|
|
2755
|
+
/* @__PURE__ */ jsx(
|
|
2756
|
+
"button",
|
|
2757
|
+
{
|
|
2758
|
+
type: "submit",
|
|
2759
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
2760
|
+
"aria-label": labels.savePageTitle,
|
|
2761
|
+
title: labels.savePageTitle,
|
|
2762
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2713" })
|
|
2763
|
+
}
|
|
2764
|
+
),
|
|
2765
|
+
/* @__PURE__ */ jsx(
|
|
2766
|
+
"button",
|
|
2767
|
+
{
|
|
2768
|
+
type: "button",
|
|
2769
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
2770
|
+
"aria-label": labels.cancelPageTitle,
|
|
2771
|
+
title: labels.cancelPageTitle,
|
|
2772
|
+
onClick: onCancel,
|
|
2773
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2715" })
|
|
2774
|
+
}
|
|
2775
|
+
),
|
|
2776
|
+
error !== void 0 && /* @__PURE__ */ jsx("span", { role: "alert", className: "dwt-page-error", children: error })
|
|
2777
|
+
]
|
|
2778
|
+
}
|
|
2779
|
+
);
|
|
2780
|
+
}
|
|
2140
2781
|
function withoutLock(definition) {
|
|
2141
2782
|
if (definition.locked === void 0) return definition;
|
|
2142
2783
|
const copy = { ...definition };
|
|
@@ -2148,6 +2789,17 @@ function DashboardInner({
|
|
|
2148
2789
|
layout: savedLayout = EMPTY_LAYOUT,
|
|
2149
2790
|
onLayoutChange,
|
|
2150
2791
|
overrideLocks = false,
|
|
2792
|
+
editMode = "always",
|
|
2793
|
+
editing: editingProp,
|
|
2794
|
+
defaultEditing = false,
|
|
2795
|
+
onEditingChange,
|
|
2796
|
+
defaultLayout,
|
|
2797
|
+
toolbar = true,
|
|
2798
|
+
activePage: activePageProp,
|
|
2799
|
+
defaultActivePage,
|
|
2800
|
+
onActivePageChange,
|
|
2801
|
+
maxRows,
|
|
2802
|
+
maxPages,
|
|
2151
2803
|
onRetry,
|
|
2152
2804
|
loadDetail,
|
|
2153
2805
|
onOpenDetail,
|
|
@@ -2163,11 +2815,47 @@ function DashboardInner({
|
|
|
2163
2815
|
const byKey = new Map(
|
|
2164
2816
|
widgets.map((w) => [w.definition.key, w])
|
|
2165
2817
|
);
|
|
2166
|
-
const
|
|
2167
|
-
const
|
|
2818
|
+
const pages = pageList(layout);
|
|
2819
|
+
const paged = pages.length >= 2;
|
|
2820
|
+
const [activeState, setActiveState] = useState(
|
|
2821
|
+
defaultActivePage
|
|
2822
|
+
);
|
|
2823
|
+
const requested = activePageProp ?? activeState;
|
|
2824
|
+
const activePage = pages.find((page) => page.key === requested) ?? pages[0];
|
|
2825
|
+
const activeKey = activePage.key;
|
|
2826
|
+
const pageDefs = assignPages(definitions, layout).get(activeKey) ?? [];
|
|
2827
|
+
const view = pageLayout(layout, activeKey) ?? layout;
|
|
2828
|
+
const roomOptions = maxRows === void 0 ? {} : { maxRows };
|
|
2829
|
+
const visible = visibleWidgets(pageDefs, view);
|
|
2830
|
+
const hidden = hiddenWidgets(pageDefs, view);
|
|
2168
2831
|
const editable = onLayoutChange !== void 0;
|
|
2169
|
-
const
|
|
2170
|
-
const
|
|
2832
|
+
const toggleMode = editMode === "toggle";
|
|
2833
|
+
const [editingState, setEditingState] = useState(defaultEditing);
|
|
2834
|
+
const editing = editingProp ?? editingState;
|
|
2835
|
+
const controlsShown = editable && (!toggleMode || editing);
|
|
2836
|
+
const [snapshot, setSnapshot] = useState(
|
|
2837
|
+
void 0
|
|
2838
|
+
);
|
|
2839
|
+
if (toggleMode && editable && editing) {
|
|
2840
|
+
if (snapshot === void 0) setSnapshot(savedLayout);
|
|
2841
|
+
} else if (snapshot !== void 0) {
|
|
2842
|
+
setSnapshot(void 0);
|
|
2843
|
+
}
|
|
2844
|
+
const [confirming, setConfirming] = useState(
|
|
2845
|
+
void 0
|
|
2846
|
+
);
|
|
2847
|
+
const pending = editing ? confirming : void 0;
|
|
2848
|
+
const [announcement, setAnnouncement] = useState("");
|
|
2849
|
+
const [pageAnnouncement, setPageAnnouncement] = useState("");
|
|
2850
|
+
const [pageError, setPageError] = useState(void 0);
|
|
2851
|
+
const [pageEditor, setPageEditor] = useState(void 0);
|
|
2852
|
+
const editorMode = pageEditor?.key === activeKey ? pageEditor.mode : void 0;
|
|
2853
|
+
const instanceId = useId();
|
|
2854
|
+
const panelId = `${instanceId}-panel`;
|
|
2855
|
+
const toggleRef = useRef(null);
|
|
2856
|
+
const resetRef = useRef(null);
|
|
2857
|
+
const minimized = editable ? visible.filter((definition) => isMinimized(view, definition.key)) : [];
|
|
2858
|
+
const shown = editable ? visible.filter((definition) => !isMinimized(view, definition.key)) : visible;
|
|
2171
2859
|
const [detailKey, setDetailKey] = useState(void 0);
|
|
2172
2860
|
const gridRef = useRef(null);
|
|
2173
2861
|
const twelve = usesWidthColumns(shown);
|
|
@@ -2179,142 +2867,507 @@ function DashboardInner({
|
|
|
2179
2867
|
function change(next) {
|
|
2180
2868
|
if (next !== layout) onLayoutChange?.(next);
|
|
2181
2869
|
}
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
)
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2870
|
+
function changePage(next) {
|
|
2871
|
+
setPageError(void 0);
|
|
2872
|
+
change(withPageLayout(layout, activeKey, next));
|
|
2873
|
+
}
|
|
2874
|
+
function selectPage(pageKey) {
|
|
2875
|
+
const index = pages.findIndex((page) => page.key === pageKey);
|
|
2876
|
+
if (index === -1) return;
|
|
2877
|
+
if (activePageProp === void 0) setActiveState(pageKey);
|
|
2878
|
+
onActivePageChange?.(pageKey);
|
|
2879
|
+
setPageError(void 0);
|
|
2880
|
+
setPageEditor(void 0);
|
|
2881
|
+
setPageAnnouncement(
|
|
2882
|
+
labels.pageTabName(
|
|
2883
|
+
index + 1,
|
|
2884
|
+
pages.length,
|
|
2885
|
+
pages[index].title
|
|
2886
|
+
)
|
|
2887
|
+
);
|
|
2888
|
+
}
|
|
2889
|
+
function addPageAction() {
|
|
2890
|
+
const added = addPage(layout);
|
|
2891
|
+
if (!added.ok) {
|
|
2892
|
+
setPageError(added.error);
|
|
2893
|
+
return;
|
|
2894
|
+
}
|
|
2895
|
+
change(added.value);
|
|
2896
|
+
const created = added.value.pages?.at(-1);
|
|
2897
|
+
if (created !== void 0) {
|
|
2898
|
+
if (activePageProp === void 0) setActiveState(created.key);
|
|
2899
|
+
onActivePageChange?.(created.key);
|
|
2900
|
+
setPageError(void 0);
|
|
2901
|
+
setPageEditor({ mode: "rename", key: created.key });
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2904
|
+
function renamePageAction(title) {
|
|
2905
|
+
const renamed = renamePage(layout, activeKey, title);
|
|
2906
|
+
if (!renamed.ok) return renamed.error;
|
|
2907
|
+
change(renamed.value);
|
|
2908
|
+
setPageEditor(void 0);
|
|
2909
|
+
return void 0;
|
|
2910
|
+
}
|
|
2911
|
+
function deletePageAction() {
|
|
2912
|
+
const index = pages.findIndex((page) => page.key === activeKey);
|
|
2913
|
+
const removed = removePage(definitions, layout, activeKey, roomOptions);
|
|
2914
|
+
setPageEditor(void 0);
|
|
2915
|
+
if (!removed.ok) {
|
|
2916
|
+
setPageError(removed.error);
|
|
2917
|
+
return;
|
|
2918
|
+
}
|
|
2919
|
+
const neighbor = pages[index > 0 ? index - 1 : 1];
|
|
2920
|
+
change(removed.value);
|
|
2921
|
+
if (neighbor !== void 0) selectPage(neighbor.key);
|
|
2922
|
+
}
|
|
2923
|
+
function moveWidgetAction(widgetKey, targetKey) {
|
|
2924
|
+
let target = targetKey;
|
|
2925
|
+
let base = layout;
|
|
2926
|
+
if (targetKey === NEW_PAGE_VALUE) {
|
|
2927
|
+
const added = addPage(layout);
|
|
2928
|
+
if (!added.ok) {
|
|
2929
|
+
setPageError(added.error);
|
|
2930
|
+
return;
|
|
2221
2931
|
}
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2932
|
+
base = added.value;
|
|
2933
|
+
target = (added.value.pages?.at(-1)).key;
|
|
2934
|
+
}
|
|
2935
|
+
const moved = moveWidgetToPage(
|
|
2936
|
+
definitions,
|
|
2937
|
+
base,
|
|
2938
|
+
widgetKey,
|
|
2939
|
+
target,
|
|
2940
|
+
roomOptions
|
|
2941
|
+
);
|
|
2942
|
+
if (!moved.ok) {
|
|
2943
|
+
setPageError(moved.error);
|
|
2944
|
+
return;
|
|
2945
|
+
}
|
|
2946
|
+
setPageError(void 0);
|
|
2947
|
+
change(moved.value);
|
|
2948
|
+
const destination = moved.value.pages?.find(
|
|
2949
|
+
(page) => page.key === target
|
|
2950
|
+
);
|
|
2951
|
+
setPageAnnouncement(
|
|
2952
|
+
labels.movedToPage(
|
|
2953
|
+
byKey.get(widgetKey)?.definition.title ?? widgetKey,
|
|
2954
|
+
destination?.title ?? target
|
|
2955
|
+
)
|
|
2956
|
+
);
|
|
2957
|
+
}
|
|
2958
|
+
function showAction(widgetKey) {
|
|
2959
|
+
const next = withPageLayout(
|
|
2960
|
+
layout,
|
|
2961
|
+
activeKey,
|
|
2962
|
+
showWidget(view, widgetKey)
|
|
2963
|
+
);
|
|
2964
|
+
if (hasPages(next)) {
|
|
2965
|
+
const room = pageRoom(definitions, next, activeKey, roomOptions);
|
|
2966
|
+
if (room !== void 0 && room.rowsUsed > room.maxRows) {
|
|
2967
|
+
setPageError(labels.pageFull(activePage.title, room.maxRows));
|
|
2968
|
+
return;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
setPageError(void 0);
|
|
2972
|
+
change(next);
|
|
2973
|
+
}
|
|
2974
|
+
function setEditing(next) {
|
|
2975
|
+
if (editingProp === void 0) setEditingState(next);
|
|
2976
|
+
onEditingChange?.(next);
|
|
2977
|
+
setAnnouncement(next ? labels.editingOn : labels.editingOff);
|
|
2978
|
+
setConfirming(void 0);
|
|
2979
|
+
}
|
|
2980
|
+
function answerConfirmation(yes) {
|
|
2981
|
+
const which = pending;
|
|
2982
|
+
setConfirming(void 0);
|
|
2983
|
+
if (yes && which === "reset") {
|
|
2984
|
+
change(enforceLocks(definitions, defaultLayout ?? EMPTY_LAYOUT));
|
|
2985
|
+
} else if (yes && which === "revert" && snapshot !== void 0) {
|
|
2986
|
+
change(snapshot);
|
|
2987
|
+
}
|
|
2988
|
+
(which === "revert" ? toggleRef : resetRef).current?.focus();
|
|
2989
|
+
}
|
|
2990
|
+
return /* @__PURE__ */ jsxs(
|
|
2991
|
+
"div",
|
|
2992
|
+
{
|
|
2993
|
+
className: slot(
|
|
2994
|
+
"dashboard",
|
|
2995
|
+
"dwt-dashboard",
|
|
2996
|
+
toggleMode && controlsShown && "dwt-dashboard--editing",
|
|
2997
|
+
className
|
|
2998
|
+
),
|
|
2999
|
+
children: [
|
|
3000
|
+
editable && toggleMode && toolbar && /* @__PURE__ */ jsxs(
|
|
3001
|
+
"div",
|
|
3002
|
+
{
|
|
3003
|
+
role: "group",
|
|
3004
|
+
"aria-label": labels.dashboardControls,
|
|
3005
|
+
className: slot("toolbar", "dwt-toolbar"),
|
|
3006
|
+
children: [
|
|
2240
3007
|
/* @__PURE__ */ jsx(
|
|
2241
3008
|
"button",
|
|
2242
3009
|
{
|
|
3010
|
+
ref: toggleRef,
|
|
2243
3011
|
type: "button",
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
),
|
|
2249
|
-
"aria-label": labels.moveEarlier(title),
|
|
2250
|
-
title: labels.moveEarlier(title),
|
|
2251
|
-
disabled: index === 0 || !canMoveEarlier,
|
|
2252
|
-
onClick: () => change(moveWidgetBy(definitions, layout, key, -1)),
|
|
2253
|
-
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2191" })
|
|
3012
|
+
"aria-pressed": editing,
|
|
3013
|
+
className: slot("button", "dwt-button", "dwt-toolbar-toggle"),
|
|
3014
|
+
onClick: () => setEditing(!editing),
|
|
3015
|
+
children: editing ? labels.done : labels.customize
|
|
2254
3016
|
}
|
|
2255
3017
|
),
|
|
3018
|
+
editing && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3019
|
+
/* @__PURE__ */ jsx(
|
|
3020
|
+
"button",
|
|
3021
|
+
{
|
|
3022
|
+
ref: resetRef,
|
|
3023
|
+
type: "button",
|
|
3024
|
+
className: slot("button", "dwt-button"),
|
|
3025
|
+
onClick: () => setConfirming("reset"),
|
|
3026
|
+
children: labels.reset
|
|
3027
|
+
}
|
|
3028
|
+
),
|
|
3029
|
+
/* @__PURE__ */ jsx(
|
|
3030
|
+
"button",
|
|
3031
|
+
{
|
|
3032
|
+
type: "button",
|
|
3033
|
+
className: slot("button", "dwt-button"),
|
|
3034
|
+
disabled: snapshot === void 0 || savedLayout === snapshot,
|
|
3035
|
+
onClick: () => setConfirming("revert"),
|
|
3036
|
+
children: labels.revertChanges
|
|
3037
|
+
}
|
|
3038
|
+
)
|
|
3039
|
+
] }),
|
|
3040
|
+
pending !== void 0 && /* @__PURE__ */ jsx(
|
|
3041
|
+
InlineConfirm,
|
|
3042
|
+
{
|
|
3043
|
+
message: pending === "reset" ? labels.confirmReset : labels.confirmRevert,
|
|
3044
|
+
onAnswer: answerConfirmation
|
|
3045
|
+
}
|
|
3046
|
+
),
|
|
3047
|
+
/* @__PURE__ */ jsx("span", { className: "dwt-visually-hidden", "aria-live": "polite", children: announcement })
|
|
3048
|
+
]
|
|
3049
|
+
}
|
|
3050
|
+
),
|
|
3051
|
+
paged && /* @__PURE__ */ jsx(
|
|
3052
|
+
PageTabs,
|
|
3053
|
+
{
|
|
3054
|
+
pages,
|
|
3055
|
+
activeKey,
|
|
3056
|
+
idPrefix: instanceId,
|
|
3057
|
+
panelId,
|
|
3058
|
+
announcement: pageAnnouncement,
|
|
3059
|
+
onSelect: selectPage
|
|
3060
|
+
}
|
|
3061
|
+
),
|
|
3062
|
+
controlsShown && /* @__PURE__ */ jsxs(
|
|
3063
|
+
"div",
|
|
3064
|
+
{
|
|
3065
|
+
role: "group",
|
|
3066
|
+
"aria-label": labels.managePages,
|
|
3067
|
+
className: "dwt-page-manage",
|
|
3068
|
+
children: [
|
|
2256
3069
|
/* @__PURE__ */ jsx(
|
|
2257
3070
|
"button",
|
|
2258
3071
|
{
|
|
2259
3072
|
type: "button",
|
|
2260
|
-
className: slot(
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
3073
|
+
className: slot("button", "dwt-button"),
|
|
3074
|
+
disabled: maxPages !== void 0 && pages.length >= maxPages,
|
|
3075
|
+
onClick: addPageAction,
|
|
3076
|
+
children: labels.addPage
|
|
3077
|
+
}
|
|
3078
|
+
),
|
|
3079
|
+
paged && editorMode === "rename" && /* @__PURE__ */ jsx(
|
|
3080
|
+
PageRenameForm,
|
|
3081
|
+
{
|
|
3082
|
+
initial: activePage.title,
|
|
3083
|
+
onSubmit: renamePageAction,
|
|
3084
|
+
onCancel: () => setPageEditor(void 0)
|
|
3085
|
+
},
|
|
3086
|
+
activeKey
|
|
3087
|
+
),
|
|
3088
|
+
paged && editorMode !== "rename" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3089
|
+
/* @__PURE__ */ jsx(
|
|
3090
|
+
"button",
|
|
3091
|
+
{
|
|
3092
|
+
type: "button",
|
|
3093
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
3094
|
+
"aria-label": labels.renamePage(activePage.title),
|
|
3095
|
+
title: labels.renamePage(activePage.title),
|
|
3096
|
+
onClick: () => setPageEditor({ mode: "rename", key: activeKey }),
|
|
3097
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u270E" })
|
|
3098
|
+
}
|
|
3099
|
+
),
|
|
3100
|
+
/* @__PURE__ */ jsx(
|
|
3101
|
+
"button",
|
|
3102
|
+
{
|
|
3103
|
+
type: "button",
|
|
3104
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
3105
|
+
"aria-label": labels.movePageLeft(activePage.title),
|
|
3106
|
+
title: labels.movePageLeft(activePage.title),
|
|
3107
|
+
disabled: pages[0]?.key === activeKey,
|
|
3108
|
+
onClick: () => change(movePage(layout, activeKey, -1)),
|
|
3109
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2190" })
|
|
3110
|
+
}
|
|
3111
|
+
),
|
|
3112
|
+
/* @__PURE__ */ jsx(
|
|
3113
|
+
"button",
|
|
3114
|
+
{
|
|
3115
|
+
type: "button",
|
|
3116
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
3117
|
+
"aria-label": labels.movePageRight(activePage.title),
|
|
3118
|
+
title: labels.movePageRight(activePage.title),
|
|
3119
|
+
disabled: pages.at(-1)?.key === activeKey,
|
|
3120
|
+
onClick: () => change(movePage(layout, activeKey, 1)),
|
|
3121
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2192" })
|
|
3122
|
+
}
|
|
3123
|
+
),
|
|
3124
|
+
/* @__PURE__ */ jsx(
|
|
3125
|
+
"button",
|
|
3126
|
+
{
|
|
3127
|
+
type: "button",
|
|
3128
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
3129
|
+
"aria-label": labels.deletePage(activePage.title),
|
|
3130
|
+
title: labels.deletePage(activePage.title),
|
|
3131
|
+
onClick: () => setPageEditor({ mode: "delete", key: activeKey }),
|
|
3132
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xD7" })
|
|
3133
|
+
}
|
|
3134
|
+
)
|
|
3135
|
+
] }),
|
|
3136
|
+
paged && editorMode === "delete" && /* @__PURE__ */ jsx(
|
|
3137
|
+
InlineConfirm,
|
|
3138
|
+
{
|
|
3139
|
+
message: labels.confirmDeletePage(activePage.title),
|
|
3140
|
+
onAnswer: (yes) => yes ? deletePageAction() : setPageEditor(void 0)
|
|
3141
|
+
}
|
|
3142
|
+
),
|
|
3143
|
+
pageError !== void 0 && /* @__PURE__ */ jsx("span", { role: "alert", className: "dwt-page-error", children: pageError })
|
|
3144
|
+
]
|
|
3145
|
+
}
|
|
3146
|
+
),
|
|
3147
|
+
/* @__PURE__ */ jsxs(
|
|
3148
|
+
PagePanel,
|
|
3149
|
+
{
|
|
3150
|
+
paged,
|
|
3151
|
+
id: panelId,
|
|
3152
|
+
labelledBy: `${instanceId}-tab-${pages.findIndex((p) => p.key === activeKey)}`,
|
|
3153
|
+
children: [
|
|
3154
|
+
controlsShown && hidden.length > 0 && /* @__PURE__ */ jsxs("div", { className: slot("hiddenBar", "dwt-hidden-bar"), children: [
|
|
3155
|
+
/* @__PURE__ */ jsx("span", { className: "dwt-hidden-label", children: labels.hiddenWidgets }),
|
|
3156
|
+
hidden.map((definition) => /* @__PURE__ */ jsxs(
|
|
3157
|
+
"button",
|
|
3158
|
+
{
|
|
3159
|
+
type: "button",
|
|
3160
|
+
className: slot("button", "dwt-button", "dwt-show-button"),
|
|
3161
|
+
"aria-label": labels.show(definition.title),
|
|
3162
|
+
onClick: () => showAction(definition.key),
|
|
3163
|
+
children: [
|
|
3164
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "+ " }),
|
|
3165
|
+
definition.title
|
|
3166
|
+
]
|
|
3167
|
+
},
|
|
3168
|
+
definition.key
|
|
3169
|
+
))
|
|
3170
|
+
] }),
|
|
3171
|
+
minimized.length > 0 && /* @__PURE__ */ jsxs(
|
|
3172
|
+
"div",
|
|
3173
|
+
{
|
|
3174
|
+
className: slot("hiddenBar", "dwt-hidden-bar", "dwt-minimized-bar"),
|
|
3175
|
+
children: [
|
|
3176
|
+
/* @__PURE__ */ jsx("span", { className: "dwt-hidden-label", children: labels.minimizedWidgets }),
|
|
3177
|
+
minimized.map((definition) => /* @__PURE__ */ jsxs(
|
|
3178
|
+
"button",
|
|
3179
|
+
{
|
|
3180
|
+
type: "button",
|
|
3181
|
+
className: slot("button", "dwt-button", "dwt-show-button"),
|
|
3182
|
+
"aria-label": labels.expand(definition.title),
|
|
3183
|
+
onClick: () => changePage(toggleMinimized(view, definition.key)),
|
|
3184
|
+
children: [
|
|
3185
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u25B8 " }),
|
|
3186
|
+
definition.title
|
|
3187
|
+
]
|
|
3188
|
+
},
|
|
3189
|
+
definition.key
|
|
3190
|
+
))
|
|
3191
|
+
]
|
|
3192
|
+
}
|
|
3193
|
+
),
|
|
3194
|
+
visible.length === 0 ? /* @__PURE__ */ jsx("p", { className: slot("empty", "dwt-empty", "dwt-dashboard-empty"), children: paged && pageDefs.length === 0 ? labels.emptyPage : definitions.length === 0 ? labels.noWidgets : labels.allHidden }) : shown.length === 0 ? null : /* @__PURE__ */ jsx(
|
|
3195
|
+
"div",
|
|
3196
|
+
{
|
|
3197
|
+
ref: gridRef,
|
|
3198
|
+
className: slot("grid", "dwt-grid", twelve && "dwt-grid--twelve"),
|
|
3199
|
+
children: shown.map((definition, index) => {
|
|
3200
|
+
const widget = byKey.get(
|
|
3201
|
+
definition.key
|
|
3202
|
+
);
|
|
3203
|
+
if (widget === void 0) return null;
|
|
3204
|
+
const key = definition.key;
|
|
3205
|
+
const title = definition.title;
|
|
3206
|
+
const lock = resolveWidgetLock(definition);
|
|
3207
|
+
const ownLock = resolveWidgetLock(
|
|
3208
|
+
widget.definition
|
|
3209
|
+
);
|
|
3210
|
+
const isLocked = ownLock.move || ownLock.hide || ownLock.minimize;
|
|
3211
|
+
const lockLabel = overrideLocks ? labels.lockedForViewers(title) : labels.locked(title);
|
|
3212
|
+
const canMoveEarlier = !lock.move && moveWidgetBy(pageDefs, view, key, -1) !== view;
|
|
3213
|
+
const canMoveLater = !lock.move && moveWidgetBy(pageDefs, view, key, 1) !== view;
|
|
3214
|
+
const actions = controlsShown ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3215
|
+
isLocked && /* @__PURE__ */ jsx(
|
|
3216
|
+
"span",
|
|
3217
|
+
{
|
|
3218
|
+
role: "img",
|
|
3219
|
+
className: "dwt-lock",
|
|
3220
|
+
"aria-label": lockLabel,
|
|
3221
|
+
title: lockLabel,
|
|
3222
|
+
children: /* @__PURE__ */ jsxs(
|
|
3223
|
+
"svg",
|
|
3224
|
+
{
|
|
3225
|
+
viewBox: "0 0 16 16",
|
|
3226
|
+
width: "14",
|
|
3227
|
+
height: "14",
|
|
3228
|
+
"aria-hidden": "true",
|
|
3229
|
+
focusable: "false",
|
|
3230
|
+
children: [
|
|
3231
|
+
/* @__PURE__ */ jsx(
|
|
3232
|
+
"rect",
|
|
3233
|
+
{
|
|
3234
|
+
x: "3",
|
|
3235
|
+
y: "7",
|
|
3236
|
+
width: "10",
|
|
3237
|
+
height: "7",
|
|
3238
|
+
rx: "1.5",
|
|
3239
|
+
fill: "currentColor"
|
|
3240
|
+
}
|
|
3241
|
+
),
|
|
3242
|
+
/* @__PURE__ */ jsx(
|
|
3243
|
+
"path",
|
|
3244
|
+
{
|
|
3245
|
+
d: "M5.5 7V5a2.5 2.5 0 0 1 5 0v2",
|
|
3246
|
+
fill: "none",
|
|
3247
|
+
stroke: "currentColor",
|
|
3248
|
+
strokeWidth: "1.4"
|
|
3249
|
+
}
|
|
3250
|
+
)
|
|
3251
|
+
]
|
|
3252
|
+
}
|
|
3253
|
+
)
|
|
3254
|
+
}
|
|
3255
|
+
),
|
|
3256
|
+
!lock.move && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3257
|
+
/* @__PURE__ */ jsx(
|
|
3258
|
+
"button",
|
|
3259
|
+
{
|
|
3260
|
+
type: "button",
|
|
3261
|
+
className: slot(
|
|
3262
|
+
"button",
|
|
3263
|
+
"dwt-button",
|
|
3264
|
+
"dwt-icon-button"
|
|
3265
|
+
),
|
|
3266
|
+
"aria-label": labels.moveEarlier(title),
|
|
3267
|
+
title: labels.moveEarlier(title),
|
|
3268
|
+
disabled: index === 0 || !canMoveEarlier,
|
|
3269
|
+
onClick: () => changePage(moveWidgetBy(pageDefs, view, key, -1)),
|
|
3270
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2191" })
|
|
3271
|
+
}
|
|
3272
|
+
),
|
|
3273
|
+
/* @__PURE__ */ jsx(
|
|
3274
|
+
"button",
|
|
3275
|
+
{
|
|
3276
|
+
type: "button",
|
|
3277
|
+
className: slot(
|
|
3278
|
+
"button",
|
|
3279
|
+
"dwt-button",
|
|
3280
|
+
"dwt-icon-button"
|
|
3281
|
+
),
|
|
3282
|
+
"aria-label": labels.moveLater(title),
|
|
3283
|
+
title: labels.moveLater(title),
|
|
3284
|
+
disabled: index === shown.length - 1 || !canMoveLater,
|
|
3285
|
+
onClick: () => changePage(moveWidgetBy(pageDefs, view, key, 1)),
|
|
3286
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2193" })
|
|
3287
|
+
}
|
|
3288
|
+
),
|
|
3289
|
+
paged && /* @__PURE__ */ jsxs(
|
|
3290
|
+
"select",
|
|
3291
|
+
{
|
|
3292
|
+
className: "dwt-move-select",
|
|
3293
|
+
"aria-label": labels.moveToPage(title),
|
|
3294
|
+
value: "",
|
|
3295
|
+
onChange: (event) => {
|
|
3296
|
+
if (event.target.value !== "") {
|
|
3297
|
+
moveWidgetAction(key, event.target.value);
|
|
3298
|
+
}
|
|
3299
|
+
},
|
|
3300
|
+
children: [
|
|
3301
|
+
/* @__PURE__ */ jsx("option", { value: "", children: labels.moveToPagePlaceholder }),
|
|
3302
|
+
pages.filter((page) => page.key !== activeKey).map((page) => /* @__PURE__ */ jsx("option", { value: page.key, children: labels.moveToPageOption(
|
|
3303
|
+
page.title,
|
|
3304
|
+
pageRoom(
|
|
3305
|
+
definitions,
|
|
3306
|
+
layout,
|
|
3307
|
+
page.key,
|
|
3308
|
+
roomOptions
|
|
3309
|
+
)?.rowsFree ?? 0
|
|
3310
|
+
) }, page.key)),
|
|
3311
|
+
(maxPages === void 0 || pages.length < maxPages) && /* @__PURE__ */ jsx("option", { value: NEW_PAGE_VALUE, children: labels.newPageOption })
|
|
3312
|
+
]
|
|
3313
|
+
}
|
|
3314
|
+
)
|
|
3315
|
+
] }),
|
|
3316
|
+
!lock.hide && /* @__PURE__ */ jsx(
|
|
3317
|
+
"button",
|
|
3318
|
+
{
|
|
3319
|
+
type: "button",
|
|
3320
|
+
className: slot(
|
|
3321
|
+
"button",
|
|
3322
|
+
"dwt-button",
|
|
3323
|
+
"dwt-icon-button"
|
|
3324
|
+
),
|
|
3325
|
+
"aria-label": labels.hide(title),
|
|
3326
|
+
title: labels.hide(title),
|
|
3327
|
+
onClick: () => changePage(hideWidget(view, key)),
|
|
3328
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xD7" })
|
|
3329
|
+
}
|
|
3330
|
+
)
|
|
3331
|
+
] }) : void 0;
|
|
3332
|
+
const viewable = resolveDetailOptions(definition) !== void 0 && (onOpenDetail !== void 0 || loadDetail !== void 0 || widget.status === "ok" && deriveDetailData(widget.data) !== void 0);
|
|
3333
|
+
return /* @__PURE__ */ jsx(
|
|
3334
|
+
ResolvedWidgetCard,
|
|
3335
|
+
{
|
|
3336
|
+
widget,
|
|
3337
|
+
...viewable ? {
|
|
3338
|
+
onView: () => onOpenDetail === void 0 ? setDetailKey(key) : onOpenDetail(key)
|
|
3339
|
+
} : {},
|
|
3340
|
+
...spanProps(spans, key),
|
|
3341
|
+
...widthProps(twelve, definition),
|
|
3342
|
+
minimized: isMinimized(view, key),
|
|
3343
|
+
editing: toggleMode && controlsShown,
|
|
3344
|
+
...actions === void 0 ? {} : { actions },
|
|
3345
|
+
...editable && !lock.minimize ? {
|
|
3346
|
+
onToggleMinimized: () => changePage(toggleMinimized(view, key))
|
|
3347
|
+
} : {},
|
|
3348
|
+
...headingLevel === void 0 ? {} : { headingLevel },
|
|
3349
|
+
...onRetry === void 0 || widget.status !== "error" ? {} : { onRetry: () => onRetry(key) }
|
|
3350
|
+
},
|
|
3351
|
+
key
|
|
3352
|
+
);
|
|
3353
|
+
})
|
|
2270
3354
|
}
|
|
2271
3355
|
)
|
|
2272
|
-
]
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
ResolvedWidgetCard,
|
|
2288
|
-
{
|
|
2289
|
-
widget,
|
|
2290
|
-
...viewable ? {
|
|
2291
|
-
onView: () => onOpenDetail === void 0 ? setDetailKey(key) : onOpenDetail(key)
|
|
2292
|
-
} : {},
|
|
2293
|
-
...spanProps(spans, key),
|
|
2294
|
-
...widthProps(twelve, definition),
|
|
2295
|
-
minimized: isMinimized(layout, key),
|
|
2296
|
-
...actions === void 0 ? {} : { actions },
|
|
2297
|
-
...editable && !lock.minimize ? {
|
|
2298
|
-
onToggleMinimized: () => change(toggleMinimized(layout, key))
|
|
2299
|
-
} : {},
|
|
2300
|
-
...headingLevel === void 0 ? {} : { headingLevel },
|
|
2301
|
-
...onRetry === void 0 || widget.status !== "error" ? {} : { onRetry: () => onRetry(key) }
|
|
2302
|
-
},
|
|
2303
|
-
key
|
|
2304
|
-
);
|
|
2305
|
-
})
|
|
2306
|
-
}
|
|
2307
|
-
),
|
|
2308
|
-
detailKey !== void 0 && byKey.get(detailKey) !== void 0 && /* @__PURE__ */ jsx(
|
|
2309
|
-
DetailHost,
|
|
2310
|
-
{
|
|
2311
|
-
widget: byKey.get(detailKey),
|
|
2312
|
-
loadDetail,
|
|
2313
|
-
onClose: () => setDetailKey(void 0)
|
|
2314
|
-
},
|
|
2315
|
-
detailKey
|
|
2316
|
-
)
|
|
2317
|
-
] });
|
|
3356
|
+
]
|
|
3357
|
+
}
|
|
3358
|
+
),
|
|
3359
|
+
detailKey !== void 0 && byKey.get(detailKey) !== void 0 && /* @__PURE__ */ jsx(
|
|
3360
|
+
DetailHost,
|
|
3361
|
+
{
|
|
3362
|
+
widget: byKey.get(detailKey),
|
|
3363
|
+
loadDetail,
|
|
3364
|
+
onClose: () => setDetailKey(void 0)
|
|
3365
|
+
},
|
|
3366
|
+
detailKey
|
|
3367
|
+
)
|
|
3368
|
+
]
|
|
3369
|
+
}
|
|
3370
|
+
);
|
|
2318
3371
|
}
|
|
2319
3372
|
function Dashboard({
|
|
2320
3373
|
locale,
|
|
@@ -2959,8 +4012,21 @@ function useWidgets(definitions, providers, context, options = {}) {
|
|
|
2959
4012
|
},
|
|
2960
4013
|
{ rootMargin }
|
|
2961
4014
|
);
|
|
2962
|
-
|
|
2963
|
-
|
|
4015
|
+
const observed = /* @__PURE__ */ new WeakSet();
|
|
4016
|
+
const observeNewCards = () => {
|
|
4017
|
+
grid.querySelectorAll("[data-widget-key]").forEach((card) => {
|
|
4018
|
+
if (observed.has(card)) return;
|
|
4019
|
+
observed.add(card);
|
|
4020
|
+
observer.observe(card);
|
|
4021
|
+
});
|
|
4022
|
+
};
|
|
4023
|
+
observeNewCards();
|
|
4024
|
+
const mutations = typeof MutationObserver === "undefined" ? void 0 : new MutationObserver(observeNewCards);
|
|
4025
|
+
mutations?.observe(grid, { childList: true, subtree: true });
|
|
4026
|
+
return () => {
|
|
4027
|
+
mutations?.disconnect();
|
|
4028
|
+
observer.disconnect();
|
|
4029
|
+
};
|
|
2964
4030
|
}, [loader, loadWhen, rootMargin, cardKeys]);
|
|
2965
4031
|
useEffect(() => {
|
|
2966
4032
|
if (loader === null || !(refreshMs > 0)) return void 0;
|