@richardmcquiston01/dashboard-widgets-toolkit 0.11.1 → 0.12.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/react.cjs +242 -74
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +7 -1
- package/dist/react.d.ts +7 -1
- package/dist/react.js +242 -74
- package/dist/react.js.map +1 -1
- package/dist/styles.css +54 -8
- package/package.json +1 -1
package/dist/react.cjs
CHANGED
|
@@ -825,6 +825,10 @@ var DEFAULT_LABELS = {
|
|
|
825
825
|
confirmDeletePage: (title) => `Delete the page "${title}" and move its widgets to another page?`,
|
|
826
826
|
movePageLeft: (title) => `Move ${title} page left`,
|
|
827
827
|
movePageRight: (title) => `Move ${title} page right`,
|
|
828
|
+
arrangeWidget: (title) => `Arrange ${title}`,
|
|
829
|
+
menuMoveEarlier: "Move earlier",
|
|
830
|
+
menuMoveLater: "Move later",
|
|
831
|
+
menuHide: "Hide",
|
|
828
832
|
moveToPage: (title) => `Move ${title} to another page`,
|
|
829
833
|
moveToPagePlaceholder: "Move to page\u2026",
|
|
830
834
|
moveToPageOption: (title, rowsFree) => `${title} (${rowsFree} ${rowsFree === 1 ? "row" : "rows"} free)`,
|
|
@@ -2420,6 +2424,144 @@ function moveWidgetToPage(definitions, layout, widgetKey, targetKey, options = {
|
|
|
2420
2424
|
}
|
|
2421
2425
|
return ok(moved);
|
|
2422
2426
|
}
|
|
2427
|
+
var EditMenuInitialOpenContext = react.createContext(false);
|
|
2428
|
+
var ITEM_SELECTOR = '[role="menuitem"]:not(:disabled)';
|
|
2429
|
+
function WidgetEditMenu({
|
|
2430
|
+
label,
|
|
2431
|
+
items,
|
|
2432
|
+
initialOpen
|
|
2433
|
+
}) {
|
|
2434
|
+
const slot = useSlotClassName();
|
|
2435
|
+
const startOpen = react.useContext(EditMenuInitialOpenContext);
|
|
2436
|
+
const menuId = react.useId();
|
|
2437
|
+
const [open, setOpen] = react.useState(initialOpen ?? startOpen);
|
|
2438
|
+
const wrapper = react.useRef(null);
|
|
2439
|
+
const button = react.useRef(null);
|
|
2440
|
+
const menu = react.useRef(null);
|
|
2441
|
+
react.useEffect(() => {
|
|
2442
|
+
if (!open) return void 0;
|
|
2443
|
+
menu.current?.querySelector(ITEM_SELECTOR)?.focus();
|
|
2444
|
+
const onPointerDown = (event) => {
|
|
2445
|
+
if (!wrapper.current?.contains(event.target)) setOpen(false);
|
|
2446
|
+
};
|
|
2447
|
+
document.addEventListener("pointerdown", onPointerDown);
|
|
2448
|
+
return () => document.removeEventListener("pointerdown", onPointerDown);
|
|
2449
|
+
}, [open]);
|
|
2450
|
+
function close(returnFocus) {
|
|
2451
|
+
setOpen(false);
|
|
2452
|
+
if (returnFocus) button.current?.focus();
|
|
2453
|
+
}
|
|
2454
|
+
function onKeyDown(event) {
|
|
2455
|
+
if (event.key === "Escape") {
|
|
2456
|
+
event.stopPropagation();
|
|
2457
|
+
close(true);
|
|
2458
|
+
return;
|
|
2459
|
+
}
|
|
2460
|
+
const enabled = [
|
|
2461
|
+
...menu.current?.querySelectorAll(ITEM_SELECTOR) ?? []
|
|
2462
|
+
];
|
|
2463
|
+
if (enabled.length === 0) return;
|
|
2464
|
+
const current = enabled.indexOf(
|
|
2465
|
+
document.activeElement
|
|
2466
|
+
);
|
|
2467
|
+
let next;
|
|
2468
|
+
if (event.key === "ArrowDown") next = (current + 1) % enabled.length;
|
|
2469
|
+
else if (event.key === "ArrowUp") {
|
|
2470
|
+
next = (current - 1 + enabled.length) % enabled.length;
|
|
2471
|
+
} else if (event.key === "Home") next = 0;
|
|
2472
|
+
else if (event.key === "End") next = enabled.length - 1;
|
|
2473
|
+
if (next !== void 0) {
|
|
2474
|
+
event.preventDefault();
|
|
2475
|
+
enabled[next]?.focus();
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2479
|
+
"span",
|
|
2480
|
+
{
|
|
2481
|
+
ref: wrapper,
|
|
2482
|
+
className: "dwt-edit-menu",
|
|
2483
|
+
onBlur: (event) => {
|
|
2484
|
+
if (!event.currentTarget.contains(event.relatedTarget)) {
|
|
2485
|
+
setOpen(false);
|
|
2486
|
+
}
|
|
2487
|
+
},
|
|
2488
|
+
children: [
|
|
2489
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2490
|
+
"button",
|
|
2491
|
+
{
|
|
2492
|
+
ref: button,
|
|
2493
|
+
type: "button",
|
|
2494
|
+
className: slot("button", "dwt-button", "dwt-icon-button"),
|
|
2495
|
+
"aria-label": label,
|
|
2496
|
+
title: label,
|
|
2497
|
+
"aria-haspopup": "menu",
|
|
2498
|
+
"aria-expanded": open,
|
|
2499
|
+
"aria-controls": open ? menuId : void 0,
|
|
2500
|
+
onClick: () => setOpen((current) => !current),
|
|
2501
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2502
|
+
"svg",
|
|
2503
|
+
{
|
|
2504
|
+
viewBox: "0 0 24 24",
|
|
2505
|
+
width: "16",
|
|
2506
|
+
height: "16",
|
|
2507
|
+
"aria-hidden": "true",
|
|
2508
|
+
focusable: "false",
|
|
2509
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2510
|
+
"path",
|
|
2511
|
+
{
|
|
2512
|
+
d: "M5 9l-3 3 3 3M9 5l3-3 3 3M15 19l-3 3-3-3M19 9l3 3-3 3M2 12h20M12 2v20",
|
|
2513
|
+
fill: "none",
|
|
2514
|
+
stroke: "currentColor",
|
|
2515
|
+
strokeWidth: "2",
|
|
2516
|
+
strokeLinecap: "round",
|
|
2517
|
+
strokeLinejoin: "round"
|
|
2518
|
+
}
|
|
2519
|
+
)
|
|
2520
|
+
}
|
|
2521
|
+
)
|
|
2522
|
+
}
|
|
2523
|
+
),
|
|
2524
|
+
open && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2525
|
+
"div",
|
|
2526
|
+
{
|
|
2527
|
+
ref: menu,
|
|
2528
|
+
id: menuId,
|
|
2529
|
+
className: "dwt-edit-popover",
|
|
2530
|
+
role: "menu",
|
|
2531
|
+
"aria-label": label,
|
|
2532
|
+
onKeyDown,
|
|
2533
|
+
children: items.map(
|
|
2534
|
+
(item) => item.kind === "heading" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2535
|
+
"p",
|
|
2536
|
+
{
|
|
2537
|
+
className: "dwt-edit-heading",
|
|
2538
|
+
role: "presentation",
|
|
2539
|
+
children: item.label
|
|
2540
|
+
},
|
|
2541
|
+
item.key
|
|
2542
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2543
|
+
"button",
|
|
2544
|
+
{
|
|
2545
|
+
type: "button",
|
|
2546
|
+
role: "menuitem",
|
|
2547
|
+
className: "dwt-edit-option",
|
|
2548
|
+
...item.ariaLabel === void 0 ? {} : { "aria-label": item.ariaLabel },
|
|
2549
|
+
disabled: item.disabled === true,
|
|
2550
|
+
onClick: () => {
|
|
2551
|
+
close(false);
|
|
2552
|
+
item.onSelect();
|
|
2553
|
+
},
|
|
2554
|
+
children: item.label
|
|
2555
|
+
},
|
|
2556
|
+
item.key
|
|
2557
|
+
)
|
|
2558
|
+
)
|
|
2559
|
+
}
|
|
2560
|
+
)
|
|
2561
|
+
]
|
|
2562
|
+
}
|
|
2563
|
+
);
|
|
2564
|
+
}
|
|
2423
2565
|
function nextSort(current, column) {
|
|
2424
2566
|
if (current?.column !== column) return { column, direction: "asc" };
|
|
2425
2567
|
return current.direction === "asc" ? { column, direction: "desc" } : void 0;
|
|
@@ -3143,6 +3285,7 @@ function DashboardInner({
|
|
|
3143
3285
|
const [announcement, setAnnouncement] = react.useState("");
|
|
3144
3286
|
const [pageAnnouncement, setPageAnnouncement] = react.useState("");
|
|
3145
3287
|
const [pageError, setPageError] = react.useState(void 0);
|
|
3288
|
+
const [newPage, setNewPage] = react.useState(void 0);
|
|
3146
3289
|
const [pageEditor, setPageEditor] = react.useState(void 0);
|
|
3147
3290
|
const editorMode = pageEditor?.key === activeKey ? pageEditor.mode : void 0;
|
|
3148
3291
|
const instanceId = react.useId();
|
|
@@ -3173,6 +3316,7 @@ function DashboardInner({
|
|
|
3173
3316
|
onActivePageChange?.(pageKey);
|
|
3174
3317
|
setPageError(void 0);
|
|
3175
3318
|
setPageEditor(void 0);
|
|
3319
|
+
setNewPage(void 0);
|
|
3176
3320
|
setPageAnnouncement(
|
|
3177
3321
|
labels.pageTabName(
|
|
3178
3322
|
index + 1,
|
|
@@ -3190,6 +3334,7 @@ function DashboardInner({
|
|
|
3190
3334
|
change(added.value);
|
|
3191
3335
|
const created = added.value.pages?.at(-1);
|
|
3192
3336
|
if (created !== void 0) {
|
|
3337
|
+
setNewPage({ key: created.key, activeBefore: activeKey });
|
|
3193
3338
|
if (activePageProp === void 0) setActiveState(created.key);
|
|
3194
3339
|
onActivePageChange?.(created.key);
|
|
3195
3340
|
setPageError(void 0);
|
|
@@ -3201,8 +3346,21 @@ function DashboardInner({
|
|
|
3201
3346
|
if (!renamed.ok) return renamed.error;
|
|
3202
3347
|
change(renamed.value);
|
|
3203
3348
|
setPageEditor(void 0);
|
|
3349
|
+
setNewPage(void 0);
|
|
3204
3350
|
return void 0;
|
|
3205
3351
|
}
|
|
3352
|
+
function cancelPageEditor() {
|
|
3353
|
+
const fresh = newPage;
|
|
3354
|
+
setPageEditor(void 0);
|
|
3355
|
+
setNewPage(void 0);
|
|
3356
|
+
if (fresh === void 0 || fresh.key !== activeKey) return;
|
|
3357
|
+
const pagesWithout = pages.filter(
|
|
3358
|
+
(page) => page.key !== fresh.key
|
|
3359
|
+
);
|
|
3360
|
+
if (pagesWithout.length === pages.length) return;
|
|
3361
|
+
change({ ...layout, pages: pagesWithout });
|
|
3362
|
+
selectPage(fresh.activeBefore);
|
|
3363
|
+
}
|
|
3206
3364
|
function deletePageAction() {
|
|
3207
3365
|
const index = pages.findIndex((page) => page.key === activeKey);
|
|
3208
3366
|
const removed = removePage(definitions, layout, activeKey, roomOptions);
|
|
@@ -3376,7 +3534,7 @@ function DashboardInner({
|
|
|
3376
3534
|
{
|
|
3377
3535
|
initial: activePage.title,
|
|
3378
3536
|
onSubmit: renamePageAction,
|
|
3379
|
-
onCancel:
|
|
3537
|
+
onCancel: cancelPageEditor
|
|
3380
3538
|
},
|
|
3381
3539
|
activeKey
|
|
3382
3540
|
),
|
|
@@ -3424,7 +3582,27 @@ function DashboardInner({
|
|
|
3424
3582
|
"aria-label": labels.deletePage(activePage.title),
|
|
3425
3583
|
title: labels.deletePage(activePage.title),
|
|
3426
3584
|
onClick: () => setPageEditor({ mode: "delete", key: activeKey }),
|
|
3427
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3585
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3586
|
+
"svg",
|
|
3587
|
+
{
|
|
3588
|
+
viewBox: "0 0 16 16",
|
|
3589
|
+
width: "14",
|
|
3590
|
+
height: "14",
|
|
3591
|
+
"aria-hidden": "true",
|
|
3592
|
+
focusable: "false",
|
|
3593
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3594
|
+
"path",
|
|
3595
|
+
{
|
|
3596
|
+
d: "M3 4.5h10M6.5 4.5V3h3v1.5M4.5 4.5l.6 8.5h5.8l.6-8.5M6.8 7v3.5M9.2 7v3.5",
|
|
3597
|
+
fill: "none",
|
|
3598
|
+
stroke: "currentColor",
|
|
3599
|
+
strokeWidth: "1.3",
|
|
3600
|
+
strokeLinecap: "round",
|
|
3601
|
+
strokeLinejoin: "round"
|
|
3602
|
+
}
|
|
3603
|
+
)
|
|
3604
|
+
}
|
|
3605
|
+
)
|
|
3428
3606
|
}
|
|
3429
3607
|
)
|
|
3430
3608
|
] }),
|
|
@@ -3506,6 +3684,64 @@ function DashboardInner({
|
|
|
3506
3684
|
const lockLabel = overrideLocks ? labels.lockedForViewers(title) : labels.locked(title);
|
|
3507
3685
|
const canMoveEarlier = !lock.move && moveWidgetBy(pageDefs, view, key, -1) !== view;
|
|
3508
3686
|
const canMoveLater = !lock.move && moveWidgetBy(pageDefs, view, key, 1) !== view;
|
|
3687
|
+
const pageTargets = paged && !lock.move ? [
|
|
3688
|
+
{
|
|
3689
|
+
kind: "heading",
|
|
3690
|
+
key: "page-heading",
|
|
3691
|
+
label: labels.moveToPagePlaceholder
|
|
3692
|
+
},
|
|
3693
|
+
...pages.filter((page) => page.key !== activeKey).map((page) => ({
|
|
3694
|
+
kind: "action",
|
|
3695
|
+
key: `page:${page.key}`,
|
|
3696
|
+
label: labels.moveToPageOption(
|
|
3697
|
+
page.title,
|
|
3698
|
+
pageRoom(definitions, layout, page.key, roomOptions)?.rowsFree ?? 0
|
|
3699
|
+
),
|
|
3700
|
+
ariaLabel: labels.moveToPageOption(
|
|
3701
|
+
page.title,
|
|
3702
|
+
pageRoom(definitions, layout, page.key, roomOptions)?.rowsFree ?? 0
|
|
3703
|
+
),
|
|
3704
|
+
onSelect: () => moveWidgetAction(key, page.key)
|
|
3705
|
+
})),
|
|
3706
|
+
...maxPages === void 0 || pages.length < maxPages ? [
|
|
3707
|
+
{
|
|
3708
|
+
kind: "action",
|
|
3709
|
+
key: "page:new",
|
|
3710
|
+
label: labels.newPageOption,
|
|
3711
|
+
onSelect: () => moveWidgetAction(key, NEW_PAGE_VALUE)
|
|
3712
|
+
}
|
|
3713
|
+
] : []
|
|
3714
|
+
] : [];
|
|
3715
|
+
const editItems = [
|
|
3716
|
+
...lock.move ? [] : [
|
|
3717
|
+
{
|
|
3718
|
+
kind: "action",
|
|
3719
|
+
key: "earlier",
|
|
3720
|
+
label: labels.menuMoveEarlier,
|
|
3721
|
+
ariaLabel: labels.moveEarlier(title),
|
|
3722
|
+
disabled: index === 0 || !canMoveEarlier,
|
|
3723
|
+
onSelect: () => changePage(moveWidgetBy(pageDefs, view, key, -1))
|
|
3724
|
+
},
|
|
3725
|
+
{
|
|
3726
|
+
kind: "action",
|
|
3727
|
+
key: "later",
|
|
3728
|
+
label: labels.menuMoveLater,
|
|
3729
|
+
ariaLabel: labels.moveLater(title),
|
|
3730
|
+
disabled: index === shown.length - 1 || !canMoveLater,
|
|
3731
|
+
onSelect: () => changePage(moveWidgetBy(pageDefs, view, key, 1))
|
|
3732
|
+
}
|
|
3733
|
+
],
|
|
3734
|
+
...pageTargets,
|
|
3735
|
+
...lock.hide ? [] : [
|
|
3736
|
+
{
|
|
3737
|
+
kind: "action",
|
|
3738
|
+
key: "hide",
|
|
3739
|
+
label: labels.menuHide,
|
|
3740
|
+
ariaLabel: labels.hide(title),
|
|
3741
|
+
onSelect: () => changePage(hideWidget(view, key))
|
|
3742
|
+
}
|
|
3743
|
+
]
|
|
3744
|
+
];
|
|
3509
3745
|
const actions = controlsShown ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3510
3746
|
isLocked && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3511
3747
|
"span",
|
|
@@ -3548,79 +3784,11 @@ function DashboardInner({
|
|
|
3548
3784
|
)
|
|
3549
3785
|
}
|
|
3550
3786
|
),
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
"button",
|
|
3554
|
-
{
|
|
3555
|
-
type: "button",
|
|
3556
|
-
className: slot(
|
|
3557
|
-
"button",
|
|
3558
|
-
"dwt-button",
|
|
3559
|
-
"dwt-icon-button"
|
|
3560
|
-
),
|
|
3561
|
-
"aria-label": labels.moveEarlier(title),
|
|
3562
|
-
title: labels.moveEarlier(title),
|
|
3563
|
-
disabled: index === 0 || !canMoveEarlier,
|
|
3564
|
-
onClick: () => changePage(moveWidgetBy(pageDefs, view, key, -1)),
|
|
3565
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2191" })
|
|
3566
|
-
}
|
|
3567
|
-
),
|
|
3568
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3569
|
-
"button",
|
|
3570
|
-
{
|
|
3571
|
-
type: "button",
|
|
3572
|
-
className: slot(
|
|
3573
|
-
"button",
|
|
3574
|
-
"dwt-button",
|
|
3575
|
-
"dwt-icon-button"
|
|
3576
|
-
),
|
|
3577
|
-
"aria-label": labels.moveLater(title),
|
|
3578
|
-
title: labels.moveLater(title),
|
|
3579
|
-
disabled: index === shown.length - 1 || !canMoveLater,
|
|
3580
|
-
onClick: () => changePage(moveWidgetBy(pageDefs, view, key, 1)),
|
|
3581
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2193" })
|
|
3582
|
-
}
|
|
3583
|
-
),
|
|
3584
|
-
paged && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3585
|
-
"select",
|
|
3586
|
-
{
|
|
3587
|
-
className: "dwt-move-select",
|
|
3588
|
-
"aria-label": labels.moveToPage(title),
|
|
3589
|
-
value: "",
|
|
3590
|
-
onChange: (event) => {
|
|
3591
|
-
if (event.target.value !== "") {
|
|
3592
|
-
moveWidgetAction(key, event.target.value);
|
|
3593
|
-
}
|
|
3594
|
-
},
|
|
3595
|
-
children: [
|
|
3596
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: labels.moveToPagePlaceholder }),
|
|
3597
|
-
pages.filter((page) => page.key !== activeKey).map((page) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: page.key, children: labels.moveToPageOption(
|
|
3598
|
-
page.title,
|
|
3599
|
-
pageRoom(
|
|
3600
|
-
definitions,
|
|
3601
|
-
layout,
|
|
3602
|
-
page.key,
|
|
3603
|
-
roomOptions
|
|
3604
|
-
)?.rowsFree ?? 0
|
|
3605
|
-
) }, page.key)),
|
|
3606
|
-
(maxPages === void 0 || pages.length < maxPages) && /* @__PURE__ */ jsxRuntime.jsx("option", { value: NEW_PAGE_VALUE, children: labels.newPageOption })
|
|
3607
|
-
]
|
|
3608
|
-
}
|
|
3609
|
-
)
|
|
3610
|
-
] }),
|
|
3611
|
-
!lock.hide && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3612
|
-
"button",
|
|
3787
|
+
editItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3788
|
+
WidgetEditMenu,
|
|
3613
3789
|
{
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
"button",
|
|
3617
|
-
"dwt-button",
|
|
3618
|
-
"dwt-icon-button"
|
|
3619
|
-
),
|
|
3620
|
-
"aria-label": labels.hide(title),
|
|
3621
|
-
title: labels.hide(title),
|
|
3622
|
-
onClick: () => changePage(hideWidget(view, key)),
|
|
3623
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xD7" })
|
|
3790
|
+
label: labels.arrangeWidget(title),
|
|
3791
|
+
items: editItems
|
|
3624
3792
|
}
|
|
3625
3793
|
)
|
|
3626
3794
|
] }) : void 0;
|