@fiscozen/navbar 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.
- package/.eslintignore +1 -0
- package/.eslintrc.cjs +18 -0
- package/.prettierrc.js +6 -0
- package/LICENSE +21 -0
- package/README.md +4 -0
- package/dist/navbar.js +3496 -0
- package/dist/navbar.umd.cjs +763 -0
- package/package.json +42 -0
- package/src/FzNavbar.vue +67 -0
- package/src/__tests__/FzNavbar.spec.ts +85 -0
- package/src/__tests__/__snapshots__/FzNavbar.spec.ts.snap +65 -0
- package/src/index.ts +3 -0
- package/src/types.ts +8 -0
- package/tsconfig.json +4 -0
- package/vite.config.ts +35 -0
- package/vitest.config.ts +19 -0
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fiscozen/navbar",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Design System Navbar Component",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"keywords": [],
|
|
8
|
+
"author": "Riccardo Agnoletto",
|
|
9
|
+
"peerDependencies": {
|
|
10
|
+
"tailwindcss": "^3.4.1",
|
|
11
|
+
"vue": "^3.4.13",
|
|
12
|
+
"@fiscozen/button": "^0.1.0"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@rushstack/eslint-patch": "^1.3.3",
|
|
16
|
+
"@types/jsdom": "^21.1.6",
|
|
17
|
+
"@types/node": "^18.19.3",
|
|
18
|
+
"@vitejs/plugin-vue": "^4.5.2",
|
|
19
|
+
"@vitest/coverage-v8": "^1.2.1",
|
|
20
|
+
"@vue/test-utils": "^2.4.3",
|
|
21
|
+
"@vue/tsconfig": "^0.5.0",
|
|
22
|
+
"vite-plugin-dts": "^3.8.3",
|
|
23
|
+
"eslint": "^8.49.0",
|
|
24
|
+
"jsdom": "^23.0.1",
|
|
25
|
+
"prettier": "^3.0.3",
|
|
26
|
+
"typescript": "~5.3.0",
|
|
27
|
+
"vite": "^5.0.10",
|
|
28
|
+
"vitest": "^1.2.0",
|
|
29
|
+
"vue-tsc": "^1.8.25",
|
|
30
|
+
"@fiscozen/eslint-config": "^0.1.0",
|
|
31
|
+
"@fiscozen/prettier-config": "^0.1.0",
|
|
32
|
+
"@fiscozen/tsconfig": "^0.1.0"
|
|
33
|
+
},
|
|
34
|
+
"license": "ISC",
|
|
35
|
+
"scripts": {
|
|
36
|
+
"coverage": "vitest run --coverage",
|
|
37
|
+
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts",
|
|
38
|
+
"format": "prettier --write src/",
|
|
39
|
+
"test:unit": "vitest run",
|
|
40
|
+
"build": "vue-tsc && vite build"
|
|
41
|
+
}
|
|
42
|
+
}
|
package/src/FzNavbar.vue
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref, onBeforeMount, onMounted, onUnmounted, computed } from 'vue'
|
|
3
|
+
import { FzIconButton } from '@fiscozen/button'
|
|
4
|
+
import { FzNavbarProps } from './types'
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<FzNavbarProps>(), {
|
|
7
|
+
variant: 'horizontal'
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
const width = ref(0)
|
|
11
|
+
|
|
12
|
+
const onResize = () => {
|
|
13
|
+
width.value = window.innerWidth
|
|
14
|
+
}
|
|
15
|
+
onBeforeMount(() => {
|
|
16
|
+
onResize()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
onMounted(() => {
|
|
20
|
+
window.addEventListener('resize', onResize)
|
|
21
|
+
})
|
|
22
|
+
onUnmounted(() => {
|
|
23
|
+
window.removeEventListener('resize', onResize)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
const isMobile = computed(() => Boolean(width.value <= 1024))
|
|
27
|
+
const isVertical = computed(() => Boolean(props.variant === 'vertical'))
|
|
28
|
+
const isHorizontal = computed(() => Boolean(props.variant === 'horizontal'))
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<header
|
|
33
|
+
class="flex p-12 shadow"
|
|
34
|
+
:class="{
|
|
35
|
+
'justify-between': isMobile,
|
|
36
|
+
'h-full w-56 flex-col': isVertical && !isMobile,
|
|
37
|
+
'h-56 w-full': isHorizontal || isMobile
|
|
38
|
+
}"
|
|
39
|
+
>
|
|
40
|
+
<template v-if="!isMobile">
|
|
41
|
+
<div :class="{ 'mr-32': isHorizontal, 'mb-32': isVertical }">
|
|
42
|
+
<slot name="brand-logo" :isMobile :isHorizontal :isVertical></slot>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="flex gap-4" :class="{ 'flex-row': isHorizontal, 'flex-col': isVertical }">
|
|
45
|
+
<slot name="navigation" :isVertical :isHorizontal :isMobile></slot>
|
|
46
|
+
</div>
|
|
47
|
+
<div
|
|
48
|
+
class="flex gap-16"
|
|
49
|
+
:class="{ 'ml-auto flex-row': isHorizontal, 'mt-auto flex-col': isVertical }"
|
|
50
|
+
>
|
|
51
|
+
<slot name="notifications" :isHorizontal :isVertical :isMobile></slot>
|
|
52
|
+
<slot name="user-menu" :isHorizontal :isMobile :isVertical></slot>
|
|
53
|
+
</div>
|
|
54
|
+
</template>
|
|
55
|
+
<template v-else>
|
|
56
|
+
<FzIconButton iconName="bars" variant="secondary" tooltip="menu" :disabled="false" />
|
|
57
|
+
<div>
|
|
58
|
+
<slot name="brand-logo" :isMobile :isHorizontal :isVertical></slot>
|
|
59
|
+
</div>
|
|
60
|
+
<div>
|
|
61
|
+
<slot :name="isHorizontal ? 'notifications' : 'user-menu'" :isHorizontal :isVertical :isMobile></slot>
|
|
62
|
+
</div>
|
|
63
|
+
</template>
|
|
64
|
+
</header>
|
|
65
|
+
</template>
|
|
66
|
+
|
|
67
|
+
<style></style>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import { mount } from '@vue/test-utils'
|
|
4
|
+
import FzNavbar from '../FzNavbar.vue'
|
|
5
|
+
|
|
6
|
+
const navigation = `
|
|
7
|
+
<div class="link">one</div>
|
|
8
|
+
<div class="link">two</div>
|
|
9
|
+
<div class="link">three</div>
|
|
10
|
+
`
|
|
11
|
+
|
|
12
|
+
const logo = `
|
|
13
|
+
<template #brand-logo="scope">
|
|
14
|
+
<div id="brandlogo" :class="{'mobile': scope.isMobile, 'desktop': !scope.isMobile}"></div>
|
|
15
|
+
</template>
|
|
16
|
+
`
|
|
17
|
+
const avatar = '<div id="avatar"></div>'
|
|
18
|
+
const notifications = '<div id="notification"></div>'
|
|
19
|
+
|
|
20
|
+
describe('FzNavbar', () => {
|
|
21
|
+
it('should match snapshot in horizontal layout large screen', () => {
|
|
22
|
+
window.innerWidth = 1280
|
|
23
|
+
const wrapper = mount(FzNavbar, {
|
|
24
|
+
props: {
|
|
25
|
+
variant: 'horizontal'
|
|
26
|
+
},
|
|
27
|
+
slots: {
|
|
28
|
+
navigation,
|
|
29
|
+
notifications,
|
|
30
|
+
'user-menu': avatar,
|
|
31
|
+
'brand-logo': logo
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
36
|
+
})
|
|
37
|
+
it('should match snapshot in horizontal layout small screen', () => {
|
|
38
|
+
window.innerWidth = 1024
|
|
39
|
+
const wrapper = mount(FzNavbar, {
|
|
40
|
+
props: {
|
|
41
|
+
variant: 'horizontal'
|
|
42
|
+
},
|
|
43
|
+
slots: {
|
|
44
|
+
navigation,
|
|
45
|
+
notifications,
|
|
46
|
+
'user-menu': avatar,
|
|
47
|
+
'brand-logo': logo
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
52
|
+
})
|
|
53
|
+
it('should match snapshot in vertical layout large screen', () => {
|
|
54
|
+
window.innerWidth = 1280
|
|
55
|
+
const wrapper = mount(FzNavbar, {
|
|
56
|
+
props: {
|
|
57
|
+
variant: 'vertical'
|
|
58
|
+
},
|
|
59
|
+
slots: {
|
|
60
|
+
navigation,
|
|
61
|
+
notifications,
|
|
62
|
+
'user-menu': avatar,
|
|
63
|
+
'brand-logo': logo
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
68
|
+
})
|
|
69
|
+
it('should match snapshot in vertical layout small screen', () => {
|
|
70
|
+
window.innerWidth = 1024
|
|
71
|
+
const wrapper = mount(FzNavbar, {
|
|
72
|
+
props: {
|
|
73
|
+
variant: 'vertical'
|
|
74
|
+
},
|
|
75
|
+
slots: {
|
|
76
|
+
navigation,
|
|
77
|
+
notifications,
|
|
78
|
+
'user-menu': avatar,
|
|
79
|
+
'brand-logo': logo
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
84
|
+
})
|
|
85
|
+
})
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`FzNavbar > should match snapshot in horizontal layout large screen 1`] = `
|
|
4
|
+
"<header class="flex px-12 py-12 shadow h-56 w-full">
|
|
5
|
+
<div class="mr-32">
|
|
6
|
+
<div id="brandlogo" class="desktop"></div>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="flex gap-4 flex-row">
|
|
9
|
+
<div class="link">one</div>
|
|
10
|
+
<div class="link">two</div>
|
|
11
|
+
<div class="link">three</div>
|
|
12
|
+
</div>
|
|
13
|
+
<div class="flex gap-16 ml-auto flex-row">
|
|
14
|
+
<div id="notification"></div>
|
|
15
|
+
<div id="avatar"></div>
|
|
16
|
+
</div>
|
|
17
|
+
</header>"
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
exports[`FzNavbar > should match snapshot in horizontal layout small screen 1`] = `
|
|
21
|
+
"<header class="flex px-12 py-12 shadow justify-between h-56 w-full"><button type="button" class="relative relative rounded flex flex-shrink items-center justify-center w-32 h-32 focus:border-blue-600 focus:border-solid focus:border-1 text-grey-500 bg-core-white border-1 border-grey-200 hover:bg-grey-100 disabled:text-grey-100"><svg class="svg-inline--fa fa-bars fa-lg" aria-hidden="true" focusable="false" data-prefix="fasl" data-icon="bars" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
|
22
|
+
<path class="" fill="currentColor" d="M0 64H448V96H0V64zM0 224H448v32H0V224zM448 384v32H0V384H448z"></path>
|
|
23
|
+
</svg>
|
|
24
|
+
<!--v-if--><span class="hidden h-0 w-0">menu</span>
|
|
25
|
+
</button>
|
|
26
|
+
<div>
|
|
27
|
+
<div id="brandlogo" class="mobile"></div>
|
|
28
|
+
</div>
|
|
29
|
+
<div>
|
|
30
|
+
<div id="notification"></div>
|
|
31
|
+
</div>
|
|
32
|
+
</header>"
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
exports[`FzNavbar > should match snapshot in vertical layout large screen 1`] = `
|
|
36
|
+
"<header class="flex px-12 py-12 shadow h-full w-56 flex-col">
|
|
37
|
+
<div class="mb-32">
|
|
38
|
+
<div id="brandlogo" class="desktop"></div>
|
|
39
|
+
</div>
|
|
40
|
+
<div class="flex gap-4 flex-col">
|
|
41
|
+
<div class="link">one</div>
|
|
42
|
+
<div class="link">two</div>
|
|
43
|
+
<div class="link">three</div>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="flex gap-16 mt-auto flex-col">
|
|
46
|
+
<div id="notification"></div>
|
|
47
|
+
<div id="avatar"></div>
|
|
48
|
+
</div>
|
|
49
|
+
</header>"
|
|
50
|
+
`;
|
|
51
|
+
|
|
52
|
+
exports[`FzNavbar > should match snapshot in vertical layout small screen 1`] = `
|
|
53
|
+
"<header class="flex px-12 py-12 shadow justify-between h-56 w-full"><button type="button" class="relative relative rounded flex flex-shrink items-center justify-center w-32 h-32 focus:border-blue-600 focus:border-solid focus:border-1 text-grey-500 bg-core-white border-1 border-grey-200 hover:bg-grey-100 disabled:text-grey-100"><svg class="svg-inline--fa fa-bars fa-lg" aria-hidden="true" focusable="false" data-prefix="fasl" data-icon="bars" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
|
|
54
|
+
<path class="" fill="currentColor" d="M0 64H448V96H0V64zM0 224H448v32H0V224zM448 384v32H0V384H448z"></path>
|
|
55
|
+
</svg>
|
|
56
|
+
<!--v-if--><span class="hidden h-0 w-0">menu</span>
|
|
57
|
+
</button>
|
|
58
|
+
<div>
|
|
59
|
+
<div id="brandlogo" class="mobile"></div>
|
|
60
|
+
</div>
|
|
61
|
+
<div>
|
|
62
|
+
<div id="avatar"></div>
|
|
63
|
+
</div>
|
|
64
|
+
</header>"
|
|
65
|
+
`;
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
package/tsconfig.json
ADDED
package/vite.config.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { fileURLToPath, URL } from 'node:url'
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { defineConfig } from 'vite'
|
|
5
|
+
import vue from '@vitejs/plugin-vue'
|
|
6
|
+
import dts from 'vite-plugin-dts'
|
|
7
|
+
|
|
8
|
+
// https://vitejs.dev/config/
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
plugins: [
|
|
11
|
+
vue(),
|
|
12
|
+
dts({
|
|
13
|
+
insertTypesEntry: true,
|
|
14
|
+
})
|
|
15
|
+
],
|
|
16
|
+
resolve: {
|
|
17
|
+
alias: {
|
|
18
|
+
'@': fileURLToPath(new URL('./src', import.meta.url))
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
build: {
|
|
22
|
+
lib: {
|
|
23
|
+
entry: resolve(__dirname, './src/index.ts'),
|
|
24
|
+
name: 'FzNavbar',
|
|
25
|
+
},
|
|
26
|
+
rollupOptions: {
|
|
27
|
+
external: ['vue'],
|
|
28
|
+
output: {
|
|
29
|
+
globals: {
|
|
30
|
+
vue: 'Vue',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
})
|
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url'
|
|
2
|
+
import { mergeConfig, defineConfig, configDefaults } from 'vitest/config'
|
|
3
|
+
import viteConfig from './vite.config'
|
|
4
|
+
|
|
5
|
+
export default mergeConfig(
|
|
6
|
+
viteConfig,
|
|
7
|
+
defineConfig({
|
|
8
|
+
test: {
|
|
9
|
+
environment: 'jsdom',
|
|
10
|
+
exclude: [...configDefaults.exclude, 'e2e/*'],
|
|
11
|
+
root: fileURLToPath(new URL('./', import.meta.url)),
|
|
12
|
+
coverage: {
|
|
13
|
+
provider: 'v8',
|
|
14
|
+
include: ['**/src/**'],
|
|
15
|
+
exclude: ['**/index.ts']
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
)
|