@richardmcquiston01/dashboard-widgets-toolkit 0.11.1 → 0.11.2

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 CHANGED
@@ -2420,6 +2420,133 @@ function moveWidgetToPage(definitions, layout, widgetKey, targetKey, options = {
2420
2420
  }
2421
2421
  return ok(moved);
2422
2422
  }
2423
+ function MoveToPageMenu({
2424
+ label,
2425
+ heading,
2426
+ options,
2427
+ onPick,
2428
+ initialOpen = false
2429
+ }) {
2430
+ const slot = useSlotClassName();
2431
+ const menuId = react.useId();
2432
+ const [open, setOpen] = react.useState(initialOpen);
2433
+ const wrapper = react.useRef(null);
2434
+ const button = react.useRef(null);
2435
+ const menu = react.useRef(null);
2436
+ react.useEffect(() => {
2437
+ if (!open) return void 0;
2438
+ menu.current?.querySelector('[role="menuitem"]')?.focus();
2439
+ const onPointerDown = (event) => {
2440
+ if (!wrapper.current?.contains(event.target)) setOpen(false);
2441
+ };
2442
+ document.addEventListener("pointerdown", onPointerDown);
2443
+ return () => document.removeEventListener("pointerdown", onPointerDown);
2444
+ }, [open]);
2445
+ function close(returnFocus) {
2446
+ setOpen(false);
2447
+ if (returnFocus) button.current?.focus();
2448
+ }
2449
+ function onKeyDown(event) {
2450
+ if (event.key === "Escape") {
2451
+ event.stopPropagation();
2452
+ close(true);
2453
+ return;
2454
+ }
2455
+ const items = [
2456
+ ...menu.current?.querySelectorAll('[role="menuitem"]') ?? []
2457
+ ];
2458
+ const current = items.indexOf(
2459
+ document.activeElement
2460
+ );
2461
+ let next;
2462
+ if (event.key === "ArrowDown") next = (current + 1) % items.length;
2463
+ else if (event.key === "ArrowUp") {
2464
+ next = (current - 1 + items.length) % items.length;
2465
+ } else if (event.key === "Home") next = 0;
2466
+ else if (event.key === "End") next = items.length - 1;
2467
+ if (next !== void 0) {
2468
+ event.preventDefault();
2469
+ items[next]?.focus();
2470
+ }
2471
+ }
2472
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2473
+ "span",
2474
+ {
2475
+ ref: wrapper,
2476
+ className: "dwt-move-menu",
2477
+ onBlur: (event) => {
2478
+ if (!event.currentTarget.contains(event.relatedTarget)) {
2479
+ setOpen(false);
2480
+ }
2481
+ },
2482
+ children: [
2483
+ /* @__PURE__ */ jsxRuntime.jsx(
2484
+ "button",
2485
+ {
2486
+ ref: button,
2487
+ type: "button",
2488
+ className: slot("button", "dwt-button", "dwt-icon-button"),
2489
+ "aria-label": label,
2490
+ title: label,
2491
+ "aria-haspopup": "menu",
2492
+ "aria-expanded": open,
2493
+ "aria-controls": open ? menuId : void 0,
2494
+ onClick: () => setOpen((current) => !current),
2495
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2496
+ "svg",
2497
+ {
2498
+ viewBox: "0 0 16 16",
2499
+ width: "14",
2500
+ height: "14",
2501
+ "aria-hidden": "true",
2502
+ focusable: "false",
2503
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2504
+ "path",
2505
+ {
2506
+ d: "M2 8h8M7 5l3 3-3 3M13 3v10",
2507
+ fill: "none",
2508
+ stroke: "currentColor",
2509
+ strokeWidth: "1.5",
2510
+ strokeLinecap: "round",
2511
+ strokeLinejoin: "round"
2512
+ }
2513
+ )
2514
+ }
2515
+ )
2516
+ }
2517
+ ),
2518
+ open && /* @__PURE__ */ jsxRuntime.jsxs(
2519
+ "div",
2520
+ {
2521
+ ref: menu,
2522
+ id: menuId,
2523
+ className: "dwt-move-popover",
2524
+ role: "menu",
2525
+ "aria-label": heading,
2526
+ onKeyDown,
2527
+ children: [
2528
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "dwt-move-heading", "aria-hidden": "true", children: heading }),
2529
+ options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(
2530
+ "button",
2531
+ {
2532
+ type: "button",
2533
+ role: "menuitem",
2534
+ className: "dwt-move-option",
2535
+ onClick: () => {
2536
+ close(false);
2537
+ onPick(option.value);
2538
+ },
2539
+ children: option.label
2540
+ },
2541
+ option.value
2542
+ ))
2543
+ ]
2544
+ }
2545
+ )
2546
+ ]
2547
+ }
2548
+ );
2549
+ }
2423
2550
  function nextSort(current, column) {
2424
2551
  if (current?.column !== column) return { column, direction: "asc" };
2425
2552
  return current.direction === "asc" ? { column, direction: "desc" } : void 0;
@@ -3143,6 +3270,7 @@ function DashboardInner({
3143
3270
  const [announcement, setAnnouncement] = react.useState("");
3144
3271
  const [pageAnnouncement, setPageAnnouncement] = react.useState("");
3145
3272
  const [pageError, setPageError] = react.useState(void 0);
3273
+ const [newPage, setNewPage] = react.useState(void 0);
3146
3274
  const [pageEditor, setPageEditor] = react.useState(void 0);
3147
3275
  const editorMode = pageEditor?.key === activeKey ? pageEditor.mode : void 0;
3148
3276
  const instanceId = react.useId();
@@ -3173,6 +3301,7 @@ function DashboardInner({
3173
3301
  onActivePageChange?.(pageKey);
3174
3302
  setPageError(void 0);
3175
3303
  setPageEditor(void 0);
3304
+ setNewPage(void 0);
3176
3305
  setPageAnnouncement(
3177
3306
  labels.pageTabName(
3178
3307
  index + 1,
@@ -3190,6 +3319,7 @@ function DashboardInner({
3190
3319
  change(added.value);
3191
3320
  const created = added.value.pages?.at(-1);
3192
3321
  if (created !== void 0) {
3322
+ setNewPage({ key: created.key, activeBefore: activeKey });
3193
3323
  if (activePageProp === void 0) setActiveState(created.key);
3194
3324
  onActivePageChange?.(created.key);
3195
3325
  setPageError(void 0);
@@ -3201,8 +3331,21 @@ function DashboardInner({
3201
3331
  if (!renamed.ok) return renamed.error;
3202
3332
  change(renamed.value);
3203
3333
  setPageEditor(void 0);
3334
+ setNewPage(void 0);
3204
3335
  return void 0;
3205
3336
  }
3337
+ function cancelPageEditor() {
3338
+ const fresh = newPage;
3339
+ setPageEditor(void 0);
3340
+ setNewPage(void 0);
3341
+ if (fresh === void 0 || fresh.key !== activeKey) return;
3342
+ const pagesWithout = pages.filter(
3343
+ (page) => page.key !== fresh.key
3344
+ );
3345
+ if (pagesWithout.length === pages.length) return;
3346
+ change({ ...layout, pages: pagesWithout });
3347
+ selectPage(fresh.activeBefore);
3348
+ }
3206
3349
  function deletePageAction() {
3207
3350
  const index = pages.findIndex((page) => page.key === activeKey);
3208
3351
  const removed = removePage(definitions, layout, activeKey, roomOptions);
@@ -3376,7 +3519,7 @@ function DashboardInner({
3376
3519
  {
3377
3520
  initial: activePage.title,
3378
3521
  onSubmit: renamePageAction,
3379
- onCancel: () => setPageEditor(void 0)
3522
+ onCancel: cancelPageEditor
3380
3523
  },
3381
3524
  activeKey
3382
3525
  ),
@@ -3424,7 +3567,27 @@ function DashboardInner({
3424
3567
  "aria-label": labels.deletePage(activePage.title),
3425
3568
  title: labels.deletePage(activePage.title),
3426
3569
  onClick: () => setPageEditor({ mode: "delete", key: activeKey }),
3427
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\xD7" })
3570
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3571
+ "svg",
3572
+ {
3573
+ viewBox: "0 0 16 16",
3574
+ width: "14",
3575
+ height: "14",
3576
+ "aria-hidden": "true",
3577
+ focusable: "false",
3578
+ children: /* @__PURE__ */ jsxRuntime.jsx(
3579
+ "path",
3580
+ {
3581
+ d: "M3 4.5h10M6.5 4.5V3h3v1.5M4.5 4.5l.6 8.5h5.8l.6-8.5M6.8 7v3.5M9.2 7v3.5",
3582
+ fill: "none",
3583
+ stroke: "currentColor",
3584
+ strokeWidth: "1.3",
3585
+ strokeLinecap: "round",
3586
+ strokeLinejoin: "round"
3587
+ }
3588
+ )
3589
+ }
3590
+ )
3428
3591
  }
3429
3592
  )
3430
3593
  ] }),
@@ -3581,29 +3744,31 @@ function DashboardInner({
3581
3744
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2193" })
3582
3745
  }
3583
3746
  ),
3584
- paged && /* @__PURE__ */ jsxRuntime.jsxs(
3585
- "select",
3747
+ paged && /* @__PURE__ */ jsxRuntime.jsx(
3748
+ MoveToPageMenu,
3586
3749
  {
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 })
3750
+ label: labels.moveToPage(title),
3751
+ heading: labels.moveToPagePlaceholder,
3752
+ onPick: (pageKey) => moveWidgetAction(key, pageKey),
3753
+ options: [
3754
+ ...pages.filter((page) => page.key !== activeKey).map((page) => ({
3755
+ value: page.key,
3756
+ label: labels.moveToPageOption(
3757
+ page.title,
3758
+ pageRoom(
3759
+ definitions,
3760
+ layout,
3761
+ page.key,
3762
+ roomOptions
3763
+ )?.rowsFree ?? 0
3764
+ )
3765
+ })),
3766
+ ...maxPages === void 0 || pages.length < maxPages ? [
3767
+ {
3768
+ value: NEW_PAGE_VALUE,
3769
+ label: labels.newPageOption
3770
+ }
3771
+ ] : []
3607
3772
  ]
3608
3773
  }
3609
3774
  )