@richardmcquiston01/dashboard-widgets-toolkit 0.12.0 → 0.14.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 +951 -370
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +57 -3
- package/dist/core.d.ts +57 -3
- package/dist/core.js +933 -371
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +951 -370
- 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 +933 -371
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +836 -60
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +53 -4
- package/dist/react.d.ts +53 -4
- package/dist/react.js +836 -61
- package/dist/react.js.map +1 -1
- package/dist/{storage-VaaysVnZ.d.cts → storage-_Eb8Y98-.d.cts} +144 -3
- package/dist/{storage-VaaysVnZ.d.ts → storage-_Eb8Y98-.d.ts} +144 -3
- package/dist/styles.css +146 -0
- package/package.json +1 -1
package/dist/react.cjs
CHANGED
|
@@ -829,6 +829,30 @@ var DEFAULT_LABELS = {
|
|
|
829
829
|
menuMoveEarlier: "Move earlier",
|
|
830
830
|
menuMoveLater: "Move later",
|
|
831
831
|
menuHide: "Hide",
|
|
832
|
+
menuOptions: "Options\u2026",
|
|
833
|
+
optionsFor: (title) => `Options for ${title}`,
|
|
834
|
+
optionsTitleField: "Title",
|
|
835
|
+
titleInUse: "Another widget already uses this title.",
|
|
836
|
+
optionsWidthField: "Width",
|
|
837
|
+
widthDefault: "Default",
|
|
838
|
+
widthOption: (width, share) => `${width} of 12 (${share})`,
|
|
839
|
+
optionsFlexible: "Grow to fill empty space in the row",
|
|
840
|
+
optionsDeclared: "Data",
|
|
841
|
+
apply: "Apply",
|
|
842
|
+
cancel: "Cancel",
|
|
843
|
+
resetToDefaults: "Reset to defaults",
|
|
844
|
+
revertToBeforeEditing: "Revert to before editing",
|
|
845
|
+
confirmApply: "Apply these changes?",
|
|
846
|
+
confirmDiscard: "Discard your changes?",
|
|
847
|
+
confirmResetOptions: "Reset these options to their defaults?",
|
|
848
|
+
confirmRevertOptions: "Revert these options to how they were before you started editing?",
|
|
849
|
+
optionsSaved: (title) => `Options saved for ${title}`,
|
|
850
|
+
sortDefault: "Default order",
|
|
851
|
+
sortAscending: "Ascending",
|
|
852
|
+
sortDescending: "Descending",
|
|
853
|
+
moveColumnUp: (column) => `Move ${column} up`,
|
|
854
|
+
moveColumnDown: (column) => `Move ${column} down`,
|
|
855
|
+
customRange: (value) => `Custom: ${value}`,
|
|
832
856
|
moveToPage: (title) => `Move ${title} to another page`,
|
|
833
857
|
moveToPagePlaceholder: "Move to page\u2026",
|
|
834
858
|
moveToPageOption: (title, rowsFree) => `${title} (${rowsFree} ${rowsFree === 1 ? "row" : "rows"} free)`,
|
|
@@ -1912,12 +1936,14 @@ function ResolvedWidgetCard({
|
|
|
1912
1936
|
var NOT_LOCKED = Object.freeze({
|
|
1913
1937
|
move: false,
|
|
1914
1938
|
hide: false,
|
|
1915
|
-
minimize: false
|
|
1939
|
+
minimize: false,
|
|
1940
|
+
options: false
|
|
1916
1941
|
});
|
|
1917
1942
|
var FULLY_LOCKED = Object.freeze({
|
|
1918
1943
|
move: true,
|
|
1919
1944
|
hide: true,
|
|
1920
|
-
minimize: true
|
|
1945
|
+
minimize: true,
|
|
1946
|
+
options: true
|
|
1921
1947
|
});
|
|
1922
1948
|
function resolveWidgetLock(definition) {
|
|
1923
1949
|
const setting = definition.locked;
|
|
@@ -1926,7 +1952,8 @@ function resolveWidgetLock(definition) {
|
|
|
1926
1952
|
return {
|
|
1927
1953
|
move: setting.move === true,
|
|
1928
1954
|
hide: setting.hide === true,
|
|
1929
|
-
minimize: setting.minimize === true
|
|
1955
|
+
minimize: setting.minimize === true,
|
|
1956
|
+
options: setting.options === true
|
|
1930
1957
|
};
|
|
1931
1958
|
}
|
|
1932
1959
|
function sortDefinitions(definitions) {
|
|
@@ -1947,6 +1974,151 @@ function isWidgetVisibleTo(definition, roles) {
|
|
|
1947
1974
|
return definition.roles.some((role) => roles.includes(role));
|
|
1948
1975
|
}
|
|
1949
1976
|
|
|
1977
|
+
// src/core/settings.ts
|
|
1978
|
+
var MAX_WIDGET_TITLE_LENGTH = 80;
|
|
1979
|
+
var MAX_COLUMN_LIST = 100;
|
|
1980
|
+
var MAX_VALUE_LENGTH = 500;
|
|
1981
|
+
function isRecord(value) {
|
|
1982
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1983
|
+
}
|
|
1984
|
+
function parseOptionValue(value) {
|
|
1985
|
+
if (typeof value === "string") {
|
|
1986
|
+
return value.length <= MAX_VALUE_LENGTH ? value : void 0;
|
|
1987
|
+
}
|
|
1988
|
+
if (typeof value === "number")
|
|
1989
|
+
return Number.isFinite(value) ? value : void 0;
|
|
1990
|
+
if (typeof value === "boolean") return value;
|
|
1991
|
+
if (Array.isArray(value) && value.length <= MAX_COLUMN_LIST) {
|
|
1992
|
+
return value.every(
|
|
1993
|
+
(entry) => typeof entry === "string" && entry.length <= MAX_VALUE_LENGTH
|
|
1994
|
+
) ? value : void 0;
|
|
1995
|
+
}
|
|
1996
|
+
return void 0;
|
|
1997
|
+
}
|
|
1998
|
+
function parseOne(raw) {
|
|
1999
|
+
if (!isRecord(raw)) return void 0;
|
|
2000
|
+
const title = raw["title"];
|
|
2001
|
+
const width = raw["width"];
|
|
2002
|
+
const flexible = raw["flexible"];
|
|
2003
|
+
const options = raw["options"];
|
|
2004
|
+
const cleanTitle = typeof title === "string" ? title.trim().slice(0, MAX_WIDGET_TITLE_LENGTH) : "";
|
|
2005
|
+
const chosen = {};
|
|
2006
|
+
if (isRecord(options)) {
|
|
2007
|
+
for (const [key, value] of Object.entries(options)) {
|
|
2008
|
+
const parsed = parseOptionValue(value);
|
|
2009
|
+
if (parsed !== void 0) chosen[key] = parsed;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
const settings = {
|
|
2013
|
+
...cleanTitle === "" ? {} : { title: cleanTitle },
|
|
2014
|
+
...isWidgetWidth(width) ? { width } : {},
|
|
2015
|
+
...typeof flexible === "boolean" ? { flexible } : {},
|
|
2016
|
+
...Object.keys(chosen).length === 0 ? {} : { options: chosen }
|
|
2017
|
+
};
|
|
2018
|
+
return Object.keys(settings).length === 0 ? void 0 : settings;
|
|
2019
|
+
}
|
|
2020
|
+
function widthRange(item) {
|
|
2021
|
+
const min = isWidgetWidth(item.minWidth) ? item.minWidth : MIN_WIDGET_WIDTH;
|
|
2022
|
+
const max = isWidgetWidth(item.maxWidth) ? item.maxWidth : MAX_WIDGET_WIDTH;
|
|
2023
|
+
return { min, max: Math.max(min, max) };
|
|
2024
|
+
}
|
|
2025
|
+
var WIDTH_SHARES = {
|
|
2026
|
+
2: "1/6",
|
|
2027
|
+
3: "1/4",
|
|
2028
|
+
4: "1/3",
|
|
2029
|
+
5: "5/12",
|
|
2030
|
+
6: "1/2",
|
|
2031
|
+
7: "7/12",
|
|
2032
|
+
8: "2/3",
|
|
2033
|
+
9: "3/4",
|
|
2034
|
+
10: "5/6",
|
|
2035
|
+
11: "11/12",
|
|
2036
|
+
12: "Full"
|
|
2037
|
+
};
|
|
2038
|
+
function widthShareLabel(width) {
|
|
2039
|
+
return WIDTH_SHARES[width] ?? `${width}/12`;
|
|
2040
|
+
}
|
|
2041
|
+
function isOptionsLocked(item) {
|
|
2042
|
+
return resolveWidgetLock(item).options;
|
|
2043
|
+
}
|
|
2044
|
+
function fillWith(fill, flexible) {
|
|
2045
|
+
const heightToo = fill === "height" || fill === "both";
|
|
2046
|
+
if (flexible) return heightToo ? "both" : "width";
|
|
2047
|
+
return heightToo ? "height" : void 0;
|
|
2048
|
+
}
|
|
2049
|
+
function isFlexible(item, settings) {
|
|
2050
|
+
return item.fill === "width" || item.fill === "both";
|
|
2051
|
+
}
|
|
2052
|
+
function applySettings(definition, settings) {
|
|
2053
|
+
if (settings === void 0) return definition;
|
|
2054
|
+
const range = widthRange(definition);
|
|
2055
|
+
const width = settings.width === void 0 ? void 0 : Math.min(range.max, Math.max(range.min, settings.width));
|
|
2056
|
+
const title = settings.title === void 0 || settings.title.trim() === "" ? void 0 : settings.title;
|
|
2057
|
+
const flexibleChanged = settings.flexible !== void 0 && settings.flexible !== isFlexible(definition);
|
|
2058
|
+
if (title === void 0 && width === void 0 && !flexibleChanged) {
|
|
2059
|
+
return definition;
|
|
2060
|
+
}
|
|
2061
|
+
const next = { ...definition };
|
|
2062
|
+
if (title !== void 0) next.title = title;
|
|
2063
|
+
if (width !== void 0) next.width = width;
|
|
2064
|
+
if (flexibleChanged) {
|
|
2065
|
+
const fill = fillWith(
|
|
2066
|
+
definition.fill,
|
|
2067
|
+
settings.flexible === true
|
|
2068
|
+
);
|
|
2069
|
+
if (fill === void 0) {
|
|
2070
|
+
delete next.fill;
|
|
2071
|
+
} else {
|
|
2072
|
+
next.fill = fill;
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
return next;
|
|
2076
|
+
}
|
|
2077
|
+
function effectiveDefinitions(definitions, layout, options = {}) {
|
|
2078
|
+
return definitions.map(
|
|
2079
|
+
(definition) => options.overrideLocks !== true && isOptionsLocked(definition) ? definition : applySettings(definition, layout.settings?.[definition.key])
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2082
|
+
function sameSettings(a, b) {
|
|
2083
|
+
if (a === b) return true;
|
|
2084
|
+
return a?.title === b?.title && a?.width === b?.width && a?.flexible === b?.flexible && sameOptionValues(a?.options ?? {}, b?.options ?? {});
|
|
2085
|
+
}
|
|
2086
|
+
function setWidgetSettings(layout, key, patch) {
|
|
2087
|
+
const before = layout.settings?.[key];
|
|
2088
|
+
const draft = { ...before };
|
|
2089
|
+
for (const field of ["title", "width", "flexible", "options"]) {
|
|
2090
|
+
if (!(field in patch)) continue;
|
|
2091
|
+
const value = patch[field];
|
|
2092
|
+
if (value === void 0) {
|
|
2093
|
+
delete draft[field];
|
|
2094
|
+
} else {
|
|
2095
|
+
draft[field] = value;
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
const merged = parseOne(draft);
|
|
2099
|
+
if (sameSettings(before, merged)) return layout;
|
|
2100
|
+
const rest = { ...layout.settings };
|
|
2101
|
+
if (merged === void 0) {
|
|
2102
|
+
delete rest[key];
|
|
2103
|
+
} else {
|
|
2104
|
+
rest[key] = merged;
|
|
2105
|
+
}
|
|
2106
|
+
const { settings: _previous, ...others } = layout;
|
|
2107
|
+
return Object.keys(rest).length === 0 ? others : { ...others, settings: rest };
|
|
2108
|
+
}
|
|
2109
|
+
function normalizeTitle(title) {
|
|
2110
|
+
return title.normalize("NFKC").trim().toLowerCase();
|
|
2111
|
+
}
|
|
2112
|
+
function isTitleInUse(definitions, layout, key, title) {
|
|
2113
|
+
const wanted = normalizeTitle(title);
|
|
2114
|
+
if (wanted === "") return false;
|
|
2115
|
+
return effectiveDefinitions(definitions, layout, {
|
|
2116
|
+
overrideLocks: true
|
|
2117
|
+
}).some(
|
|
2118
|
+
(other) => other.key !== key && normalizeTitle(other.title ?? other.key) === wanted
|
|
2119
|
+
);
|
|
2120
|
+
}
|
|
2121
|
+
|
|
1950
2122
|
// src/core/layout.ts
|
|
1951
2123
|
var MAX_PAGE_TITLE_LENGTH = 30;
|
|
1952
2124
|
var MAX_PARSED_PAGES = 50;
|
|
@@ -2424,6 +2596,57 @@ function moveWidgetToPage(definitions, layout, widgetKey, targetKey, options = {
|
|
|
2424
2596
|
}
|
|
2425
2597
|
return ok(moved);
|
|
2426
2598
|
}
|
|
2599
|
+
function InlineConfirm({
|
|
2600
|
+
message,
|
|
2601
|
+
onAnswer
|
|
2602
|
+
}) {
|
|
2603
|
+
const slot = useSlotClassName();
|
|
2604
|
+
const { labels } = useWidgetSettings();
|
|
2605
|
+
const noRef = react.useRef(null);
|
|
2606
|
+
react.useEffect(() => {
|
|
2607
|
+
noRef.current?.focus();
|
|
2608
|
+
}, []);
|
|
2609
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2610
|
+
"span",
|
|
2611
|
+
{
|
|
2612
|
+
role: "group",
|
|
2613
|
+
"aria-label": message,
|
|
2614
|
+
className: "dwt-confirm",
|
|
2615
|
+
onKeyDown: (event) => {
|
|
2616
|
+
if (event.key === "Escape") {
|
|
2617
|
+
event.stopPropagation();
|
|
2618
|
+
onAnswer(false);
|
|
2619
|
+
}
|
|
2620
|
+
},
|
|
2621
|
+
children: [
|
|
2622
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { role: "alert", className: "dwt-confirm-message", children: message }),
|
|
2623
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2624
|
+
"button",
|
|
2625
|
+
{
|
|
2626
|
+
type: "button",
|
|
2627
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
2628
|
+
"aria-label": labels.confirmYes,
|
|
2629
|
+
title: labels.confirmYes,
|
|
2630
|
+
onClick: () => onAnswer(true),
|
|
2631
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2713" })
|
|
2632
|
+
}
|
|
2633
|
+
),
|
|
2634
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2635
|
+
"button",
|
|
2636
|
+
{
|
|
2637
|
+
ref: noRef,
|
|
2638
|
+
type: "button",
|
|
2639
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
2640
|
+
"aria-label": labels.confirmNo,
|
|
2641
|
+
title: labels.confirmNo,
|
|
2642
|
+
onClick: () => onAnswer(false),
|
|
2643
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2715" })
|
|
2644
|
+
}
|
|
2645
|
+
)
|
|
2646
|
+
]
|
|
2647
|
+
}
|
|
2648
|
+
);
|
|
2649
|
+
}
|
|
2427
2650
|
var EditMenuInitialOpenContext = react.createContext(false);
|
|
2428
2651
|
var ITEM_SELECTOR = '[role="menuitem"]:not(:disabled)';
|
|
2429
2652
|
function WidgetEditMenu({
|
|
@@ -2562,6 +2785,561 @@ function WidgetEditMenu({
|
|
|
2562
2785
|
}
|
|
2563
2786
|
);
|
|
2564
2787
|
}
|
|
2788
|
+
function draftFrom(settings) {
|
|
2789
|
+
return {
|
|
2790
|
+
title: settings?.title ?? "",
|
|
2791
|
+
width: settings?.width,
|
|
2792
|
+
flexible: settings?.flexible,
|
|
2793
|
+
options: settings?.options ?? {}
|
|
2794
|
+
};
|
|
2795
|
+
}
|
|
2796
|
+
function storedDefault(option) {
|
|
2797
|
+
return option.type === "dateRange" ? option.default : defaultOptionValue(option);
|
|
2798
|
+
}
|
|
2799
|
+
function sameValue2(a, b) {
|
|
2800
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
2801
|
+
return a.length === b.length && a.every((item, i) => item === b[i]);
|
|
2802
|
+
}
|
|
2803
|
+
return a === b;
|
|
2804
|
+
}
|
|
2805
|
+
function patchFrom(definition, draft) {
|
|
2806
|
+
const title = draft.title.trim();
|
|
2807
|
+
const options = {};
|
|
2808
|
+
for (const option of definition.options ?? []) {
|
|
2809
|
+
const value = draft.options[option.key];
|
|
2810
|
+
if (value === void 0) continue;
|
|
2811
|
+
if (sameValue2(value, storedDefault(option))) continue;
|
|
2812
|
+
options[option.key] = value;
|
|
2813
|
+
}
|
|
2814
|
+
return {
|
|
2815
|
+
title: title === "" ? void 0 : title,
|
|
2816
|
+
width: draft.width,
|
|
2817
|
+
flexible: draft.flexible === void 0 || draft.flexible === isFlexible(definition) ? void 0 : draft.flexible,
|
|
2818
|
+
options: Object.keys(options).length === 0 ? void 0 : options
|
|
2819
|
+
};
|
|
2820
|
+
}
|
|
2821
|
+
function patchKey(patch) {
|
|
2822
|
+
const options = {};
|
|
2823
|
+
for (const key of Object.keys(patch.options ?? {}).sort()) {
|
|
2824
|
+
options[key] = patch.options[key];
|
|
2825
|
+
}
|
|
2826
|
+
return JSON.stringify([patch.title, patch.width, patch.flexible, options]);
|
|
2827
|
+
}
|
|
2828
|
+
var EMPTY_PATCH = {
|
|
2829
|
+
title: void 0,
|
|
2830
|
+
width: void 0,
|
|
2831
|
+
flexible: void 0,
|
|
2832
|
+
options: void 0
|
|
2833
|
+
};
|
|
2834
|
+
function WidgetOptionsDialog({
|
|
2835
|
+
definition,
|
|
2836
|
+
settings,
|
|
2837
|
+
baseline,
|
|
2838
|
+
isTitleInUse: isTitleInUse2,
|
|
2839
|
+
onApply,
|
|
2840
|
+
onClose
|
|
2841
|
+
}) {
|
|
2842
|
+
const slot = useSlotClassName();
|
|
2843
|
+
const { labels } = useWidgetSettings();
|
|
2844
|
+
const dialogRef = react.useRef(null);
|
|
2845
|
+
const headingId = react.useId();
|
|
2846
|
+
const baseId = react.useId();
|
|
2847
|
+
const [draft, setDraft] = react.useState(() => draftFrom(settings));
|
|
2848
|
+
const [confirming, setConfirming] = react.useState(
|
|
2849
|
+
void 0
|
|
2850
|
+
);
|
|
2851
|
+
react.useEffect(() => {
|
|
2852
|
+
const dialog = dialogRef.current;
|
|
2853
|
+
if (dialog === null) return void 0;
|
|
2854
|
+
const opener = document.activeElement;
|
|
2855
|
+
if (!dialog.open) dialog.showModal();
|
|
2856
|
+
return () => {
|
|
2857
|
+
if (dialog.open) dialog.close();
|
|
2858
|
+
if (opener instanceof HTMLElement) opener.focus();
|
|
2859
|
+
};
|
|
2860
|
+
}, []);
|
|
2861
|
+
const savedKey = patchKey(patchFrom(definition, draftFrom(settings)));
|
|
2862
|
+
const draftPatch = patchFrom(definition, draft);
|
|
2863
|
+
const dirty = patchKey(draftPatch) !== savedKey;
|
|
2864
|
+
const titleTaken = draft.title.trim() !== "" && isTitleInUse2?.(draft.title.trim()) === true;
|
|
2865
|
+
const canApply = dirty && !titleTaken;
|
|
2866
|
+
const baselineKey = baseline === void 0 ? void 0 : patchKey(patchFrom(definition, draftFrom(baseline.settings)));
|
|
2867
|
+
const canRevert = baselineKey !== void 0 && baselineKey !== savedKey;
|
|
2868
|
+
const canReset = savedKey !== patchKey(EMPTY_PATCH);
|
|
2869
|
+
const range = widthRange(definition);
|
|
2870
|
+
const effectiveFlexible = draft.flexible ?? isFlexible(definition);
|
|
2871
|
+
function requestClose() {
|
|
2872
|
+
if (confirming !== void 0) {
|
|
2873
|
+
setConfirming(void 0);
|
|
2874
|
+
} else if (dirty) {
|
|
2875
|
+
setConfirming("discard");
|
|
2876
|
+
} else {
|
|
2877
|
+
onClose();
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
function answer(yes) {
|
|
2881
|
+
const which = confirming;
|
|
2882
|
+
setConfirming(void 0);
|
|
2883
|
+
if (!yes || which === void 0) return;
|
|
2884
|
+
if (which === "discard") {
|
|
2885
|
+
onClose();
|
|
2886
|
+
} else if (which === "apply") {
|
|
2887
|
+
onApply(draftPatch);
|
|
2888
|
+
onClose();
|
|
2889
|
+
} else if (which === "reset") {
|
|
2890
|
+
onApply(EMPTY_PATCH);
|
|
2891
|
+
onClose();
|
|
2892
|
+
} else if (baseline !== void 0) {
|
|
2893
|
+
onApply(patchFrom(definition, draftFrom(baseline.settings)));
|
|
2894
|
+
onClose();
|
|
2895
|
+
}
|
|
2896
|
+
}
|
|
2897
|
+
function setOption(key, value) {
|
|
2898
|
+
setDraft((current) => ({
|
|
2899
|
+
...current,
|
|
2900
|
+
options: { ...current.options, [key]: value }
|
|
2901
|
+
}));
|
|
2902
|
+
}
|
|
2903
|
+
const confirmMessage = {
|
|
2904
|
+
apply: labels.confirmApply,
|
|
2905
|
+
discard: labels.confirmDiscard,
|
|
2906
|
+
reset: labels.confirmResetOptions,
|
|
2907
|
+
revert: labels.confirmRevertOptions
|
|
2908
|
+
};
|
|
2909
|
+
const widths = [];
|
|
2910
|
+
for (let width = range.min; width <= range.max; width += 1)
|
|
2911
|
+
widths.push(width);
|
|
2912
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2913
|
+
"dialog",
|
|
2914
|
+
{
|
|
2915
|
+
ref: dialogRef,
|
|
2916
|
+
className: slot("dialog", "dwt-options-dialog"),
|
|
2917
|
+
"aria-labelledby": headingId,
|
|
2918
|
+
onCancel: (event) => {
|
|
2919
|
+
event.preventDefault();
|
|
2920
|
+
requestClose();
|
|
2921
|
+
},
|
|
2922
|
+
onClick: (event) => {
|
|
2923
|
+
if (event.target === dialogRef.current) requestClose();
|
|
2924
|
+
},
|
|
2925
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2926
|
+
"form",
|
|
2927
|
+
{
|
|
2928
|
+
className: "dwt-options",
|
|
2929
|
+
onSubmit: (event) => {
|
|
2930
|
+
event.preventDefault();
|
|
2931
|
+
if (canApply && confirming === void 0) setConfirming("apply");
|
|
2932
|
+
},
|
|
2933
|
+
children: [
|
|
2934
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { id: headingId, className: "dwt-options-heading", children: labels.optionsFor(definition.title) }),
|
|
2935
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dwt-options-field", children: [
|
|
2936
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: `${baseId}-title`, children: labels.optionsTitleField }),
|
|
2937
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2938
|
+
"input",
|
|
2939
|
+
{
|
|
2940
|
+
id: `${baseId}-title`,
|
|
2941
|
+
type: "text",
|
|
2942
|
+
value: draft.title,
|
|
2943
|
+
maxLength: MAX_WIDGET_TITLE_LENGTH,
|
|
2944
|
+
placeholder: definition.title,
|
|
2945
|
+
"aria-invalid": titleTaken,
|
|
2946
|
+
...titleTaken ? { "aria-describedby": `${baseId}-title-error` } : {},
|
|
2947
|
+
onChange: (event) => setDraft((current) => ({ ...current, title: event.target.value }))
|
|
2948
|
+
}
|
|
2949
|
+
),
|
|
2950
|
+
titleTaken && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2951
|
+
"p",
|
|
2952
|
+
{
|
|
2953
|
+
id: `${baseId}-title-error`,
|
|
2954
|
+
role: "alert",
|
|
2955
|
+
className: "dwt-options-error",
|
|
2956
|
+
children: labels.titleInUse
|
|
2957
|
+
}
|
|
2958
|
+
)
|
|
2959
|
+
] }),
|
|
2960
|
+
range.min < range.max && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dwt-options-field", children: [
|
|
2961
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: `${baseId}-width`, children: labels.optionsWidthField }),
|
|
2962
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2963
|
+
"select",
|
|
2964
|
+
{
|
|
2965
|
+
id: `${baseId}-width`,
|
|
2966
|
+
value: draft.width === void 0 ? "" : String(draft.width),
|
|
2967
|
+
onChange: (event) => {
|
|
2968
|
+
const value = event.target.value;
|
|
2969
|
+
setDraft((current) => ({
|
|
2970
|
+
...current,
|
|
2971
|
+
width: value === "" ? void 0 : Number(value)
|
|
2972
|
+
}));
|
|
2973
|
+
},
|
|
2974
|
+
children: [
|
|
2975
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: labels.widthDefault }),
|
|
2976
|
+
widths.map((width) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: String(width), children: labels.widthOption(width, widthShareLabel(width)) }, width))
|
|
2977
|
+
]
|
|
2978
|
+
}
|
|
2979
|
+
)
|
|
2980
|
+
] }),
|
|
2981
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "dwt-options-check", children: [
|
|
2982
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2983
|
+
"input",
|
|
2984
|
+
{
|
|
2985
|
+
type: "checkbox",
|
|
2986
|
+
checked: effectiveFlexible,
|
|
2987
|
+
onChange: (event) => setDraft((current) => ({
|
|
2988
|
+
...current,
|
|
2989
|
+
flexible: event.target.checked
|
|
2990
|
+
}))
|
|
2991
|
+
}
|
|
2992
|
+
),
|
|
2993
|
+
labels.optionsFlexible
|
|
2994
|
+
] }),
|
|
2995
|
+
(definition.options?.length ?? 0) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className: "dwt-options-group", children: [
|
|
2996
|
+
/* @__PURE__ */ jsxRuntime.jsx("legend", { children: labels.optionsDeclared }),
|
|
2997
|
+
(definition.options ?? []).map((option) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2998
|
+
OptionField,
|
|
2999
|
+
{
|
|
3000
|
+
option,
|
|
3001
|
+
value: draft.options[option.key],
|
|
3002
|
+
id: `${baseId}-opt-${option.key}`,
|
|
3003
|
+
onChange: (value) => setOption(option.key, value)
|
|
3004
|
+
},
|
|
3005
|
+
option.key
|
|
3006
|
+
))
|
|
3007
|
+
] }),
|
|
3008
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "dwt-options-actions", children: confirming === void 0 ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3009
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3010
|
+
"button",
|
|
3011
|
+
{
|
|
3012
|
+
type: "submit",
|
|
3013
|
+
className: slot("button", "dwt-button", "dwt-button-primary"),
|
|
3014
|
+
disabled: !canApply,
|
|
3015
|
+
children: labels.apply
|
|
3016
|
+
}
|
|
3017
|
+
),
|
|
3018
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3019
|
+
"button",
|
|
3020
|
+
{
|
|
3021
|
+
type: "button",
|
|
3022
|
+
className: slot("button", "dwt-button"),
|
|
3023
|
+
onClick: requestClose,
|
|
3024
|
+
children: labels.cancel
|
|
3025
|
+
}
|
|
3026
|
+
),
|
|
3027
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3028
|
+
"button",
|
|
3029
|
+
{
|
|
3030
|
+
type: "button",
|
|
3031
|
+
className: slot("button", "dwt-button"),
|
|
3032
|
+
disabled: !canReset,
|
|
3033
|
+
onClick: () => setConfirming("reset"),
|
|
3034
|
+
children: labels.resetToDefaults
|
|
3035
|
+
}
|
|
3036
|
+
),
|
|
3037
|
+
baseline !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3038
|
+
"button",
|
|
3039
|
+
{
|
|
3040
|
+
type: "button",
|
|
3041
|
+
className: slot("button", "dwt-button"),
|
|
3042
|
+
disabled: !canRevert,
|
|
3043
|
+
onClick: () => setConfirming("revert"),
|
|
3044
|
+
children: labels.revertToBeforeEditing
|
|
3045
|
+
}
|
|
3046
|
+
)
|
|
3047
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
3048
|
+
InlineConfirm,
|
|
3049
|
+
{
|
|
3050
|
+
message: confirmMessage[confirming],
|
|
3051
|
+
onAnswer: answer
|
|
3052
|
+
}
|
|
3053
|
+
) })
|
|
3054
|
+
]
|
|
3055
|
+
}
|
|
3056
|
+
)
|
|
3057
|
+
}
|
|
3058
|
+
);
|
|
3059
|
+
}
|
|
3060
|
+
function OptionField({
|
|
3061
|
+
option,
|
|
3062
|
+
value,
|
|
3063
|
+
id,
|
|
3064
|
+
onChange
|
|
3065
|
+
}) {
|
|
3066
|
+
const current = value ?? storedDefault(option);
|
|
3067
|
+
switch (option.type) {
|
|
3068
|
+
case "choice":
|
|
3069
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dwt-options-field", children: [
|
|
3070
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, children: option.label }),
|
|
3071
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3072
|
+
"select",
|
|
3073
|
+
{
|
|
3074
|
+
id,
|
|
3075
|
+
value: String(current ?? option.default),
|
|
3076
|
+
onChange: (event) => onChange(event.target.value),
|
|
3077
|
+
children: option.choices.map((choice) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: choice.value, children: choice.label }, choice.value))
|
|
3078
|
+
}
|
|
3079
|
+
)
|
|
3080
|
+
] });
|
|
3081
|
+
case "number":
|
|
3082
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3083
|
+
NumberField,
|
|
3084
|
+
{
|
|
3085
|
+
option,
|
|
3086
|
+
id,
|
|
3087
|
+
value: typeof current === "number" ? current : option.default,
|
|
3088
|
+
onChange
|
|
3089
|
+
}
|
|
3090
|
+
);
|
|
3091
|
+
case "boolean":
|
|
3092
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "dwt-options-check", children: [
|
|
3093
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3094
|
+
"input",
|
|
3095
|
+
{
|
|
3096
|
+
type: "checkbox",
|
|
3097
|
+
checked: current === true,
|
|
3098
|
+
onChange: (event) => onChange(event.target.checked)
|
|
3099
|
+
}
|
|
3100
|
+
),
|
|
3101
|
+
option.label
|
|
3102
|
+
] });
|
|
3103
|
+
case "text":
|
|
3104
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dwt-options-field", children: [
|
|
3105
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, children: option.label }),
|
|
3106
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3107
|
+
"input",
|
|
3108
|
+
{
|
|
3109
|
+
id,
|
|
3110
|
+
type: "text",
|
|
3111
|
+
value: typeof current === "string" ? current : "",
|
|
3112
|
+
maxLength: option.maxLength,
|
|
3113
|
+
onChange: (event) => onChange(event.target.value)
|
|
3114
|
+
}
|
|
3115
|
+
)
|
|
3116
|
+
] });
|
|
3117
|
+
case "color":
|
|
3118
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dwt-options-field", children: [
|
|
3119
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, children: option.label }),
|
|
3120
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3121
|
+
"input",
|
|
3122
|
+
{
|
|
3123
|
+
id,
|
|
3124
|
+
type: "color",
|
|
3125
|
+
value: typeof current === "string" ? current : option.default,
|
|
3126
|
+
onChange: (event) => onChange(event.target.value)
|
|
3127
|
+
}
|
|
3128
|
+
)
|
|
3129
|
+
] });
|
|
3130
|
+
case "dateRange":
|
|
3131
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3132
|
+
DateRangeField,
|
|
3133
|
+
{
|
|
3134
|
+
option,
|
|
3135
|
+
id,
|
|
3136
|
+
value: typeof current === "string" ? current : option.default,
|
|
3137
|
+
onChange
|
|
3138
|
+
}
|
|
3139
|
+
);
|
|
3140
|
+
case "sort":
|
|
3141
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3142
|
+
SortField,
|
|
3143
|
+
{
|
|
3144
|
+
option,
|
|
3145
|
+
id,
|
|
3146
|
+
value: typeof current === "string" ? current : void 0,
|
|
3147
|
+
onChange
|
|
3148
|
+
}
|
|
3149
|
+
);
|
|
3150
|
+
case "columns":
|
|
3151
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
3152
|
+
ColumnsField,
|
|
3153
|
+
{
|
|
3154
|
+
option,
|
|
3155
|
+
value: Array.isArray(current) ? current : option.default,
|
|
3156
|
+
onChange
|
|
3157
|
+
}
|
|
3158
|
+
);
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
function NumberField({
|
|
3162
|
+
option,
|
|
3163
|
+
id,
|
|
3164
|
+
value,
|
|
3165
|
+
onChange
|
|
3166
|
+
}) {
|
|
3167
|
+
const [text, setText] = react.useState(String(value));
|
|
3168
|
+
react.useEffect(() => {
|
|
3169
|
+
setText((typed) => Number(typed) === value ? typed : String(value));
|
|
3170
|
+
}, [value]);
|
|
3171
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dwt-options-field", children: [
|
|
3172
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, children: option.label }),
|
|
3173
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3174
|
+
"input",
|
|
3175
|
+
{
|
|
3176
|
+
id,
|
|
3177
|
+
type: "number",
|
|
3178
|
+
value: text,
|
|
3179
|
+
min: option.min,
|
|
3180
|
+
max: option.max,
|
|
3181
|
+
step: option.step ?? 1,
|
|
3182
|
+
onChange: (event) => {
|
|
3183
|
+
setText(event.target.value);
|
|
3184
|
+
const parsed = Number(event.target.value);
|
|
3185
|
+
if (event.target.value.trim() !== "" && coerceOptionValue(option, parsed) !== void 0) {
|
|
3186
|
+
onChange(parsed);
|
|
3187
|
+
}
|
|
3188
|
+
}
|
|
3189
|
+
}
|
|
3190
|
+
)
|
|
3191
|
+
] });
|
|
3192
|
+
}
|
|
3193
|
+
var PRESET_LABELS = {
|
|
3194
|
+
today: "Today",
|
|
3195
|
+
yesterday: "Yesterday",
|
|
3196
|
+
last7: "Last 7 days",
|
|
3197
|
+
last30: "Last 30 days",
|
|
3198
|
+
last90: "Last 90 days",
|
|
3199
|
+
thisMonth: "This month",
|
|
3200
|
+
lastMonth: "Last month",
|
|
3201
|
+
thisYear: "This year",
|
|
3202
|
+
lastYear: "Last year"
|
|
3203
|
+
};
|
|
3204
|
+
function DateRangeField({
|
|
3205
|
+
option,
|
|
3206
|
+
id,
|
|
3207
|
+
value,
|
|
3208
|
+
onChange
|
|
3209
|
+
}) {
|
|
3210
|
+
const { labels } = useWidgetSettings();
|
|
3211
|
+
const presets = option.presets ?? DATE_RANGE_PRESETS.map((preset) => ({
|
|
3212
|
+
value: preset,
|
|
3213
|
+
label: PRESET_LABELS[preset]
|
|
3214
|
+
}));
|
|
3215
|
+
const known = presets.some((preset) => preset.value === value);
|
|
3216
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dwt-options-field", children: [
|
|
3217
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, children: option.label }),
|
|
3218
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3219
|
+
"select",
|
|
3220
|
+
{
|
|
3221
|
+
id,
|
|
3222
|
+
value,
|
|
3223
|
+
onChange: (event) => onChange(event.target.value),
|
|
3224
|
+
children: [
|
|
3225
|
+
!known && /* @__PURE__ */ jsxRuntime.jsx("option", { value, children: labels.customRange(value) }),
|
|
3226
|
+
presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: preset.value, children: preset.label }, preset.value))
|
|
3227
|
+
]
|
|
3228
|
+
}
|
|
3229
|
+
)
|
|
3230
|
+
] });
|
|
3231
|
+
}
|
|
3232
|
+
function SortField({
|
|
3233
|
+
option,
|
|
3234
|
+
id,
|
|
3235
|
+
value,
|
|
3236
|
+
onChange
|
|
3237
|
+
}) {
|
|
3238
|
+
const { labels } = useWidgetSettings();
|
|
3239
|
+
const parsed = value === void 0 ? void 0 : parseSortValue(value);
|
|
3240
|
+
const column = parsed?.column ?? "";
|
|
3241
|
+
const direction = parsed?.direction ?? "desc";
|
|
3242
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "dwt-options-field", children: [
|
|
3243
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, children: option.label }),
|
|
3244
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "dwt-options-pair", children: [
|
|
3245
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3246
|
+
"select",
|
|
3247
|
+
{
|
|
3248
|
+
id,
|
|
3249
|
+
value: column,
|
|
3250
|
+
onChange: (event) => onChange(`${event.target.value}:${direction}`),
|
|
3251
|
+
children: [
|
|
3252
|
+
option.default === void 0 && column === "" && /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: labels.sortDefault }),
|
|
3253
|
+
option.columns.map((entry) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: entry.key, children: entry.label }, entry.key))
|
|
3254
|
+
]
|
|
3255
|
+
}
|
|
3256
|
+
),
|
|
3257
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3258
|
+
"select",
|
|
3259
|
+
{
|
|
3260
|
+
"aria-label": option.label,
|
|
3261
|
+
value: direction,
|
|
3262
|
+
disabled: column === "",
|
|
3263
|
+
onChange: (event) => onChange(`${column}:${event.target.value}`),
|
|
3264
|
+
children: [
|
|
3265
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "asc", children: labels.sortAscending }),
|
|
3266
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "desc", children: labels.sortDescending })
|
|
3267
|
+
]
|
|
3268
|
+
}
|
|
3269
|
+
)
|
|
3270
|
+
] })
|
|
3271
|
+
] });
|
|
3272
|
+
}
|
|
3273
|
+
function ColumnsField({
|
|
3274
|
+
option,
|
|
3275
|
+
value,
|
|
3276
|
+
onChange
|
|
3277
|
+
}) {
|
|
3278
|
+
const { labels } = useWidgetSettings();
|
|
3279
|
+
const slot = useSlotClassName();
|
|
3280
|
+
const ordered = [
|
|
3281
|
+
...value,
|
|
3282
|
+
...option.columns.map((c) => c.key).filter((key) => !value.includes(key))
|
|
3283
|
+
];
|
|
3284
|
+
const labelOf = (key) => option.columns.find((c) => c.key === key)?.label ?? key;
|
|
3285
|
+
function move(key, by) {
|
|
3286
|
+
const next = [...value];
|
|
3287
|
+
const from = next.indexOf(key);
|
|
3288
|
+
const to = from + by;
|
|
3289
|
+
if (from === -1 || to < 0 || to >= next.length) return;
|
|
3290
|
+
[next[from], next[to]] = [next[to], next[from]];
|
|
3291
|
+
onChange(next);
|
|
3292
|
+
}
|
|
3293
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("fieldset", { className: "dwt-options-columns", children: [
|
|
3294
|
+
/* @__PURE__ */ jsxRuntime.jsx("legend", { children: option.label }),
|
|
3295
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { children: ordered.map((key) => {
|
|
3296
|
+
const shown = value.includes(key);
|
|
3297
|
+
const name = labelOf(key);
|
|
3298
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
|
|
3299
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
3300
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3301
|
+
"input",
|
|
3302
|
+
{
|
|
3303
|
+
type: "checkbox",
|
|
3304
|
+
checked: shown,
|
|
3305
|
+
disabled: shown && value.length === 1,
|
|
3306
|
+
onChange: (event) => onChange(
|
|
3307
|
+
event.target.checked ? [...value, key] : value.filter((k) => k !== key)
|
|
3308
|
+
)
|
|
3309
|
+
}
|
|
3310
|
+
),
|
|
3311
|
+
name
|
|
3312
|
+
] }),
|
|
3313
|
+
shown && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "dwt-options-move", children: [
|
|
3314
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3315
|
+
"button",
|
|
3316
|
+
{
|
|
3317
|
+
type: "button",
|
|
3318
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
3319
|
+
"aria-label": labels.moveColumnUp(name),
|
|
3320
|
+
title: labels.moveColumnUp(name),
|
|
3321
|
+
disabled: value.indexOf(key) === 0,
|
|
3322
|
+
onClick: () => move(key, -1),
|
|
3323
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2191" })
|
|
3324
|
+
}
|
|
3325
|
+
),
|
|
3326
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3327
|
+
"button",
|
|
3328
|
+
{
|
|
3329
|
+
type: "button",
|
|
3330
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
3331
|
+
"aria-label": labels.moveColumnDown(name),
|
|
3332
|
+
title: labels.moveColumnDown(name),
|
|
3333
|
+
disabled: value.indexOf(key) === value.length - 1,
|
|
3334
|
+
onClick: () => move(key, 1),
|
|
3335
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2193" })
|
|
3336
|
+
}
|
|
3337
|
+
)
|
|
3338
|
+
] })
|
|
3339
|
+
] }, key);
|
|
3340
|
+
}) })
|
|
3341
|
+
] });
|
|
3342
|
+
}
|
|
2565
3343
|
function nextSort(current, column) {
|
|
2566
3344
|
if (current?.column !== column) return { column, direction: "asc" };
|
|
2567
3345
|
return current.direction === "asc" ? { column, direction: "desc" } : void 0;
|
|
@@ -2989,57 +3767,6 @@ function DetailHost({
|
|
|
2989
3767
|
}
|
|
2990
3768
|
) });
|
|
2991
3769
|
}
|
|
2992
|
-
function InlineConfirm({
|
|
2993
|
-
message,
|
|
2994
|
-
onAnswer
|
|
2995
|
-
}) {
|
|
2996
|
-
const slot = useSlotClassName();
|
|
2997
|
-
const { labels } = useWidgetSettings();
|
|
2998
|
-
const noRef = react.useRef(null);
|
|
2999
|
-
react.useEffect(() => {
|
|
3000
|
-
noRef.current?.focus();
|
|
3001
|
-
}, []);
|
|
3002
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3003
|
-
"span",
|
|
3004
|
-
{
|
|
3005
|
-
role: "group",
|
|
3006
|
-
"aria-label": message,
|
|
3007
|
-
className: "dwt-confirm",
|
|
3008
|
-
onKeyDown: (event) => {
|
|
3009
|
-
if (event.key === "Escape") {
|
|
3010
|
-
event.stopPropagation();
|
|
3011
|
-
onAnswer(false);
|
|
3012
|
-
}
|
|
3013
|
-
},
|
|
3014
|
-
children: [
|
|
3015
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { role: "alert", className: "dwt-confirm-message", children: message }),
|
|
3016
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3017
|
-
"button",
|
|
3018
|
-
{
|
|
3019
|
-
type: "button",
|
|
3020
|
-
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
3021
|
-
"aria-label": labels.confirmYes,
|
|
3022
|
-
title: labels.confirmYes,
|
|
3023
|
-
onClick: () => onAnswer(true),
|
|
3024
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2713" })
|
|
3025
|
-
}
|
|
3026
|
-
),
|
|
3027
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3028
|
-
"button",
|
|
3029
|
-
{
|
|
3030
|
-
ref: noRef,
|
|
3031
|
-
type: "button",
|
|
3032
|
-
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
3033
|
-
"aria-label": labels.confirmNo,
|
|
3034
|
-
title: labels.confirmNo,
|
|
3035
|
-
onClick: () => onAnswer(false),
|
|
3036
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2715" })
|
|
3037
|
-
}
|
|
3038
|
-
)
|
|
3039
|
-
]
|
|
3040
|
-
}
|
|
3041
|
-
);
|
|
3042
|
-
}
|
|
3043
3770
|
function PageTabs({
|
|
3044
3771
|
pages,
|
|
3045
3772
|
activeKey,
|
|
@@ -3245,12 +3972,19 @@ function DashboardInner({
|
|
|
3245
3972
|
}) {
|
|
3246
3973
|
const slot = useSlotClassName();
|
|
3247
3974
|
const { labels } = useWidgetSettings();
|
|
3248
|
-
const
|
|
3975
|
+
const effectiveWidgets = widgets.map((w) => {
|
|
3976
|
+
const settings = savedLayout.settings?.[w.definition.key];
|
|
3977
|
+
return settings === void 0 || !overrideLocks && isOptionsLocked(w.definition) ? w : { ...w, definition: applySettings(w.definition, settings) };
|
|
3978
|
+
});
|
|
3979
|
+
const definitions = effectiveWidgets.map(
|
|
3249
3980
|
(w) => overrideLocks ? withoutLock(w.definition) : w.definition
|
|
3250
3981
|
);
|
|
3251
3982
|
const layout = enforceLocks(definitions, savedLayout);
|
|
3252
3983
|
const byKey = new Map(
|
|
3253
|
-
|
|
3984
|
+
effectiveWidgets.map((w) => [w.definition.key, w])
|
|
3985
|
+
);
|
|
3986
|
+
const authorDefinitions = new Map(
|
|
3987
|
+
widgets.map((w) => [w.definition.key, w.definition])
|
|
3254
3988
|
);
|
|
3255
3989
|
const pages = pageList(layout);
|
|
3256
3990
|
const paged = pages.length >= 2;
|
|
@@ -3295,6 +4029,7 @@ function DashboardInner({
|
|
|
3295
4029
|
const minimized = editable ? visible.filter((definition) => isMinimized(view, definition.key)) : [];
|
|
3296
4030
|
const shown = editable ? visible.filter((definition) => !isMinimized(view, definition.key)) : visible;
|
|
3297
4031
|
const [detailKey, setDetailKey] = react.useState(void 0);
|
|
4032
|
+
const [optionsKey, setOptionsKey] = react.useState(void 0);
|
|
3298
4033
|
const gridRef = react.useRef(null);
|
|
3299
4034
|
const twelve = usesWidthColumns(shown);
|
|
3300
4035
|
const spans = useFillSpans(
|
|
@@ -3434,7 +4169,14 @@ function DashboardInner({
|
|
|
3434
4169
|
const which = pending;
|
|
3435
4170
|
setConfirming(void 0);
|
|
3436
4171
|
if (yes && which === "reset") {
|
|
3437
|
-
|
|
4172
|
+
const arranged = enforceLocks(
|
|
4173
|
+
definitions,
|
|
4174
|
+
defaultLayout ?? EMPTY_LAYOUT
|
|
4175
|
+
);
|
|
4176
|
+
const { settings: _defaultSettings, ...arrangement } = arranged;
|
|
4177
|
+
change(
|
|
4178
|
+
layout.settings === void 0 ? arrangement : { ...arrangement, settings: layout.settings }
|
|
4179
|
+
);
|
|
3438
4180
|
} else if (yes && which === "revert" && snapshot !== void 0) {
|
|
3439
4181
|
change(snapshot);
|
|
3440
4182
|
}
|
|
@@ -3731,6 +4473,15 @@ function DashboardInner({
|
|
|
3731
4473
|
onSelect: () => changePage(moveWidgetBy(pageDefs, view, key, 1))
|
|
3732
4474
|
}
|
|
3733
4475
|
],
|
|
4476
|
+
...lock.options ? [] : [
|
|
4477
|
+
{
|
|
4478
|
+
kind: "action",
|
|
4479
|
+
key: "options",
|
|
4480
|
+
label: labels.menuOptions,
|
|
4481
|
+
ariaLabel: labels.optionsFor(title),
|
|
4482
|
+
onSelect: () => setOptionsKey(key)
|
|
4483
|
+
}
|
|
4484
|
+
],
|
|
3734
4485
|
...pageTargets,
|
|
3735
4486
|
...lock.hide ? [] : [
|
|
3736
4487
|
{
|
|
@@ -3819,6 +4570,30 @@ function DashboardInner({
|
|
|
3819
4570
|
]
|
|
3820
4571
|
}
|
|
3821
4572
|
),
|
|
4573
|
+
optionsKey !== void 0 && authorDefinitions.get(optionsKey) !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4574
|
+
WidgetOptionsDialog,
|
|
4575
|
+
{
|
|
4576
|
+
definition: authorDefinitions.get(optionsKey),
|
|
4577
|
+
settings: layout.settings?.[optionsKey],
|
|
4578
|
+
...snapshot === void 0 ? {} : { baseline: { settings: snapshot.settings?.[optionsKey] } },
|
|
4579
|
+
isTitleInUse: (title) => isTitleInUse(
|
|
4580
|
+
widgets.map((w) => w.definition),
|
|
4581
|
+
layout,
|
|
4582
|
+
optionsKey,
|
|
4583
|
+
title
|
|
4584
|
+
),
|
|
4585
|
+
onApply: (patch) => {
|
|
4586
|
+
change(setWidgetSettings(layout, optionsKey, patch));
|
|
4587
|
+
setAnnouncement(
|
|
4588
|
+
labels.optionsSaved(
|
|
4589
|
+
authorDefinitions.get(optionsKey)?.title ?? optionsKey
|
|
4590
|
+
)
|
|
4591
|
+
);
|
|
4592
|
+
},
|
|
4593
|
+
onClose: () => setOptionsKey(void 0)
|
|
4594
|
+
},
|
|
4595
|
+
optionsKey
|
|
4596
|
+
),
|
|
3822
4597
|
detailKey !== void 0 && byKey.get(detailKey) !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3823
4598
|
DetailHost,
|
|
3824
4599
|
{
|
|
@@ -4093,7 +4868,7 @@ function describeType2(value) {
|
|
|
4093
4868
|
}
|
|
4094
4869
|
return typeof value;
|
|
4095
4870
|
}
|
|
4096
|
-
function
|
|
4871
|
+
function isRecord2(value) {
|
|
4097
4872
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4098
4873
|
}
|
|
4099
4874
|
function join(path, field) {
|
|
@@ -4175,7 +4950,7 @@ function requireOneOf(record, field, options, path, problems) {
|
|
|
4175
4950
|
function eachRecord(items, path, problems, check) {
|
|
4176
4951
|
items.forEach((item, index) => {
|
|
4177
4952
|
const itemPath = `${path}[${index}]`;
|
|
4178
|
-
if (
|
|
4953
|
+
if (isRecord2(item)) {
|
|
4179
4954
|
check(item, itemPath);
|
|
4180
4955
|
} else {
|
|
4181
4956
|
problems.push(
|
|
@@ -4329,7 +5104,7 @@ function formatProblems(prefix, problems) {
|
|
|
4329
5104
|
}
|
|
4330
5105
|
function validateWidgetData(value, options = {}) {
|
|
4331
5106
|
const subject = options.widgetKey === void 0 ? "Widget data" : `Widget ${JSON.stringify(options.widgetKey)}`;
|
|
4332
|
-
if (!
|
|
5107
|
+
if (!isRecord2(value)) {
|
|
4333
5108
|
return err(`${subject}: must be an object, got ${describeType2(value)}.`);
|
|
4334
5109
|
}
|
|
4335
5110
|
if (value["empty"] === true) {
|
|
@@ -4792,6 +5567,7 @@ exports.WidgetDetail = WidgetDetail;
|
|
|
4792
5567
|
exports.WidgetDetailDialog = WidgetDetailDialog;
|
|
4793
5568
|
exports.WidgetGrid = WidgetGrid;
|
|
4794
5569
|
exports.WidgetLink = WidgetLink;
|
|
5570
|
+
exports.WidgetOptionsDialog = WidgetOptionsDialog;
|
|
4795
5571
|
exports.WidgetSettingsProvider = WidgetSettingsProvider;
|
|
4796
5572
|
exports.barPath = barPath;
|
|
4797
5573
|
exports.buildChartModel = buildChartModel;
|