@cypress-design/vue-docmenu 0.3.0 → 0.4.1
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/.turbo/turbo-build.log +6 -5
- package/CHANGELOG.md +22 -0
- package/DocMenu.vue +40 -11
- package/DocMenuVue.cy.tsx +41 -3
- package/ReadMe.md +21 -22
- package/_DocGroup.vue +63 -72
- package/_DocGroupElements.vue +97 -0
- package/_DocLink.vue +53 -8
- package/dist/DocMenu.vue.d.ts +39 -19
- package/dist/DocMenu.vue.d.ts.map +1 -1
- package/dist/_DocGroup.vue.d.ts +51 -28
- package/dist/_DocGroup.vue.d.ts.map +1 -1
- package/dist/_DocGroupElements.vue.d.ts +43 -0
- package/dist/_DocGroupElements.vue.d.ts.map +1 -0
- package/dist/_DocLink.vue.d.ts +48 -27
- package/dist/_DocLink.vue.d.ts.map +1 -1
- package/dist/index.es.mjs +222 -133
- package/dist/index.es.mjs.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -3
- package/DocMenu.rootstory.tsx +0 -6
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
$ yarn build:module && yarn build:types
|
|
2
2
|
$ yarn vite build
|
|
3
3
|
$ /home/runner/work/cypress-design/cypress-design/node_modules/.bin/vite build
|
|
4
|
-
[
|
|
4
|
+
[33mThe CJS build of Vite's Node API is deprecated. See https://vitejs.dev/guide/troubleshooting.html#vite-cjs-node-api-deprecated for more details.[39m
|
|
5
|
+
[36mvite v5.0.4 [32mbuilding for production...[36m[39m
|
|
5
6
|
transforming...
|
|
6
|
-
[32m✓[39m
|
|
7
|
+
[32m✓[39m 10 modules transformed.
|
|
7
8
|
rendering chunks...
|
|
8
9
|
computing gzip size...
|
|
9
|
-
[2mdist/[22m[36mindex.es.mjs [39m[1m[
|
|
10
|
-
[2mdist/[22m[36mindex.umd.js [39m[1m[
|
|
11
|
-
[32m✓ built in
|
|
10
|
+
[2mdist/[22m[36mindex.es.mjs [39m[1m[2m9.07 kB[22m[1m[22m[2m │ gzip: 2.73 kB[22m[2m │ map: 12.03 kB[22m
|
|
11
|
+
[2mdist/[22m[36mindex.umd.js [39m[1m[2m7.15 kB[22m[1m[22m[2m │ gzip: 2.40 kB[22m[2m │ map: 11.67 kB[22m
|
|
12
|
+
[32m✓ built in 3.08s[39m
|
|
12
13
|
$ yarn vue-tsc --project ./tsconfig.build.json
|
|
13
14
|
$ /home/runner/work/cypress-design/cypress-design/node_modules/.bin/vue-tsc --project ./tsconfig.build.json
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# @cypress-design/vue-docmenu
|
|
2
2
|
|
|
3
|
+
## 0.4.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#353](https://github.com/cypress-io/cypress-design/pull/353) [`b382b9e`](https://github.com/cypress-io/cypress-design/commit/b382b9ecc99e3ab6288eee406831199edb661c19) Thanks [@elevatebart](https://github.com/elevatebart)! - feat: Docgen wrapping active links
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`b382b9e`](https://github.com/cypress-io/cypress-design/commit/b382b9ecc99e3ab6288eee406831199edb661c19)]:
|
|
10
|
+
- @cypress-design/constants-docmenu@0.1.2
|
|
11
|
+
|
|
12
|
+
## 0.4.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- [#350](https://github.com/cypress-io/cypress-design/pull/350) [`abc414d`](https://github.com/cypress-io/cypress-design/commit/abc414da149eb6fe0cfa61497a0aa8630d8d8d6e) Thanks [@elevatebart](https://github.com/elevatebart)! - feat: allow usage of a custom link component
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- [#347](https://github.com/cypress-io/cypress-design/pull/347) [`de67952`](https://github.com/cypress-io/cypress-design/commit/de679522ea2269854ec8ac8de925fcf930ce96e4) Thanks [@elevatebart](https://github.com/elevatebart)! - fix: docmenu docusaurus style items structure
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [[`de67952`](https://github.com/cypress-io/cypress-design/commit/de679522ea2269854ec8ac8de925fcf930ce96e4)]:
|
|
23
|
+
- @cypress-design/constants-docmenu@0.1.1
|
|
24
|
+
|
|
3
25
|
## 0.3.0
|
|
4
26
|
|
|
5
27
|
### Minor Changes
|
package/DocMenu.vue
CHANGED
|
@@ -1,26 +1,55 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { ref, type DefineComponent } from 'vue'
|
|
2
3
|
import { NavGroup, NavItemLink } from '@cypress-design/constants-docmenu'
|
|
3
|
-
import
|
|
4
|
-
import DocLink from './_DocLink.vue'
|
|
4
|
+
import DocGroupElements from './_DocGroupElements.vue'
|
|
5
5
|
|
|
6
6
|
withDefaults(
|
|
7
7
|
defineProps<{
|
|
8
8
|
items: (NavItemLink | NavGroup)[]
|
|
9
|
+
activePath?: string
|
|
9
10
|
collapsible?: boolean
|
|
11
|
+
linkComponent?: DefineComponent | 'a'
|
|
10
12
|
}>(),
|
|
11
13
|
{
|
|
14
|
+
linkComponent: 'a',
|
|
12
15
|
collapsible: true,
|
|
13
|
-
|
|
16
|
+
activePath: undefined,
|
|
17
|
+
},
|
|
14
18
|
)
|
|
19
|
+
|
|
20
|
+
const $container = ref<HTMLDivElement>()
|
|
21
|
+
|
|
22
|
+
const activeTop = ref(0)
|
|
23
|
+
const activeHeight = ref(36)
|
|
24
|
+
const showMarker = ref(false)
|
|
25
|
+
|
|
26
|
+
function updateActiveMarkerPosition({ top, height } = { height: 0, top: 0 }) {
|
|
27
|
+
const containerTop = $container.value?.getBoundingClientRect().top || 0
|
|
28
|
+
activeTop.value = top - containerTop
|
|
29
|
+
activeHeight.value = height
|
|
30
|
+
showMarker.value = true
|
|
31
|
+
}
|
|
15
32
|
</script>
|
|
16
33
|
|
|
17
34
|
<template>
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
<div ref="$container" class="relative">
|
|
36
|
+
<div
|
|
37
|
+
v-if="showMarker && collapsible"
|
|
38
|
+
data-cy="doc-menu-active-marker"
|
|
39
|
+
class="absolute h-[36px] w-[4px] z-50 rounded-full bg-indigo-500 transition-all duration-300 ml-[6.5px] mt-[4px]"
|
|
40
|
+
:style="{
|
|
41
|
+
top: `${activeTop + 4}px`,
|
|
42
|
+
height: `${activeHeight - 8}px`,
|
|
43
|
+
}"
|
|
44
|
+
/>
|
|
45
|
+
<DocGroupElements
|
|
46
|
+
:items="items"
|
|
47
|
+
:active-path="activePath"
|
|
48
|
+
:collapsible="collapsible"
|
|
49
|
+
:link-component="linkComponent"
|
|
50
|
+
:depth="-1"
|
|
51
|
+
@update-active-position="updateActiveMarkerPosition"
|
|
52
|
+
@hide-marker="showMarker = false"
|
|
53
|
+
/>
|
|
54
|
+
</div>
|
|
26
55
|
</template>
|
package/DocMenuVue.cy.tsx
CHANGED
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
/// <reference types="cypress" />
|
|
2
|
+
import { type DefineComponent, defineComponent } from 'vue'
|
|
2
3
|
import { mount } from 'cypress/vue'
|
|
3
4
|
import assertions from '../assertions'
|
|
4
5
|
import type { NavGroup, NavItemLink } from '../constants'
|
|
5
|
-
import
|
|
6
|
+
import DocMenu from './DocMenu.vue'
|
|
7
|
+
|
|
8
|
+
const CustomLinkVue: DefineComponent<{ href: StringConstructor }> =
|
|
9
|
+
defineComponent({
|
|
10
|
+
props: {
|
|
11
|
+
href: String,
|
|
12
|
+
},
|
|
13
|
+
setup(props, { slots }) {
|
|
14
|
+
return () => (
|
|
15
|
+
<div>
|
|
16
|
+
{slots.default?.()} + href: {props.href}
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
},
|
|
20
|
+
})
|
|
6
21
|
|
|
7
22
|
describe('<DocMenu/>', () => {
|
|
8
|
-
|
|
9
|
-
mount(() => <
|
|
23
|
+
it('renders', () => {
|
|
24
|
+
mount(() => <DocMenu items={[{ href: '/foo', label: 'Foo' }]} />)
|
|
25
|
+
cy.get('ul').should('exist')
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
it('renders the custom link components', () => {
|
|
29
|
+
mount(() => (
|
|
30
|
+
<DocMenu
|
|
31
|
+
items={[
|
|
32
|
+
{
|
|
33
|
+
label: 'Baaaaaaz',
|
|
34
|
+
items: [{ label: 'Bar', items: [{ href: '/foo', label: 'Foo' }] }],
|
|
35
|
+
},
|
|
36
|
+
]}
|
|
37
|
+
linkComponent={CustomLinkVue}
|
|
38
|
+
/>
|
|
39
|
+
))
|
|
40
|
+
|
|
41
|
+
cy.findByText('Foo + href: /foo', { selector: 'div' }).should('be.visible')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
function mountStory(items: (NavItemLink | NavGroup)[] = [], activePath = '') {
|
|
45
|
+
mount(() => {
|
|
46
|
+
return <DocMenu items={items} activePath={activePath} />
|
|
47
|
+
})
|
|
10
48
|
}
|
|
11
49
|
assertions(mountStory)
|
|
12
50
|
})
|
package/ReadMe.md
CHANGED
|
@@ -20,57 +20,56 @@ import DocMenu from '@cypress-design/vue-docmenu'
|
|
|
20
20
|
|
|
21
21
|
```vue live
|
|
22
22
|
<DocMenu
|
|
23
|
+
activePath="#group-item-3"
|
|
23
24
|
:items="[
|
|
24
25
|
{
|
|
25
|
-
|
|
26
|
-
href: '#',
|
|
26
|
+
label: 'Get Started',
|
|
27
|
+
href: '#get-started',
|
|
27
28
|
},
|
|
28
29
|
{
|
|
29
|
-
|
|
30
|
+
label: 'Overview',
|
|
30
31
|
items: [
|
|
31
32
|
{
|
|
32
|
-
|
|
33
|
-
href: '#',
|
|
33
|
+
label: 'Overview Item 1',
|
|
34
|
+
href: '#overview-item-1',
|
|
34
35
|
},
|
|
35
36
|
{
|
|
36
|
-
|
|
37
|
-
href: '#',
|
|
38
|
-
active: true,
|
|
37
|
+
label: 'Overview Item 2',
|
|
38
|
+
href: '#overview-item-2',
|
|
39
39
|
},
|
|
40
40
|
],
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
|
-
|
|
43
|
+
label: 'Getting Started',
|
|
44
44
|
items: [
|
|
45
45
|
{
|
|
46
|
-
|
|
47
|
-
href: '#',
|
|
46
|
+
label: 'Item 1',
|
|
47
|
+
href: '#item-1',
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
|
-
|
|
50
|
+
label: 'Group',
|
|
51
51
|
items: [
|
|
52
52
|
{
|
|
53
|
-
|
|
54
|
-
href: '#',
|
|
53
|
+
label: 'Item 1',
|
|
54
|
+
href: '#group-item-1',
|
|
55
55
|
},
|
|
56
56
|
{
|
|
57
|
-
|
|
58
|
-
href: '#',
|
|
57
|
+
label: 'Item 2',
|
|
58
|
+
href: '#group-item-2',
|
|
59
59
|
},
|
|
60
60
|
{
|
|
61
|
-
|
|
62
|
-
href: '#',
|
|
61
|
+
label: 'Item 3',
|
|
62
|
+
href: '#group-item-3',
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
|
-
|
|
66
|
-
href: '#',
|
|
65
|
+
label: 'Item 4',
|
|
66
|
+
href: '#group-item-4',
|
|
67
67
|
},
|
|
68
68
|
],
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
|
-
|
|
71
|
+
label: 'Item 5',
|
|
72
72
|
href: '#',
|
|
73
|
-
active: true,
|
|
74
73
|
},
|
|
75
74
|
],
|
|
76
75
|
},
|
package/_DocGroup.vue
CHANGED
|
@@ -1,63 +1,72 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import { computed,
|
|
2
|
+
import { computed, type DefineComponent, ref, watch, nextTick } from 'vue'
|
|
3
3
|
import { IconChevronDownSmall } from '@cypress-design/vue-icon'
|
|
4
4
|
import { NavGroup, classes } from '@cypress-design/constants-docmenu'
|
|
5
|
-
import
|
|
6
|
-
import DocGroup from './_DocGroup.vue'
|
|
5
|
+
import DocGroupElements from './_DocGroupElements.vue'
|
|
7
6
|
|
|
8
7
|
const props = withDefaults(
|
|
9
8
|
defineProps<{
|
|
10
9
|
group: NavGroup
|
|
10
|
+
activePath?: string
|
|
11
11
|
collapsible: boolean
|
|
12
|
+
linkComponent: DefineComponent | 'a'
|
|
12
13
|
depth?: number
|
|
13
14
|
}>(),
|
|
14
15
|
{
|
|
15
16
|
depth: 0,
|
|
16
|
-
}
|
|
17
|
+
},
|
|
17
18
|
)
|
|
18
19
|
|
|
19
|
-
const open = ref(props.
|
|
20
|
+
const open = ref(props.group.collapsed !== true)
|
|
21
|
+
const $groupElements = ref<typeof DocGroupElements>()
|
|
20
22
|
|
|
21
|
-
const
|
|
23
|
+
const Head = computed(() =>
|
|
24
|
+
props.collapsible ? 'button' : props.group.href ? 'a' : 'div',
|
|
25
|
+
)
|
|
22
26
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
29
|
-
: 0
|
|
30
|
-
})
|
|
27
|
+
const emit = defineEmits<{
|
|
28
|
+
(event: 'updateActivePosition', opts?: { top: number; height: number }): void
|
|
29
|
+
(event: 'hideMarker'): void
|
|
30
|
+
(event: 'updateMarkerPosition'): void
|
|
31
|
+
}>()
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
33
|
+
function hasActiveItemRecursively(items = props.group.items): boolean {
|
|
34
|
+
return items.some((item) => {
|
|
35
|
+
if ('items' in item) {
|
|
36
|
+
return hasActiveItemRecursively(item.items)
|
|
37
|
+
}
|
|
38
|
+
return item.href === props.activePath
|
|
39
|
+
})
|
|
40
|
+
}
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
)
|
|
42
|
+
function reTriggerSetActiveGroup() {
|
|
43
|
+
$groupElements.value?.reTriggerSetActiveGroup()
|
|
44
|
+
}
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
let numberOfGroups = props.group.items.filter(
|
|
45
|
-
(item, index) => !('href' in item) && index < activeIndex
|
|
46
|
-
).length
|
|
46
|
+
const active = computed(() => props.group.href === props.activePath)
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
numberOfGroups--
|
|
53
|
-
return acc + group.height
|
|
54
|
-
}, 0)
|
|
55
|
-
return (activeIndex + groupHeight) * 44
|
|
48
|
+
watch(active, (active) => {
|
|
49
|
+
if (active) {
|
|
50
|
+
emit('hideMarker')
|
|
51
|
+
}
|
|
56
52
|
})
|
|
57
53
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
)
|
|
54
|
+
watch(open, async (open) => {
|
|
55
|
+
await nextTick()
|
|
56
|
+
if (hasActiveItemRecursively()) {
|
|
57
|
+
if (open) {
|
|
58
|
+
reTriggerSetActiveGroup()
|
|
59
|
+
} else {
|
|
60
|
+
emit('hideMarker')
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
emit('updateMarkerPosition')
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
defineExpose({
|
|
68
|
+
reTriggerSetActiveGroup,
|
|
69
|
+
})
|
|
61
70
|
</script>
|
|
62
71
|
|
|
63
72
|
<template>
|
|
@@ -68,14 +77,16 @@ const Head = computed(() =>
|
|
|
68
77
|
{
|
|
69
78
|
[classes.topButton]: depth === 0,
|
|
70
79
|
[classes.leafButton]: depth,
|
|
71
|
-
'text-indigo-500':
|
|
80
|
+
'text-indigo-500': active,
|
|
72
81
|
},
|
|
73
82
|
]"
|
|
74
|
-
:href="
|
|
83
|
+
:href="group.href"
|
|
75
84
|
@click="
|
|
76
85
|
() => {
|
|
77
86
|
if (collapsible) {
|
|
78
87
|
open = !open
|
|
88
|
+
} else {
|
|
89
|
+
emit('updateActivePosition')
|
|
79
90
|
}
|
|
80
91
|
}
|
|
81
92
|
"
|
|
@@ -91,38 +102,18 @@ const Head = computed(() =>
|
|
|
91
102
|
'ml-[16px]': depth,
|
|
92
103
|
}"
|
|
93
104
|
/>
|
|
94
|
-
{{ group.
|
|
105
|
+
{{ group.label }}
|
|
95
106
|
</component>
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
props.collapsible &&
|
|
99
|
-
depth >= 0 &&
|
|
100
|
-
open &&
|
|
101
|
-
group.items.some((item) => 'href' in item && item.active)
|
|
102
|
-
"
|
|
103
|
-
class="absolute h-[36px] w-[4px] z-10 rounded-full bg-indigo-500 transition-all duration-300 ml-[6px] mt-[48px]"
|
|
104
|
-
:style="{
|
|
105
|
-
top: `${activeMarkerTop}px`,
|
|
106
|
-
left: `-${depth === 0 ? 0 : depth * 7.5 + 1}px`,
|
|
107
|
-
}"
|
|
108
|
-
/>
|
|
109
|
-
<ul
|
|
107
|
+
<DocGroupElements
|
|
108
|
+
ref="$groupElements"
|
|
110
109
|
v-show="open"
|
|
111
|
-
|
|
112
|
-
:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
:group="item"
|
|
121
|
-
:depth="depth + 1"
|
|
122
|
-
:collapsible="props.collapsible"
|
|
123
|
-
/>
|
|
124
|
-
</li>
|
|
125
|
-
<DocLink v-else :item="item" :depth="depth" :collapsible="collapsible" />
|
|
126
|
-
</template>
|
|
127
|
-
</ul>
|
|
110
|
+
:depth="depth"
|
|
111
|
+
:items="group.items"
|
|
112
|
+
:active-path="activePath"
|
|
113
|
+
:collapsible="collapsible"
|
|
114
|
+
:link-component="linkComponent"
|
|
115
|
+
@hide-marker="emit('hideMarker')"
|
|
116
|
+
@update-marker-position="emit('updateMarkerPosition')"
|
|
117
|
+
@update-active-position="(opts) => emit('updateActivePosition', opts)"
|
|
118
|
+
/>
|
|
128
119
|
</template>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { DefineComponent, ref } from 'vue'
|
|
3
|
+
import { NavGroup, NavItemLink } from '@cypress-design/constants-docmenu'
|
|
4
|
+
import DocGroup from './_DocGroup.vue'
|
|
5
|
+
import DocLink from './_DocLink.vue'
|
|
6
|
+
|
|
7
|
+
const props = defineProps<{
|
|
8
|
+
items: (NavGroup | NavItemLink)[]
|
|
9
|
+
activePath?: string
|
|
10
|
+
collapsible: boolean
|
|
11
|
+
linkComponent: DefineComponent | 'a'
|
|
12
|
+
depth: number
|
|
13
|
+
}>()
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits<{
|
|
16
|
+
(event: 'updateActivePosition', opts?: { top: number; height: number }): void
|
|
17
|
+
(event: 'hideMarker'): void
|
|
18
|
+
(event: 'updateMarkerPosition'): void
|
|
19
|
+
}>()
|
|
20
|
+
|
|
21
|
+
const $items = ref<(typeof DocLink)[]>([])
|
|
22
|
+
const $groups = ref<(typeof DocGroup)[]>([])
|
|
23
|
+
|
|
24
|
+
function hasActiveItemRecursively(items = props.items): boolean {
|
|
25
|
+
return items.some((item) => {
|
|
26
|
+
if ('items' in item) {
|
|
27
|
+
return hasActiveItemRecursively(item.items)
|
|
28
|
+
}
|
|
29
|
+
return item.href === props.activePath
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function reTriggerSetActiveGroup() {
|
|
34
|
+
$items.value.forEach((item) => {
|
|
35
|
+
item.setActiveMarkerPosition()
|
|
36
|
+
})
|
|
37
|
+
$groups.value.forEach((group) => {
|
|
38
|
+
group.reTriggerSetActiveGroup()
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
defineExpose({
|
|
43
|
+
reTriggerSetActiveGroup,
|
|
44
|
+
})
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<template>
|
|
48
|
+
<ul
|
|
49
|
+
class="list-none p-0"
|
|
50
|
+
:class="{
|
|
51
|
+
'border-l border-gray-100': depth === 0 && collapsible,
|
|
52
|
+
'ml-[8px]': depth >= 0,
|
|
53
|
+
}"
|
|
54
|
+
>
|
|
55
|
+
<template v-for="item in items">
|
|
56
|
+
<li class="relative list-none p-0" v-if="item && 'items' in item">
|
|
57
|
+
<DocGroup
|
|
58
|
+
ref="$groups"
|
|
59
|
+
:active-path="activePath"
|
|
60
|
+
:group="item"
|
|
61
|
+
:depth="depth + 1"
|
|
62
|
+
:collapsible="collapsible"
|
|
63
|
+
:link-component="linkComponent"
|
|
64
|
+
@update-active-position="
|
|
65
|
+
(opts) => {
|
|
66
|
+
emit('updateActivePosition', opts)
|
|
67
|
+
}
|
|
68
|
+
"
|
|
69
|
+
@update-marker-position="
|
|
70
|
+
() => {
|
|
71
|
+
if (hasActiveItemRecursively()) {
|
|
72
|
+
reTriggerSetActiveGroup()
|
|
73
|
+
} else {
|
|
74
|
+
emit('updateMarkerPosition')
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
"
|
|
78
|
+
/>
|
|
79
|
+
</li>
|
|
80
|
+
<DocLink
|
|
81
|
+
v-else
|
|
82
|
+
ref="$items"
|
|
83
|
+
:item="item"
|
|
84
|
+
:active="item.href === activePath"
|
|
85
|
+
:depth="depth"
|
|
86
|
+
:collapsible="collapsible"
|
|
87
|
+
:link-component="linkComponent"
|
|
88
|
+
@update:active="
|
|
89
|
+
(_, opts) => {
|
|
90
|
+
if (!opts) return
|
|
91
|
+
emit('updateActivePosition', opts)
|
|
92
|
+
}
|
|
93
|
+
"
|
|
94
|
+
/>
|
|
95
|
+
</template>
|
|
96
|
+
</ul>
|
|
97
|
+
</template>
|
package/_DocLink.vue
CHANGED
|
@@ -1,29 +1,74 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
+
import { watch, type DefineComponent, ref, onMounted } from 'vue'
|
|
2
3
|
import type { NavItemLink } from '@cypress-design/constants-docmenu'
|
|
3
4
|
|
|
4
|
-
withDefaults(
|
|
5
|
+
const props = withDefaults(
|
|
5
6
|
defineProps<{
|
|
6
7
|
item: NavItemLink
|
|
7
|
-
|
|
8
|
+
active: boolean
|
|
8
9
|
collapsible: boolean
|
|
10
|
+
depth?: number
|
|
11
|
+
linkComponent: DefineComponent | 'a'
|
|
9
12
|
}>(),
|
|
10
13
|
{
|
|
11
14
|
depth: -1,
|
|
12
|
-
}
|
|
15
|
+
},
|
|
13
16
|
)
|
|
17
|
+
|
|
18
|
+
const emit = defineEmits<{
|
|
19
|
+
(
|
|
20
|
+
event: 'update:active',
|
|
21
|
+
active: boolean,
|
|
22
|
+
opts?: { top: number; height: number },
|
|
23
|
+
): void
|
|
24
|
+
}>()
|
|
25
|
+
|
|
26
|
+
const $container = ref<HTMLLIElement>()
|
|
27
|
+
|
|
28
|
+
function setActiveMarkerPosition() {
|
|
29
|
+
if (props.active) {
|
|
30
|
+
const { top = 0, height = 36 } =
|
|
31
|
+
$container.value?.getBoundingClientRect() ?? {}
|
|
32
|
+
|
|
33
|
+
emit('update:active', props.active, {
|
|
34
|
+
top,
|
|
35
|
+
height,
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
onMounted(() => {
|
|
41
|
+
watch(
|
|
42
|
+
() => props.active,
|
|
43
|
+
(active) => {
|
|
44
|
+
if (active) {
|
|
45
|
+
setActiveMarkerPosition()
|
|
46
|
+
} else {
|
|
47
|
+
emit('update:active', active)
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
{ immediate: true },
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
defineExpose({
|
|
55
|
+
setActiveMarkerPosition,
|
|
56
|
+
})
|
|
14
57
|
</script>
|
|
15
58
|
|
|
16
59
|
<template>
|
|
17
60
|
<li
|
|
61
|
+
ref="$container"
|
|
18
62
|
class="list-none p-0"
|
|
19
63
|
:class="{
|
|
20
64
|
'pl-[16px]': depth >= 0,
|
|
21
65
|
}"
|
|
22
66
|
>
|
|
23
|
-
<
|
|
67
|
+
<component
|
|
68
|
+
:is="linkComponent"
|
|
24
69
|
class="group relative block w-full pl-[24px]"
|
|
25
70
|
:class="{
|
|
26
|
-
'text-indigo-500':
|
|
71
|
+
'text-indigo-500': active,
|
|
27
72
|
'py-[8px] text-[16px] leading-[24px]': depth < 0,
|
|
28
73
|
'leading-[20px] text-[14px] py-[12px]': depth >= 0,
|
|
29
74
|
}"
|
|
@@ -33,13 +78,13 @@ withDefaults(
|
|
|
33
78
|
v-if="depth >= 0"
|
|
34
79
|
class="absolute h-[80%] top-[10%] w-[4px] z-10 rounded-full hidden"
|
|
35
80
|
:class="{
|
|
36
|
-
'group-hover:block bg-gray-300': !
|
|
81
|
+
'group-hover:block bg-gray-300': !active && collapsible,
|
|
37
82
|
}"
|
|
38
83
|
:style="{
|
|
39
84
|
left: `-${18.5 + depth * 7.5}px`,
|
|
40
85
|
}"
|
|
41
86
|
/>
|
|
42
|
-
{{ item.
|
|
43
|
-
</
|
|
87
|
+
{{ item.label }}
|
|
88
|
+
</component>
|
|
44
89
|
</li>
|
|
45
90
|
</template>
|