@dnax/ui 0.0.31 → 0.0.32

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.
@@ -1,16 +1,26 @@
1
1
  <script setup lang="ts">
2
2
  // QSidebarMenuButton — bouton/lien de menu (équivalent SidebarMenuButton).
3
+ // Avec `to`, le bouton devient un lien routeur : navigation au clic + état actif
4
+ // automatique selon la route courante (pattern QRouteTab).
3
5
  import { computed } from "vue"
4
6
  import { Icon } from "@iconify/vue"
5
7
  import { cn } from "../lib/utils"
8
+ import { useRoute, useRouter } from "vue-router"
9
+ import type { RouteLocationRaw } from "vue-router"
6
10
 
7
11
  interface Props {
8
12
  label?: string
9
13
  /** Icône Iconify (ex. : "lucide:settings") */
10
14
  icon?: string
11
- /** Lien natif (<a>) ; sinon bouton */
15
+ /** Lien natif (<a href>) — sans routeur */
12
16
  href?: string
13
- /** État actif */
17
+ /** Destination routeur : rend un lien et active le bouton selon la route courante */
18
+ to?: RouteLocationRaw
19
+ /** Match exact (path + hash) — sinon préfixe de segment de chemin */
20
+ exact?: boolean
21
+ /** router.replace au lieu de router.push */
22
+ replace?: boolean
23
+ /** État actif manuel (ignoré quand `to` est fourni — l'activation suit la route) */
14
24
  active?: boolean
15
25
  activeClass?: string
16
26
  disable?: boolean
@@ -20,35 +30,75 @@ interface Props {
20
30
 
21
31
  const props = withDefaults(defineProps<Props>(), {
22
32
  active: false,
33
+ exact: false,
34
+ replace: false,
23
35
  activeClass: "",
24
36
  disable: false,
25
37
  })
26
38
 
27
39
  const emit = defineEmits<{ click: [event: MouseEvent] }>()
28
40
 
41
+ // Routeur optionnel : sans router installé, `to` dégrade en simple bouton (@click)
42
+ let router: ReturnType<typeof useRouter> | undefined
43
+ let route: ReturnType<typeof useRoute> | undefined
44
+ try {
45
+ router = useRouter()
46
+ route = useRoute()
47
+ }
48
+ catch {
49
+ router = undefined
50
+ route = undefined
51
+ }
52
+
53
+ // La route courante matche-t-elle `to` ? (même logique que QRouteTab)
54
+ const matches = computed(() => {
55
+ if (!router || !route || !props.to) return false
56
+ const resolved = router.resolve(props.to)
57
+ if (props.exact) {
58
+ return resolved.path === route.path && resolved.hash === route.hash
59
+ }
60
+ const prefix = resolved.path.endsWith("/") ? resolved.path : resolved.path + "/"
61
+ return route.path === resolved.path || route.path.startsWith(prefix)
62
+ })
63
+
64
+ const effectiveActive = computed(() => (props.to ? matches.value : props.active))
65
+
66
+ const resolvedHref = computed(() => {
67
+ if (props.href) return props.href
68
+ if (props.to && router) return router.resolve(props.to).href
69
+ return undefined
70
+ })
71
+
72
+ const tag = computed(() => (resolvedHref.value ? "a" : "button"))
73
+
29
74
  const buttonClasses = computed(() =>
30
75
  cn(
31
76
  "q-sidebar__menu-button",
32
- props.active && "q-sidebar__menu-button--active",
33
- props.active && props.activeClass,
77
+ effectiveActive.value && "q-sidebar__menu-button--active",
78
+ effectiveActive.value && props.activeClass,
34
79
  props.disable && "q-sidebar__menu-button--disabled",
35
80
  ),
36
81
  )
37
82
 
38
83
  const onClick = (e: MouseEvent) => {
39
84
  if (props.disable) return
85
+ if (props.to && router && !e.defaultPrevented) {
86
+ e.preventDefault()
87
+ if (props.replace) router.replace(props.to)
88
+ else router.push(props.to)
89
+ }
40
90
  emit("click", e)
41
91
  }
42
92
  </script>
43
93
 
44
94
  <template>
45
95
  <component
46
- :is="href ? 'a' : 'button'"
47
- :href="href || undefined"
48
- :disabled="href ? undefined : disable"
96
+ :is="tag"
97
+ :href="resolvedHref"
98
+ :disabled="tag === 'button' ? disable : undefined"
49
99
  class="q-sidebar__menu-button"
50
100
  :class="buttonClasses"
51
- :aria-current="active ? 'page' : undefined"
101
+ :aria-current="effectiveActive ? 'page' : undefined"
52
102
  @click="onClick"
53
103
  >
54
104
  <Icon :icon="icon" v-if="icon" class="q-sidebar__menu-button-icon" aria-hidden="true" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dnax/ui",
3
- "version": "0.0.31",
3
+ "version": "0.0.32",
4
4
  "module": "index.ts",
5
5
  "description": "UI design System",
6
6
  "type": "module",