@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/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
+ }
@@ -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
@@ -0,0 +1,3 @@
1
+ export { default as FzNavbar } from './FzNavbar.vue'
2
+
3
+ export * from './types'
package/src/types.ts ADDED
@@ -0,0 +1,8 @@
1
+ export type FzNavbarVariant = 'horizontal' | 'vertical'
2
+
3
+ export interface FzNavbarProps {
4
+ /**
5
+ * The main direction of the navbar
6
+ */
7
+ variant: FzNavbarVariant
8
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "@fiscozen/tsconfig",
3
+ "exclude": ["src/__tests__", "vite.config.ts", "vitest.config.ts"]
4
+ }
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
+ })
@@ -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
+ )