@leavepulse/ui 0.18.1 → 0.18.3

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.
@@ -38,11 +38,17 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
38
38
  const flatItems = computed(
39
39
  () => props.sections ? props.sections.flatMap((s) => s.items) : props.items ?? []
40
40
  );
41
- function defaultActive(item) {
42
- if (props.path == null) return item.id === props.modelValue;
41
+ function matchesPath(item) {
43
42
  if (item.id === "/") return props.path === "/";
44
43
  return props.path === item.id || props.path.startsWith(`${item.id}/`);
45
44
  }
45
+ function defaultActive(item) {
46
+ if (props.path == null) return item.id === props.modelValue;
47
+ if (!matchesPath(item)) return false;
48
+ return !flatItems.value.some(
49
+ (other) => other.id !== item.id && other.id.length > item.id.length && matchesPath(other)
50
+ );
51
+ }
46
52
  const activeTest = computed(() => props.isActive ?? defaultActive);
47
53
  const pageTitle = computed(() => {
48
54
  if (props.title != null) return props.title;
@@ -1,4 +1,4 @@
1
- import { _ as _sfc_main } from "../chunks/LpAppShell-CiHAD6PN.js";
1
+ import { _ as _sfc_main } from "../chunks/LpAppShell-BvAVgVLW.js";
2
2
  export {
3
3
  _sfc_main as default
4
4
  };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { _ as _2 } from "./chunks/LpAddressInput-Dfyn88Dd.js";
3
3
  import { _ as _3 } from "./chunks/LpMapPicker-DFKrd1Ne.js";
4
4
  import { OSM_TILES, createNominatimProvider, emptyAddress, formatAddress, project, tileUrl, unproject } from "./components/address.js";
5
5
  import { _ as _4 } from "./chunks/LpAlert-BAYHDSS1.js";
6
- import { _ as _5 } from "./chunks/LpAppShell-CiHAD6PN.js";
6
+ import { _ as _5 } from "./chunks/LpAppShell-BvAVgVLW.js";
7
7
  import { _ as _6 } from "./chunks/LpAutocomplete-DIgXmtCA.js";
8
8
  import { _ as _7 } from "./chunks/LpAvatar-B1Ez0ZAx.js";
9
9
  import { _ as _8 } from "./chunks/LpBadge-CXzBPnwO.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@leavepulse/ui",
3
- "version": "0.18.1",
3
+ "version": "0.18.3",
4
4
  "type": "module",
5
5
  "description": "LeavePulse token-driven Vue component kit.",
6
6
  "repository": {
@@ -83,10 +83,23 @@ const flatItems = computed<SidebarItem[]>(() =>
83
83
 
84
84
  // Default active test: exact match for "/", prefix match (on a segment
85
85
  // boundary) otherwise — so "/billing" doesn't light up on "/billing-x".
86
+ function matchesPath(item: SidebarItem): boolean {
87
+ if (item.id === "/") return props.path === "/"
88
+ return props.path === item.id || props.path!.startsWith(`${item.id}/`)
89
+ }
90
+
91
+ // Only the LONGEST match lights up. A parent whose id prefixes its children —
92
+ // "/dcim" over "/dcim/power" — otherwise stays lit alongside whichever child is
93
+ // open, and two highlighted items read as two current pages.
86
94
  function defaultActive(item: SidebarItem): boolean {
87
95
  if (props.path == null) return item.id === props.modelValue
88
- if (item.id === "/") return props.path === "/"
89
- return props.path === item.id || props.path.startsWith(`${item.id}/`)
96
+ if (!matchesPath(item)) return false
97
+ return !flatItems.value.some(
98
+ (other) =>
99
+ other.id !== item.id &&
100
+ other.id.length > item.id.length &&
101
+ matchesPath(other),
102
+ )
90
103
  }
91
104
  const activeTest = computed(() => props.isActive ?? defaultActive)
92
105
 
@@ -16,11 +16,9 @@
16
16
  * holds the full token values, including themes the server cannot name — keeps
17
17
  * winning.
18
18
  */
19
- // Imported through the package barrel on purpose. This file is shipped as
20
- // source and compiled by the CONSUMING app, where "@leavepulse/ui" resolves to
21
- // dist — the same module instance the kit's components use. A relative "../theme/…"
22
- // would load a second copy of the theme singleton from src/, leaving components
23
- // subscribed to a different reactive state than the one this plugin drives.
19
+ // Through the barrel, not "../theme/…": this file is compiled by the consuming
20
+ // app, where the barrel resolves to the same dist instance the components use.
21
+ // A relative path would load a second copy of the theme singleton.
24
22
  import {
25
23
  bootstrapTheme,
26
24
  leavepulse,
@@ -30,10 +28,6 @@ import {
30
28
  themeToCssRule,
31
29
  type TokenSet,
32
30
  } from "@leavepulse/ui"
33
- // "#imports" is Nuxt's virtual module: it resolves in the consuming app, which
34
- // is what compiles this file. (No @ts-expect-error here — the kit's own build
35
- // excludes src/runtime, so the directive would be unused there and error in the
36
- // consumer, where the import type-checks fine.)
37
31
  import { defineNuxtPlugin, useCookie, useHead, useRuntimeConfig } from "#imports"
38
32
 
39
33
  export default defineNuxtPlugin(() => {
@@ -45,8 +39,6 @@ export default defineNuxtPlugin(() => {
45
39
  const fallback =
46
40
  themes.find((theme) => theme.name === options.defaultTheme) ?? leavepulse
47
41
 
48
- // Read-only here: the cookie is written by cacheTheme() in the browser, which
49
- // is the one place a theme choice is recorded.
50
42
  const cookie = useCookie<string | null>(THEME_COOKIE, { readonly: true })
51
43
  const initial = themeFromCookie(cookie.value, themes) ?? fallback
52
44