@richardmcquiston01/dashboard-widgets-toolkit 0.11.0 → 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
@@ -1574,6 +1574,12 @@ function InteractiveTable({
1574
1574
  const searchId = react.useId();
1575
1575
  const [search, setSearch] = react.useState("");
1576
1576
  const [sort, setSort] = react.useState(initialSort);
1577
+ const seed = initialSort === void 0 ? "" : `${initialSort.column}:${initialSort.direction}`;
1578
+ const [seededWith, setSeededWith] = react.useState(seed);
1579
+ if (seededWith !== seed) {
1580
+ setSeededWith(seed);
1581
+ setSort(initialSort);
1582
+ }
1577
1583
  const localeTag = typeof locale === "string" ? locale : locale?.[0];
1578
1584
  const query = {
1579
1585
  page: 1,
@@ -2414,6 +2420,133 @@ function moveWidgetToPage(definitions, layout, widgetKey, targetKey, options = {
2414
2420
  }
2415
2421
  return ok(moved);
2416
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
+ }
2417
2550
  function nextSort(current, column) {
2418
2551
  if (current?.column !== column) return { column, direction: "asc" };
2419
2552
  return current.direction === "asc" ? { column, direction: "desc" } : void 0;
@@ -3137,6 +3270,7 @@ function DashboardInner({
3137
3270
  const [announcement, setAnnouncement] = react.useState("");
3138
3271
  const [pageAnnouncement, setPageAnnouncement] = react.useState("");
3139
3272
  const [pageError, setPageError] = react.useState(void 0);
3273
+ const [newPage, setNewPage] = react.useState(void 0);
3140
3274
  const [pageEditor, setPageEditor] = react.useState(void 0);
3141
3275
  const editorMode = pageEditor?.key === activeKey ? pageEditor.mode : void 0;
3142
3276
  const instanceId = react.useId();
@@ -3167,6 +3301,7 @@ function DashboardInner({
3167
3301
  onActivePageChange?.(pageKey);
3168
3302
  setPageError(void 0);
3169
3303
  setPageEditor(void 0);
3304
+ setNewPage(void 0);
3170
3305
  setPageAnnouncement(
3171
3306
  labels.pageTabName(
3172
3307
  index + 1,
@@ -3184,6 +3319,7 @@ function DashboardInner({
3184
3319
  change(added.value);
3185
3320
  const created = added.value.pages?.at(-1);
3186
3321
  if (created !== void 0) {
3322
+ setNewPage({ key: created.key, activeBefore: activeKey });
3187
3323
  if (activePageProp === void 0) setActiveState(created.key);
3188
3324
  onActivePageChange?.(created.key);
3189
3325
  setPageError(void 0);
@@ -3195,8 +3331,21 @@ function DashboardInner({
3195
3331
  if (!renamed.ok) return renamed.error;
3196
3332
  change(renamed.value);
3197
3333
  setPageEditor(void 0);
3334
+ setNewPage(void 0);
3198
3335
  return void 0;
3199
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
+ }
3200
3349
  function deletePageAction() {
3201
3350
  const index = pages.findIndex((page) => page.key === activeKey);
3202
3351
  const removed = removePage(definitions, layout, activeKey, roomOptions);
@@ -3370,7 +3519,7 @@ function DashboardInner({
3370
3519
  {
3371
3520
  initial: activePage.title,
3372
3521
  onSubmit: renamePageAction,
3373
- onCancel: () => setPageEditor(void 0)
3522
+ onCancel: cancelPageEditor
3374
3523
  },
3375
3524
  activeKey
3376
3525
  ),
@@ -3418,7 +3567,27 @@ function DashboardInner({
3418
3567
  "aria-label": labels.deletePage(activePage.title),
3419
3568
  title: labels.deletePage(activePage.title),
3420
3569
  onClick: () => setPageEditor({ mode: "delete", key: activeKey }),
3421
- 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
+ )
3422
3591
  }
3423
3592
  )
3424
3593
  ] }),
@@ -3575,29 +3744,31 @@ function DashboardInner({
3575
3744
  children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", children: "\u2193" })
3576
3745
  }
3577
3746
  ),
3578
- paged && /* @__PURE__ */ jsxRuntime.jsxs(
3579
- "select",
3747
+ paged && /* @__PURE__ */ jsxRuntime.jsx(
3748
+ MoveToPageMenu,
3580
3749
  {
3581
- className: "dwt-move-select",
3582
- "aria-label": labels.moveToPage(title),
3583
- value: "",
3584
- onChange: (event) => {
3585
- if (event.target.value !== "") {
3586
- moveWidgetAction(key, event.target.value);
3587
- }
3588
- },
3589
- children: [
3590
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: labels.moveToPagePlaceholder }),
3591
- pages.filter((page) => page.key !== activeKey).map((page) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: page.key, children: labels.moveToPageOption(
3592
- page.title,
3593
- pageRoom(
3594
- definitions,
3595
- layout,
3596
- page.key,
3597
- roomOptions
3598
- )?.rowsFree ?? 0
3599
- ) }, page.key)),
3600
- (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
+ ] : []
3601
3772
  ]
3602
3773
  }
3603
3774
  )