@dnax/ui 0.0.30 → 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.
@@ -447,13 +447,11 @@ watch(open, (v) => {
447
447
  aria-hidden="true"
448
448
  />
449
449
  </div>
450
- <div v-if="error" class="q-field__bottom">
451
- <div class="q-field__error">
450
+ <div class="q-field__bottom">
451
+ <div v-if="error" class="q-field__error">
452
452
  <slot name="error">{{ errorMessage }}</slot>
453
453
  </div>
454
- </div>
455
- <div v-else-if="hint || $slots.hint" class="q-field__bottom">
456
- <div class="q-field__hint">
454
+ <div v-else-if="hint || $slots.hint" class="q-field__hint">
457
455
  <slot name="hint">{{ hint }}</slot>
458
456
  </div>
459
457
  </div>
@@ -195,11 +195,9 @@ onBeforeUnmount(() => {
195
195
  </button>
196
196
  <ChevronDown class="q-select__arrow" :class="{ 'q-select__arrow--rotated': open }" aria-hidden="true" />
197
197
  </div>
198
- <div v-if="error" class="q-field__bottom">
199
- <div class="q-field__error">{{ errorMessage }}</div>
200
- </div>
201
- <div v-else-if="hint" class="q-field__bottom">
202
- <div class="q-field__hint">{{ hint }}</div>
198
+ <div class="q-field__bottom">
199
+ <div v-if="error" class="q-field__error">{{ errorMessage }}</div>
200
+ <div v-else-if="hint" class="q-field__hint">{{ hint }}</div>
203
201
  </div>
204
202
 
205
203
  <Teleport to="body">
@@ -588,13 +588,11 @@ const sheetClass = computed(() => [`q-select__sheet--${props.mode}`, modeOptions
588
588
  <slot name="append" />
589
589
  </div>
590
590
 
591
- <div v-if="error" class="q-field__bottom">
592
- <div class="q-field__error">
591
+ <div class="q-field__bottom">
592
+ <div v-if="error" class="q-field__error">
593
593
  <slot name="error">{{ errorMessage }}</slot>
594
594
  </div>
595
- </div>
596
- <div v-else-if="hint || $slots.hint" class="q-field__bottom">
597
- <div class="q-field__hint">
595
+ <div v-else-if="hint || $slots.hint" class="q-field__hint">
598
596
  <slot name="hint">{{ hint }}</slot>
599
597
  </div>
600
598
  </div>
@@ -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.30",
3
+ "version": "0.0.32",
4
4
  "module": "index.ts",
5
5
  "description": "UI design System",
6
6
  "type": "module",