@richardmcquiston01/dashboard-widgets-toolkit 0.11.2 → 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.d.cts CHANGED
@@ -208,7 +208,13 @@ interface DashboardLabels {
208
208
  readonly confirmDeletePage: (title: string) => string;
209
209
  readonly movePageLeft: (title: string) => string;
210
210
  readonly movePageRight: (title: string) => string;
211
- /** The select on each card that moves it to another page. */
211
+ /** The icon on each card, while editing, that opens its menu of moves. */
212
+ readonly arrangeWidget: (title: string) => string;
213
+ /** Short text of the menu's items (the full names are `moveEarlier` and so on). */
214
+ readonly menuMoveEarlier: string;
215
+ readonly menuMoveLater: string;
216
+ readonly menuHide: string;
217
+ /** The card menu's heading over the pages a widget can move to. */
212
218
  readonly moveToPage: (title: string) => string;
213
219
  readonly moveToPagePlaceholder: string;
214
220
  readonly moveToPageOption: (title: string, rowsFree: number) => string;
package/dist/react.d.ts CHANGED
@@ -208,7 +208,13 @@ interface DashboardLabels {
208
208
  readonly confirmDeletePage: (title: string) => string;
209
209
  readonly movePageLeft: (title: string) => string;
210
210
  readonly movePageRight: (title: string) => string;
211
- /** The select on each card that moves it to another page. */
211
+ /** The icon on each card, while editing, that opens its menu of moves. */
212
+ readonly arrangeWidget: (title: string) => string;
213
+ /** Short text of the menu's items (the full names are `moveEarlier` and so on). */
214
+ readonly menuMoveEarlier: string;
215
+ readonly menuMoveLater: string;
216
+ readonly menuHide: string;
217
+ /** The card menu's heading over the pages a widget can move to. */
212
218
  readonly moveToPage: (title: string) => string;
213
219
  readonly moveToPagePlaceholder: string;
214
220
  readonly moveToPageOption: (title: string, rowsFree: number) => string;
package/dist/react.js CHANGED
@@ -823,6 +823,10 @@ var DEFAULT_LABELS = {
823
823
  confirmDeletePage: (title) => `Delete the page "${title}" and move its widgets to another page?`,
824
824
  movePageLeft: (title) => `Move ${title} page left`,
825
825
  movePageRight: (title) => `Move ${title} page right`,
826
+ arrangeWidget: (title) => `Arrange ${title}`,
827
+ menuMoveEarlier: "Move earlier",
828
+ menuMoveLater: "Move later",
829
+ menuHide: "Hide",
826
830
  moveToPage: (title) => `Move ${title} to another page`,
827
831
  moveToPagePlaceholder: "Move to page\u2026",
828
832
  moveToPageOption: (title, rowsFree) => `${title} (${rowsFree} ${rowsFree === 1 ? "row" : "rows"} free)`,
@@ -2418,22 +2422,23 @@ function moveWidgetToPage(definitions, layout, widgetKey, targetKey, options = {
2418
2422
  }
2419
2423
  return ok(moved);
2420
2424
  }
2421
- function MoveToPageMenu({
2425
+ var EditMenuInitialOpenContext = createContext(false);
2426
+ var ITEM_SELECTOR = '[role="menuitem"]:not(:disabled)';
2427
+ function WidgetEditMenu({
2422
2428
  label,
2423
- heading,
2424
- options,
2425
- onPick,
2426
- initialOpen = false
2429
+ items,
2430
+ initialOpen
2427
2431
  }) {
2428
2432
  const slot = useSlotClassName();
2433
+ const startOpen = useContext(EditMenuInitialOpenContext);
2429
2434
  const menuId = useId();
2430
- const [open, setOpen] = useState(initialOpen);
2435
+ const [open, setOpen] = useState(initialOpen ?? startOpen);
2431
2436
  const wrapper = useRef(null);
2432
2437
  const button = useRef(null);
2433
2438
  const menu = useRef(null);
2434
2439
  useEffect(() => {
2435
2440
  if (!open) return void 0;
2436
- menu.current?.querySelector('[role="menuitem"]')?.focus();
2441
+ menu.current?.querySelector(ITEM_SELECTOR)?.focus();
2437
2442
  const onPointerDown = (event) => {
2438
2443
  if (!wrapper.current?.contains(event.target)) setOpen(false);
2439
2444
  };
@@ -2450,28 +2455,29 @@ function MoveToPageMenu({
2450
2455
  close(true);
2451
2456
  return;
2452
2457
  }
2453
- const items = [
2454
- ...menu.current?.querySelectorAll('[role="menuitem"]') ?? []
2458
+ const enabled = [
2459
+ ...menu.current?.querySelectorAll(ITEM_SELECTOR) ?? []
2455
2460
  ];
2456
- const current = items.indexOf(
2461
+ if (enabled.length === 0) return;
2462
+ const current = enabled.indexOf(
2457
2463
  document.activeElement
2458
2464
  );
2459
2465
  let next;
2460
- if (event.key === "ArrowDown") next = (current + 1) % items.length;
2466
+ if (event.key === "ArrowDown") next = (current + 1) % enabled.length;
2461
2467
  else if (event.key === "ArrowUp") {
2462
- next = (current - 1 + items.length) % items.length;
2468
+ next = (current - 1 + enabled.length) % enabled.length;
2463
2469
  } else if (event.key === "Home") next = 0;
2464
- else if (event.key === "End") next = items.length - 1;
2470
+ else if (event.key === "End") next = enabled.length - 1;
2465
2471
  if (next !== void 0) {
2466
2472
  event.preventDefault();
2467
- items[next]?.focus();
2473
+ enabled[next]?.focus();
2468
2474
  }
2469
2475
  }
2470
2476
  return /* @__PURE__ */ jsxs(
2471
2477
  "span",
2472
2478
  {
2473
2479
  ref: wrapper,
2474
- className: "dwt-move-menu",
2480
+ className: "dwt-edit-menu",
2475
2481
  onBlur: (event) => {
2476
2482
  if (!event.currentTarget.contains(event.relatedTarget)) {
2477
2483
  setOpen(false);
@@ -2493,18 +2499,18 @@ function MoveToPageMenu({
2493
2499
  children: /* @__PURE__ */ jsx(
2494
2500
  "svg",
2495
2501
  {
2496
- viewBox: "0 0 16 16",
2497
- width: "14",
2498
- height: "14",
2502
+ viewBox: "0 0 24 24",
2503
+ width: "16",
2504
+ height: "16",
2499
2505
  "aria-hidden": "true",
2500
2506
  focusable: "false",
2501
2507
  children: /* @__PURE__ */ jsx(
2502
2508
  "path",
2503
2509
  {
2504
- d: "M2 8h8M7 5l3 3-3 3M13 3v10",
2510
+ d: "M5 9l-3 3 3 3M9 5l3-3 3 3M15 19l-3 3-3-3M19 9l3 3-3 3M2 12h20M12 2v20",
2505
2511
  fill: "none",
2506
2512
  stroke: "currentColor",
2507
- strokeWidth: "1.5",
2513
+ strokeWidth: "2",
2508
2514
  strokeLinecap: "round",
2509
2515
  strokeLinejoin: "round"
2510
2516
  }
@@ -2513,32 +2519,41 @@ function MoveToPageMenu({
2513
2519
  )
2514
2520
  }
2515
2521
  ),
2516
- open && /* @__PURE__ */ jsxs(
2522
+ open && /* @__PURE__ */ jsx(
2517
2523
  "div",
2518
2524
  {
2519
2525
  ref: menu,
2520
2526
  id: menuId,
2521
- className: "dwt-move-popover",
2527
+ className: "dwt-edit-popover",
2522
2528
  role: "menu",
2523
- "aria-label": heading,
2529
+ "aria-label": label,
2524
2530
  onKeyDown,
2525
- children: [
2526
- /* @__PURE__ */ jsx("p", { className: "dwt-move-heading", "aria-hidden": "true", children: heading }),
2527
- options.map((option) => /* @__PURE__ */ jsx(
2531
+ children: items.map(
2532
+ (item) => item.kind === "heading" ? /* @__PURE__ */ jsx(
2533
+ "p",
2534
+ {
2535
+ className: "dwt-edit-heading",
2536
+ role: "presentation",
2537
+ children: item.label
2538
+ },
2539
+ item.key
2540
+ ) : /* @__PURE__ */ jsx(
2528
2541
  "button",
2529
2542
  {
2530
2543
  type: "button",
2531
2544
  role: "menuitem",
2532
- className: "dwt-move-option",
2545
+ className: "dwt-edit-option",
2546
+ ...item.ariaLabel === void 0 ? {} : { "aria-label": item.ariaLabel },
2547
+ disabled: item.disabled === true,
2533
2548
  onClick: () => {
2534
2549
  close(false);
2535
- onPick(option.value);
2550
+ item.onSelect();
2536
2551
  },
2537
- children: option.label
2552
+ children: item.label
2538
2553
  },
2539
- option.value
2540
- ))
2541
- ]
2554
+ item.key
2555
+ )
2556
+ )
2542
2557
  }
2543
2558
  )
2544
2559
  ]
@@ -3667,6 +3682,64 @@ function DashboardInner({
3667
3682
  const lockLabel = overrideLocks ? labels.lockedForViewers(title) : labels.locked(title);
3668
3683
  const canMoveEarlier = !lock.move && moveWidgetBy(pageDefs, view, key, -1) !== view;
3669
3684
  const canMoveLater = !lock.move && moveWidgetBy(pageDefs, view, key, 1) !== view;
3685
+ const pageTargets = paged && !lock.move ? [
3686
+ {
3687
+ kind: "heading",
3688
+ key: "page-heading",
3689
+ label: labels.moveToPagePlaceholder
3690
+ },
3691
+ ...pages.filter((page) => page.key !== activeKey).map((page) => ({
3692
+ kind: "action",
3693
+ key: `page:${page.key}`,
3694
+ label: labels.moveToPageOption(
3695
+ page.title,
3696
+ pageRoom(definitions, layout, page.key, roomOptions)?.rowsFree ?? 0
3697
+ ),
3698
+ ariaLabel: labels.moveToPageOption(
3699
+ page.title,
3700
+ pageRoom(definitions, layout, page.key, roomOptions)?.rowsFree ?? 0
3701
+ ),
3702
+ onSelect: () => moveWidgetAction(key, page.key)
3703
+ })),
3704
+ ...maxPages === void 0 || pages.length < maxPages ? [
3705
+ {
3706
+ kind: "action",
3707
+ key: "page:new",
3708
+ label: labels.newPageOption,
3709
+ onSelect: () => moveWidgetAction(key, NEW_PAGE_VALUE)
3710
+ }
3711
+ ] : []
3712
+ ] : [];
3713
+ const editItems = [
3714
+ ...lock.move ? [] : [
3715
+ {
3716
+ kind: "action",
3717
+ key: "earlier",
3718
+ label: labels.menuMoveEarlier,
3719
+ ariaLabel: labels.moveEarlier(title),
3720
+ disabled: index === 0 || !canMoveEarlier,
3721
+ onSelect: () => changePage(moveWidgetBy(pageDefs, view, key, -1))
3722
+ },
3723
+ {
3724
+ kind: "action",
3725
+ key: "later",
3726
+ label: labels.menuMoveLater,
3727
+ ariaLabel: labels.moveLater(title),
3728
+ disabled: index === shown.length - 1 || !canMoveLater,
3729
+ onSelect: () => changePage(moveWidgetBy(pageDefs, view, key, 1))
3730
+ }
3731
+ ],
3732
+ ...pageTargets,
3733
+ ...lock.hide ? [] : [
3734
+ {
3735
+ kind: "action",
3736
+ key: "hide",
3737
+ label: labels.menuHide,
3738
+ ariaLabel: labels.hide(title),
3739
+ onSelect: () => changePage(hideWidget(view, key))
3740
+ }
3741
+ ]
3742
+ ];
3670
3743
  const actions = controlsShown ? /* @__PURE__ */ jsxs(Fragment, { children: [
3671
3744
  isLocked && /* @__PURE__ */ jsx(
3672
3745
  "span",
@@ -3709,81 +3782,11 @@ function DashboardInner({
3709
3782
  )
3710
3783
  }
3711
3784
  ),
3712
- !lock.move && /* @__PURE__ */ jsxs(Fragment, { children: [
3713
- /* @__PURE__ */ jsx(
3714
- "button",
3715
- {
3716
- type: "button",
3717
- className: slot(
3718
- "button",
3719
- "dwt-button",
3720
- "dwt-icon-button"
3721
- ),
3722
- "aria-label": labels.moveEarlier(title),
3723
- title: labels.moveEarlier(title),
3724
- disabled: index === 0 || !canMoveEarlier,
3725
- onClick: () => changePage(moveWidgetBy(pageDefs, view, key, -1)),
3726
- children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2191" })
3727
- }
3728
- ),
3729
- /* @__PURE__ */ jsx(
3730
- "button",
3731
- {
3732
- type: "button",
3733
- className: slot(
3734
- "button",
3735
- "dwt-button",
3736
- "dwt-icon-button"
3737
- ),
3738
- "aria-label": labels.moveLater(title),
3739
- title: labels.moveLater(title),
3740
- disabled: index === shown.length - 1 || !canMoveLater,
3741
- onClick: () => changePage(moveWidgetBy(pageDefs, view, key, 1)),
3742
- children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\u2193" })
3743
- }
3744
- ),
3745
- paged && /* @__PURE__ */ jsx(
3746
- MoveToPageMenu,
3747
- {
3748
- label: labels.moveToPage(title),
3749
- heading: labels.moveToPagePlaceholder,
3750
- onPick: (pageKey) => moveWidgetAction(key, pageKey),
3751
- options: [
3752
- ...pages.filter((page) => page.key !== activeKey).map((page) => ({
3753
- value: page.key,
3754
- label: labels.moveToPageOption(
3755
- page.title,
3756
- pageRoom(
3757
- definitions,
3758
- layout,
3759
- page.key,
3760
- roomOptions
3761
- )?.rowsFree ?? 0
3762
- )
3763
- })),
3764
- ...maxPages === void 0 || pages.length < maxPages ? [
3765
- {
3766
- value: NEW_PAGE_VALUE,
3767
- label: labels.newPageOption
3768
- }
3769
- ] : []
3770
- ]
3771
- }
3772
- )
3773
- ] }),
3774
- !lock.hide && /* @__PURE__ */ jsx(
3775
- "button",
3785
+ editItems.length > 0 && /* @__PURE__ */ jsx(
3786
+ WidgetEditMenu,
3776
3787
  {
3777
- type: "button",
3778
- className: slot(
3779
- "button",
3780
- "dwt-button",
3781
- "dwt-icon-button"
3782
- ),
3783
- "aria-label": labels.hide(title),
3784
- title: labels.hide(title),
3785
- onClick: () => changePage(hideWidget(view, key)),
3786
- children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xD7" })
3788
+ label: labels.arrangeWidget(title),
3789
+ items: editItems
3787
3790
  }
3788
3791
  )
3789
3792
  ] }) : void 0;