@afeefa/vue-app 0.0.308 → 0.0.309

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 +1 @@
1
- 0.0.308
1
+ 0.0.309
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@afeefa/vue-app",
3
- "version": "0.0.308",
3
+ "version": "0.0.309",
4
4
  "description": "",
5
5
  "author": "Afeefa Kollektiv <kollektiv@afeefa.de>",
6
6
  "license": "MIT",
@@ -18,6 +18,8 @@
18
18
  <app-bar-title-container class="appBarTitle flex-grow-1" />
19
19
  <app-bar-buttons class="appBarButtons mr-2" />
20
20
  </div>
21
+
22
+ <app-bar-navigation v-if="$config.hasAppBarNavigation" />
21
23
  </div>
22
24
  </template>
23
25
 
@@ -25,13 +27,15 @@
25
27
  import { Component, Vue } from '@a-vue'
26
28
  import AppBarButtons from './app/AppBarButtons'
27
29
  import AppBarTitleContainer from './app/AppBarTitleContainer'
30
+ import AppBarNavigation from './app/AppBarNavigation'
28
31
  import { SidebarEvent } from '@a-admin/events'
29
32
  import { sidebarService } from './sidebar/SidebarService'
30
33
 
31
34
  @Component({
32
35
  components: {
33
36
  AppBarButtons,
34
- AppBarTitleContainer
37
+ AppBarTitleContainer,
38
+ AppBarNavigation
35
39
  }
36
40
  })
37
41
  export default class StickyHeader extends Vue {
@@ -0,0 +1,108 @@
1
+ <template>
2
+ <div
3
+ id="appBarNavigation"
4
+ class="d-flex align-center gap-1"
5
+ >
6
+ <v-btn
7
+ v-for="link in links"
8
+ :key="link.id"
9
+ class="mt-3 mb-n1"
10
+ x-small
11
+ @click="scrollToSection(link.id)"
12
+ >
13
+ {{ link.label }}
14
+ </v-btn>
15
+ </div>
16
+ </template>
17
+
18
+ <script>
19
+ import { Component, Vue } from '@a-vue'
20
+ import { debounce } from '@a-vue/utils/debounce'
21
+
22
+ @Component
23
+ export default class AppBarNavigation extends Vue {
24
+ links = []
25
+
26
+ debounceInitLinks = debounce(this.initLinks, 50) // fire immediately if !value (click clearable-x)
27
+
28
+ mounted () {
29
+ const mutationWatcher = new MutationObserver(mutations => {
30
+ let changed = false
31
+
32
+ for (const m of mutations) {
33
+ // Neue Nodes
34
+ for (const node of m.addedNodes) {
35
+ if (!(node instanceof HTMLElement)) continue
36
+ if (node.matches('.collapsible-section') || node.querySelector('.collapsible-section')) {
37
+ changed = true
38
+ }
39
+ }
40
+
41
+ // Entfernte Nodes
42
+ for (const node of m.removedNodes) {
43
+ if (!(node instanceof HTMLElement)) continue
44
+ if (node.matches('.collapsible-section') || node.querySelector('.collapsible-section')) {
45
+ changed = true
46
+ }
47
+ }
48
+ }
49
+
50
+ if (changed) {
51
+ this.debounceInitLinks()
52
+ }
53
+ })
54
+
55
+ mutationWatcher.observe(document.body, { childList: true, subtree: true })
56
+ }
57
+
58
+ initLinks () {
59
+ const sections = document.querySelectorAll('.collapsible-section')
60
+ console.log(Array.from(sections).map(s => s.getAttribute('label')))
61
+ this.links = Array.from(sections).map(s => {
62
+ const label = s.getAttribute('label')
63
+ const slug = label
64
+ .toLowerCase()
65
+ .replace(/[^\w]+/g, '-') // Sonderzeichen -> Bindestriche
66
+ .replace(/^-+|-+$/g, '') // führende/trailing -
67
+ .substring(0, 50) // Sicherheitslimit
68
+
69
+ s.id = slug
70
+
71
+ return {
72
+ id: s.id,
73
+ label,
74
+ slug
75
+ }
76
+ })
77
+ }
78
+
79
+ scrollToSection (id) {
80
+ const el = document.querySelector(`#${id}`)
81
+ if (!el) return
82
+
83
+ // Scroll-Container auswählen (kann auch this.$refs.scrollContainer sein)
84
+ const container = document.querySelector('#v-main')
85
+ if (!container) return
86
+
87
+ // Abstand in Pixeln (4rem ≈ 64px)
88
+ const offset = 140
89
+
90
+ // Berechne die Scroll-Position relativ zum Container
91
+ const containerTop = container.getBoundingClientRect().top
92
+ const elementTop = el.getBoundingClientRect().top
93
+
94
+ const scrollTarget = container.scrollTop + (elementTop - containerTop) - offset
95
+
96
+ container.scrollTo({
97
+ top: scrollTarget,
98
+ behavior: 'smooth'
99
+ })
100
+
101
+ // // Scroll sanft zur Section
102
+ // el.scrollIntoView({
103
+ // behavior: 'smooth',
104
+ // block: 'start'
105
+ // })
106
+ }
107
+ }
108
+ </script>
@@ -16,7 +16,7 @@
16
16
 
17
17
  <v-icon
18
18
  :color="icon.color"
19
- size="3.5rem"
19
+ size="2.2rem"
20
20
  v-text="icon.icon"
21
21
  />
22
22
 
@@ -6,8 +6,8 @@
6
6
  <template #actionButton>
7
7
  <a-icon
8
8
  v-if="buttonEdit"
9
- size="1.3rem"
10
- class="contextButton mt-n1"
9
+ size="1.6rem"
10
+ class="contextButton"
11
11
  title="Bearbeiten"
12
12
  @click="openModal"
13
13
  >
@@ -16,8 +16,8 @@
16
16
 
17
17
  <a-icon
18
18
  v-if="buttonAdd"
19
- size="1.3rem"
20
- class="contextButton mt-n1"
19
+ size="1.6rem"
20
+ class="contextButton"
21
21
  title="Bearbeiten"
22
22
  @click="openModal"
23
23
  >
@@ -24,7 +24,8 @@ class AdminConfig {
24
24
  }
25
25
 
26
26
  config = {
27
- has2FA: false
27
+ has2FA: false,
28
+ hasAppBarNavigation: false
28
29
  }
29
30
  }
30
31