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