@cypress-design/vue-docmenu 0.1.0

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.
@@ -0,0 +1,13 @@
1
+ $ yarn build:module && yarn build:types
2
+ $ yarn vite build
3
+ $ /home/runner/work/cypress-design/cypress-design/node_modules/.bin/vite build
4
+ vite v4.2.1 building for production...
5
+ transforming...
6
+ ✓ 9 modules transformed.
7
+ rendering chunks...
8
+ computing gzip size...
9
+ dist/index.es.mjs 7.14 kB │ gzip: 2.53 kB │ map: 262.85 kB
10
+ dist/index.umd.js 6.15 kB │ gzip: 2.31 kB │ map: 262.53 kB
11
+ ✓ built in 6.20s
12
+ $ yarn vue-tsc --project ./tsconfig.build.json
13
+ $ /home/runner/work/cypress-design/cypress-design/node_modules/.bin/vue-tsc --project ./tsconfig.build.json
package/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # @cypress-design/vue-docmenu
2
+
3
+ ## 0.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#178](https://github.com/cypress-io/cypress-design/pull/178) [`d0de778`](https://github.com/cypress-io/cypress-design/commit/d0de77843adb87d8f4804219c6dca8f45b15c650) Thanks [@elevatebart](https://github.com/elevatebart)! - deliver new docs and improved components
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`18399c7`](https://github.com/cypress-io/cypress-design/commit/18399c72a52288c67af0935384430d4e4cd24251), [`d0de778`](https://github.com/cypress-io/cypress-design/commit/d0de77843adb87d8f4804219c6dca8f45b15c650)]:
12
+ - @cypress-design/vue-icon@0.20.0
@@ -0,0 +1,6 @@
1
+ import type { NavGroup, NavItemLink } from '../constants'
2
+ import DocMenu from './DocMenu.vue'
3
+
4
+ export default ({ items }: { items: (NavGroup | NavItemLink)[] }) => {
5
+ return <DocMenu items={items} />
6
+ }
package/DocMenu.vue ADDED
@@ -0,0 +1,26 @@
1
+ <script lang="ts" setup>
2
+ import { NavGroup, NavItemLink } from '../constants'
3
+ import DocGroup from './_DocGroup.vue'
4
+ import DocLink from './_DocLink.vue'
5
+
6
+ withDefaults(
7
+ defineProps<{
8
+ items: (NavItemLink | NavGroup)[]
9
+ collapsible?: boolean
10
+ }>(),
11
+ {
12
+ collapsible: true,
13
+ }
14
+ )
15
+ </script>
16
+
17
+ <template>
18
+ <ul class="overflow-y-hidden list-none p-0">
19
+ <template v-for="item in items">
20
+ <li v-if="'items' in item" class="relative list-none p-0">
21
+ <DocGroup :group="item" :depth="0" :collapsible="collapsible" />
22
+ </li>
23
+ <DocLink v-else :item="item" :collapsible="collapsible" />
24
+ </template>
25
+ </ul>
26
+ </template>
@@ -0,0 +1,12 @@
1
+ /// <reference types="cypress" />
2
+ import { mount } from 'cypress/vue'
3
+ import assertions from '../assertions'
4
+ import type { NavGroup, NavItemLink } from '../constants'
5
+ import DocMenuStory from './DocMenu.rootstory'
6
+
7
+ describe('<DocMenu/>', () => {
8
+ function mountStory(items: (NavItemLink | NavGroup)[] = []) {
9
+ mount(() => <DocMenuStory items={items} />)
10
+ }
11
+ assertions(mountStory)
12
+ })
package/ReadMe.md ADDED
@@ -0,0 +1,79 @@
1
+ # DocMenu
2
+
3
+ ## Summary
4
+
5
+ Describe your component here.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @cypress-design/vue-docmenu
11
+ ```
12
+
13
+ or with yarn
14
+
15
+ ```bash
16
+ yarn add @cypress-design/vue-docmenu
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ ```vue live
22
+ <DocMenu
23
+ :items="[
24
+ {
25
+ text: 'Get Started',
26
+ href: '#',
27
+ },
28
+ {
29
+ text: 'Overview',
30
+ items: [
31
+ {
32
+ text: 'Overview Item 1',
33
+ href: '#',
34
+ },
35
+ {
36
+ text: 'Overview Item 2',
37
+ href: '#',
38
+ active: true,
39
+ },
40
+ ],
41
+ },
42
+ {
43
+ text: 'Getting Started',
44
+ items: [
45
+ {
46
+ text: 'Item 1',
47
+ href: '#',
48
+ },
49
+ {
50
+ text: 'Group',
51
+ items: [
52
+ {
53
+ text: 'Item 1',
54
+ href: '#',
55
+ },
56
+ {
57
+ text: 'Item 2',
58
+ href: '#',
59
+ },
60
+ {
61
+ text: 'Item 3',
62
+ href: '#',
63
+ },
64
+ {
65
+ text: 'Item 4',
66
+ href: '#',
67
+ },
68
+ ],
69
+ },
70
+ {
71
+ text: 'Item 5',
72
+ href: '#',
73
+ active: true,
74
+ },
75
+ ],
76
+ },
77
+ ]"
78
+ />
79
+ ```
package/_DocGroup.vue ADDED
@@ -0,0 +1,127 @@
1
+ <script lang="ts" setup>
2
+ import { computed, Ref, ref } from 'vue'
3
+ import { IconChevronDownSmall } from '@cypress-design/vue-icon'
4
+ import { NavGroup, classes } from '../constants'
5
+ import DocLink from './_DocLink.vue'
6
+ import DocGroup from './_DocGroup.vue'
7
+
8
+ const props = withDefaults(
9
+ defineProps<{
10
+ group: NavGroup
11
+ collapsible: boolean
12
+ depth?: number
13
+ }>(),
14
+ {
15
+ depth: 0,
16
+ }
17
+ )
18
+
19
+ const open = ref(props.depth === 0)
20
+
21
+ const $groups = ref<(typeof DocGroup)[]>([])
22
+
23
+ const height = computed(() => {
24
+ return $groups.value && open.value
25
+ ? $groups.value.reduce(
26
+ (acc, { height: h }) => acc + h,
27
+ props.group.items.length
28
+ )
29
+ : 0
30
+ })
31
+
32
+ defineExpose<{
33
+ height: Ref<number>
34
+ }>({
35
+ height,
36
+ })
37
+
38
+ const activeMarkerTop = computed(() => {
39
+ const activeIndex = props.group.items.findIndex(
40
+ (item) => 'href' in item && item.active
41
+ )
42
+
43
+ // how many groups are before the active element?
44
+ let numberOfGroups = props.group.items.filter(
45
+ (item, index) => !('href' in item) && index < activeIndex
46
+ ).length
47
+
48
+ // if there is any open group before the active element
49
+ // compensate for the height
50
+ const groupHeight = $groups.value?.reduce((acc, group) => {
51
+ if (numberOfGroups < -1) return acc
52
+ numberOfGroups--
53
+ return acc + group.height
54
+ }, 0)
55
+ return (activeIndex + groupHeight) * 44
56
+ })
57
+
58
+ const Head = computed(() =>
59
+ props.collapsible ? 'button' : props.group.href ? 'a' : 'div'
60
+ )
61
+ </script>
62
+
63
+ <template>
64
+ <component
65
+ :is="Head"
66
+ :class="[
67
+ classes.button,
68
+ {
69
+ [classes.topButton]: depth === 0,
70
+ [classes.leafButton]: depth,
71
+ },
72
+ ]"
73
+ :href="props.group.href"
74
+ @click="
75
+ () => {
76
+ if (collapsible) {
77
+ open = !open
78
+ }
79
+ }
80
+ "
81
+ >
82
+ <IconChevronDownSmall
83
+ v-if="props.collapsible"
84
+ stroke-color="gray-400"
85
+ :size="depth ? '8' : '16'"
86
+ class="absolute left-0 transform transition-transform"
87
+ :class="{
88
+ 'rotate-0': open,
89
+ '-rotate-90': !open,
90
+ 'ml-[16px]': depth,
91
+ }"
92
+ />
93
+ {{ group.text }}
94
+ </component>
95
+ <div
96
+ v-if="
97
+ props.collapsible &&
98
+ depth >= 0 &&
99
+ open &&
100
+ group.items.some((item) => 'href' in item && item.active)
101
+ "
102
+ class="absolute h-[36px] w-[4px] z-10 rounded-full bg-indigo-500 transition-all duration-300 ml-[6px] mt-[48px]"
103
+ :style="{
104
+ top: `${activeMarkerTop}px`,
105
+ left: `-${depth === 0 ? 0 : depth * 7.5 + 1}px`,
106
+ }"
107
+ />
108
+ <ul
109
+ v-show="open"
110
+ class="list-none p-0 ml-[7.5px]"
111
+ :class="{
112
+ 'border-l border-gray-100': depth === 0 && props.collapsible,
113
+ }"
114
+ >
115
+ <template v-for="item in group.items">
116
+ <li class="relative list-none p-0" v-if="'items' in item">
117
+ <DocGroup
118
+ ref="$groups"
119
+ :group="item"
120
+ :depth="depth + 1"
121
+ :collapsible="props.collapsible"
122
+ />
123
+ </li>
124
+ <DocLink v-else :item="item" :depth="depth" :collapsible="collapsible" />
125
+ </template>
126
+ </ul>
127
+ </template>
package/_DocLink.vue ADDED
@@ -0,0 +1,45 @@
1
+ <script lang="ts" setup>
2
+ import type { NavItemLink } from '../constants'
3
+
4
+ withDefaults(
5
+ defineProps<{
6
+ item: NavItemLink
7
+ depth?: number
8
+ collapsible: boolean
9
+ }>(),
10
+ {
11
+ depth: -1,
12
+ }
13
+ )
14
+ </script>
15
+
16
+ <template>
17
+ <li
18
+ class="list-none p-0"
19
+ :class="{
20
+ 'pl-[16px]': depth >= 0,
21
+ }"
22
+ >
23
+ <a
24
+ class="group relative block w-full pl-[24px]"
25
+ :class="{
26
+ 'text-indigo-500 dark:text-indigo-200': item.active,
27
+ 'py-[8px] text-[16px] leading-[24px]': depth < 0,
28
+ 'leading-[20px] text-[14px] py-[12px]': depth >= 0,
29
+ }"
30
+ :href="item.href"
31
+ >
32
+ <div
33
+ v-if="depth >= 0"
34
+ class="absolute h-[80%] top-[10%] w-[4px] z-10 rounded-full hidden"
35
+ :class="{
36
+ 'group-hover:block bg-gray-300': !item.active && collapsible,
37
+ }"
38
+ :style="{
39
+ left: `-${18.5 + depth * 7.5}px`,
40
+ }"
41
+ />
42
+ {{ item.text }}
43
+ </a>
44
+ </li>
45
+ </template>
@@ -0,0 +1,17 @@
1
+ export interface NavItemBase {
2
+ text: string;
3
+ href?: string;
4
+ active?: boolean;
5
+ }
6
+ export interface NavItemLink extends NavItemBase {
7
+ href: string;
8
+ }
9
+ export interface NavGroup extends NavItemBase {
10
+ items: (NavItemLink | NavGroup)[];
11
+ }
12
+ export declare const classes: {
13
+ readonly button: "flex leading-[24px] py-[10px] items-center relative w-full";
14
+ readonly topButton: "leading-[24px] text-[16px] pl-[24px] font-medium";
15
+ readonly leafButton: "leading-[20px] text-[14px] pl-[40px]";
16
+ };
17
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../constants.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,MAAM,WAAW,WAAY,SAAQ,WAAW;IAC9C,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,QAAS,SAAQ,WAAW;IAC3C,KAAK,EAAE,CAAC,WAAW,GAAG,QAAQ,CAAC,EAAE,CAAA;CAClC;AAED,eAAO,MAAM,OAAO;;;;CAIV,CAAA"}
@@ -0,0 +1,203 @@
1
+ import { h as I, defineComponent as C, openBlock as o, createElementBlock as i, normalizeClass as d, createElementVNode as z, normalizeStyle as B, createCommentVNode as y, createTextVNode as D, toDisplayString as O, ref as $, computed as v, Fragment as h, createBlock as x, resolveDynamicComponent as L, unref as c, withCtx as M, withDirectives as V, renderList as N, createVNode as S, vShow as G } from "vue";
2
+ import * as H from "@cypress-design/icon-registry";
3
+ import { ICON_COLOR_PROP_NAMES as T } from "@cypress-design/icon-registry";
4
+ const A = ({
5
+ body: e,
6
+ compiledClasses: a,
7
+ size: t,
8
+ class: l,
9
+ interactiveColorsOnGroup: p,
10
+ ...m
11
+ }) => {
12
+ const g = Object.keys(m).reduce(
13
+ (r, n) => (!T.includes(n) && n !== "name" && (r[n] = m[n]), r),
14
+ {}
15
+ ), f = {
16
+ width: t,
17
+ height: t,
18
+ viewBox: `0 0 ${t} ${t}`,
19
+ fill: "none",
20
+ innerHTML: e,
21
+ ...g
22
+ // add all standard attributes back to the svg tag
23
+ };
24
+ return a.length && (f.class = a.join(" ")), f;
25
+ }, P = (e) => {
26
+ const { sizeWithDefault: a, compiledClasses: t } = H.getComponentAttributes({ ...e, availableSizes: ["8", "16"] }), l = {
27
+ 8: '<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 2.5 3 3 3-3" class="icon-dark"/>',
28
+ 16: '<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m4 6 4 4 4-4" class="icon-dark"/>'
29
+ }[a];
30
+ if (!l)
31
+ throw Error(`Icon "chevron-down-small" is not available in size ${a}`);
32
+ return I("svg", A({
33
+ ...e,
34
+ size: a,
35
+ body: l,
36
+ compiledClasses: t
37
+ }));
38
+ }, k = {
39
+ button: "flex leading-[24px] py-[10px] items-center relative w-full",
40
+ topButton: "leading-[24px] text-[16px] pl-[24px] font-medium",
41
+ leafButton: "leading-[20px] text-[14px] pl-[40px]"
42
+ }, R = ["href"], j = /* @__PURE__ */ C({
43
+ __name: "_DocLink",
44
+ props: {
45
+ item: null,
46
+ depth: { default: -1 },
47
+ collapsible: { type: Boolean }
48
+ },
49
+ setup(e) {
50
+ return (a, t) => (o(), i("li", {
51
+ class: d(["list-none p-0", {
52
+ "pl-[16px]": e.depth >= 0
53
+ }])
54
+ }, [
55
+ z("a", {
56
+ class: d(["group relative block w-full pl-[24px]", {
57
+ "text-indigo-500 dark:text-indigo-200": e.item.active,
58
+ "py-[8px] text-[16px] leading-[24px]": e.depth < 0,
59
+ "leading-[20px] text-[14px] py-[12px]": e.depth >= 0
60
+ }]),
61
+ href: e.item.href
62
+ }, [
63
+ e.depth >= 0 ? (o(), i("div", {
64
+ key: 0,
65
+ class: d(["absolute h-[80%] top-[10%] w-[4px] z-10 rounded-full hidden", {
66
+ "group-hover:block bg-gray-300": !e.item.active && e.collapsible
67
+ }]),
68
+ style: B({
69
+ left: `-${18.5 + e.depth * 7.5}px`
70
+ })
71
+ }, null, 6)) : y("", !0),
72
+ D(" " + O(e.item.text), 1)
73
+ ], 10, R)
74
+ ], 2));
75
+ }
76
+ }), F = {
77
+ key: 0,
78
+ class: "relative list-none p-0"
79
+ }, E = /* @__PURE__ */ C({
80
+ __name: "_DocGroup",
81
+ props: {
82
+ group: null,
83
+ collapsible: { type: Boolean },
84
+ depth: { default: 0 }
85
+ },
86
+ setup(e, { expose: a }) {
87
+ const t = e, l = $(t.depth === 0), p = $([]), m = v(() => p.value && l.value ? p.value.reduce(
88
+ (r, { height: n }) => r + n,
89
+ t.group.items.length
90
+ ) : 0);
91
+ a({
92
+ height: m
93
+ });
94
+ const g = v(() => {
95
+ var w;
96
+ const r = t.group.items.findIndex(
97
+ (u) => "href" in u && u.active
98
+ );
99
+ let n = t.group.items.filter(
100
+ (u, b) => !("href" in u) && b < r
101
+ ).length;
102
+ const s = (w = p.value) == null ? void 0 : w.reduce((u, b) => n < -1 ? u : (n--, u + b.height), 0);
103
+ return (r + s) * 44;
104
+ }), f = v(
105
+ () => t.collapsible ? "button" : t.group.href ? "a" : "div"
106
+ );
107
+ return (r, n) => (o(), i(h, null, [
108
+ (o(), x(L(c(f)), {
109
+ class: d([
110
+ c(k).button,
111
+ {
112
+ [c(k).topButton]: e.depth === 0,
113
+ [c(k).leafButton]: e.depth
114
+ }
115
+ ]),
116
+ href: t.group.href,
117
+ onClick: n[0] || (n[0] = () => {
118
+ e.collapsible && (l.value = !l.value);
119
+ })
120
+ }, {
121
+ default: M(() => [
122
+ t.collapsible ? (o(), x(c(P), {
123
+ key: 0,
124
+ "stroke-color": "gray-400",
125
+ size: e.depth ? "8" : "16",
126
+ class: d(["absolute left-0 transform transition-transform", {
127
+ "rotate-0": l.value,
128
+ "-rotate-90": !l.value,
129
+ "ml-[16px]": e.depth
130
+ }])
131
+ }, null, 8, ["size", "class"])) : y("", !0),
132
+ D(" " + O(e.group.text), 1)
133
+ ]),
134
+ _: 1
135
+ }, 8, ["class", "href"])),
136
+ t.collapsible && e.depth >= 0 && l.value && e.group.items.some((s) => "href" in s && s.active) ? (o(), i("div", {
137
+ key: 0,
138
+ class: "absolute h-[36px] w-[4px] z-10 rounded-full bg-indigo-500 transition-all duration-300 ml-[6px] mt-[48px]",
139
+ style: B({
140
+ top: `${c(g)}px`,
141
+ left: `-${e.depth === 0 ? 0 : e.depth * 7.5 + 1}px`
142
+ })
143
+ }, null, 4)) : y("", !0),
144
+ V(z("ul", {
145
+ class: d(["list-none p-0 ml-[7.5px]", {
146
+ "border-l border-gray-100": e.depth === 0 && t.collapsible
147
+ }])
148
+ }, [
149
+ (o(!0), i(h, null, N(e.group.items, (s) => (o(), i(h, null, [
150
+ "items" in s ? (o(), i("li", F, [
151
+ S(E, {
152
+ ref_for: !0,
153
+ ref_key: "$groups",
154
+ ref: p,
155
+ group: s,
156
+ depth: e.depth + 1,
157
+ collapsible: t.collapsible
158
+ }, null, 8, ["group", "depth", "collapsible"])
159
+ ])) : (o(), x(j, {
160
+ key: 1,
161
+ item: s,
162
+ depth: e.depth,
163
+ collapsible: e.collapsible
164
+ }, null, 8, ["item", "depth", "collapsible"]))
165
+ ], 64))), 256))
166
+ ], 2), [
167
+ [G, l.value]
168
+ ])
169
+ ], 64));
170
+ }
171
+ }), W = { class: "overflow-y-hidden list-none p-0" }, q = {
172
+ key: 0,
173
+ class: "relative list-none p-0"
174
+ }, Q = /* @__PURE__ */ C({
175
+ __name: "DocMenu",
176
+ props: {
177
+ items: null,
178
+ collapsible: { type: Boolean, default: !0 }
179
+ },
180
+ setup(e) {
181
+ return (a, t) => (o(), i("ul", W, [
182
+ (o(!0), i(h, null, N(e.items, (l) => (o(), i(h, null, [
183
+ "items" in l ? (o(), i("li", q, [
184
+ S(E, {
185
+ group: l,
186
+ depth: 0,
187
+ collapsible: e.collapsible
188
+ }, null, 8, ["group", "collapsible"])
189
+ ])) : (o(), x(j, {
190
+ key: 1,
191
+ item: l,
192
+ collapsible: e.collapsible
193
+ }, null, 8, ["item", "collapsible"]))
194
+ ], 64))), 256))
195
+ ]));
196
+ }
197
+ });
198
+ export {
199
+ Q as default
200
+ };
201
+ //# sourceMappingURL=index.es.mjs.map
202
+
203
+ /* <windicss-keep class="overflow-y-hidden list-none p-0 relative absolute left-0 transform transition-transform rotate-0 -rotate-90 ml-[16px] h-[36px] w-[4px] z-10 rounded-full bg-indigo-500 transition-all duration-300 ml-[6px] mt-[48px] ml-[7.5px] border-l border-gray-100 icon-dark-gray-400 pl-[16px] block w-full pl-[24px] text-indigo-500 dark:text-indigo-200 py-[8px] text-[16px] leading-[24px] leading-[20px] text-[14px] py-[12px] h-[80%] top-[10%] hidden group-hover:block bg-gray-300 flex py-[10px] items-center font-medium pl-[40px]"> */