@revenexx/studio-shared 0.4.1 → 0.4.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/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "studio-shared",
3
3
  "configKey": "studioShared",
4
- "version": "0.4.1",
4
+ "version": "0.4.2",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "unknown"
@@ -4,7 +4,7 @@
4
4
 
5
5
  <script setup>
6
6
  import { SidebarMinimalistic as CollapseIcon } from "#solar-icons";
7
- import { SIDEBAR_BEST_MATCH, sidebarBestMatch, sidebarItemKey } from "../../lib/sidebarNav";
7
+ import { SIDEBAR_BEST_MATCH, sidebarBestMatch, sidebarItemKey, sidebarRevealScrollTop } from "../../lib/sidebarNav";
8
8
  import SidebarNavLink from "./SidebarNavLink.vue";
9
9
  import SidebarNavAreas from "./SidebarNavAreas.vue";
10
10
  const props = defineProps({
@@ -24,8 +24,11 @@ const scroller = ref(null);
24
24
  const route = useRoute();
25
25
  function revealCurrent() {
26
26
  nextTick(() => {
27
- const row = scroller.value?.querySelector("[data-nav-current]");
28
- row?.scrollIntoView({ block: "nearest" });
27
+ const view = scroller.value;
28
+ const row = view?.querySelector("[data-nav-current]");
29
+ if (!view || !row) return;
30
+ const next = sidebarRevealScrollTop(view.getBoundingClientRect(), row.getBoundingClientRect(), view.scrollTop);
31
+ if (next !== view.scrollTop) view.scrollTop = next;
29
32
  });
30
33
  }
31
34
  provide(SIDEBAR_BEST_MATCH, computed(() => sidebarBestMatch(props.sections, route.fullPath)));
@@ -51,3 +51,21 @@ export declare function sidebarItemIsCurrent(item: SidebarNavItem, path: string,
51
51
  * section (Settings, Apps, …) from rendering a dead row.
52
52
  */
53
53
  export declare function sidebarItemTarget(item: SidebarNavItem): string | undefined;
54
+ /** A box on screen, as `getBoundingClientRect` reports it — only what the sum needs. */
55
+ interface VerticalBox {
56
+ top: number;
57
+ height: number;
58
+ }
59
+ /**
60
+ * Where the sidebar's scroller has to stand for the current row to be in sight,
61
+ * moving as little as possible: the row's top edge when it sits above the view,
62
+ * its bottom edge when below, and nowhere when it is already visible.
63
+ *
64
+ * This is `scrollIntoView({ block: 'nearest' })` done by hand. The call itself is
65
+ * not usable here: Chrome also moves the point the next Tab starts from to the row
66
+ * it scrolled to, so after a page load the first Tab skipped the host's
67
+ * *Skip to content* and everything before the current row (IN-55). Setting the
68
+ * scroller's `scrollTop` moves the list and leaves the keyboard where it was.
69
+ */
70
+ export declare function sidebarRevealScrollTop(view: VerticalBox, row: VerticalBox, scrollTop: number): number;
71
+ export {};
@@ -39,3 +39,10 @@ export function sidebarItemTarget(item) {
39
39
  }
40
40
  return void 0;
41
41
  }
42
+ export function sidebarRevealScrollTop(view, row, scrollTop) {
43
+ const top = row.top - view.top + scrollTop;
44
+ const bottom = top + row.height;
45
+ if (top < scrollTop) return top;
46
+ if (bottom > scrollTop + view.height) return Math.min(top, bottom - view.height);
47
+ return scrollTop;
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@revenexx/studio-shared",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "description": "Shared revenexx Studio shell primitives (PageHeader, SidebarNav, StateCard, DataTable, …) + the platform provider contract (usePlatformAuth/usePlatformTenant). A Nuxt module — add it to `modules`.",
6
6
  "main": "./dist/module.mjs",