@nexxtmove/ui 0.1.21 → 0.1.23

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.
Files changed (66) hide show
  1. package/dist/index.d.ts +75 -8
  2. package/dist/index.js +2415 -252
  3. package/dist/nuxt.d.ts +1 -0
  4. package/dist/nuxt.js +49 -0
  5. package/package.json +23 -13
  6. package/src/assets/images/Template_aanvragen.jpg +0 -0
  7. package/src/assets/svg/type_post.svg +1 -0
  8. package/src/assets/svg/type_reel.svg +54 -0
  9. package/src/assets/svg/type_story.svg +46 -0
  10. package/src/assets/svg/type_tiktok.svg +1 -0
  11. package/src/assets/video/Template_aanvragen.mp4 +0 -0
  12. package/src/components/AnimatedNumber/AnimatedNumber.stories.ts +15 -0
  13. package/src/components/AnimatedNumber/AnimatedNumber.test.ts +56 -0
  14. package/src/components/AnimatedNumber/AnimatedNumber.vue +61 -0
  15. package/src/components/Button/Button.stories.ts +212 -0
  16. package/src/components/Button/Button.test.ts +318 -0
  17. package/src/components/Button/Button.vue +67 -0
  18. package/src/components/Calendar/Calendar.stories.ts +91 -0
  19. package/src/components/Calendar/Calendar.test.ts +269 -0
  20. package/src/components/Calendar/Calendar.vue +221 -0
  21. package/src/components/Calendar/_CalendarDayView.test.ts +145 -0
  22. package/src/components/Calendar/_CalendarDayView.vue +156 -0
  23. package/src/components/Calendar/_CalendarHeader.test.ts +86 -0
  24. package/src/components/Calendar/_CalendarHeader.vue +123 -0
  25. package/src/components/Calendar/_CalendarMonthView.test.ts +68 -0
  26. package/src/components/Calendar/_CalendarMonthView.vue +70 -0
  27. package/src/components/Calendar/_CalendarYearView.vue +77 -0
  28. package/src/components/Calendar/calendar.types.ts +10 -0
  29. package/src/components/Chip/Chip.stories.ts +42 -0
  30. package/src/components/Chip/Chip.test.ts +51 -0
  31. package/src/components/Chip/Chip.vue +37 -0
  32. package/src/components/DatePicker/DatePicker.stories.ts +149 -0
  33. package/src/components/DatePicker/DatePicker.test.ts +191 -0
  34. package/src/components/DatePicker/DatePicker.vue +142 -0
  35. package/src/components/Header/Header.stories.ts +48 -0
  36. package/src/components/Header/Header.test.ts +169 -0
  37. package/src/components/Header/Header.vue +42 -0
  38. package/src/components/Icon/Icon.stories.ts +50 -0
  39. package/src/components/Icon/Icon.test.ts +73 -0
  40. package/src/components/Icon/Icon.vue +20 -0
  41. package/src/components/InfoBlock/InfoBlock.stories.ts +90 -0
  42. package/src/components/InfoBlock/InfoBlock.test.ts +101 -0
  43. package/src/components/InfoBlock/InfoBlock.vue +70 -0
  44. package/src/components/ProgressBar/ProgressBar.stories.ts +30 -0
  45. package/src/components/ProgressBar/ProgressBar.test.ts +314 -0
  46. package/src/components/ProgressBar/ProgressBar.vue +102 -0
  47. package/src/components/SocialIcons/SocialIcons.stories.ts +34 -0
  48. package/src/components/SocialIcons/SocialIcons.test.ts +58 -0
  49. package/src/components/SocialIcons/SocialIcons.vue +58 -0
  50. package/src/components/SocialMediaCustomTemplate/SocialMediaCustomTemplate.stories.ts +11 -0
  51. package/src/components/SocialMediaCustomTemplate/SocialMediaCustomTemplate.test.ts +131 -0
  52. package/src/components/SocialMediaCustomTemplate/SocialMediaCustomTemplate.vue +55 -0
  53. package/src/components/SocialMediaTemplate/SocialMediaTemplate.stories.ts +71 -0
  54. package/src/components/SocialMediaTemplate/SocialMediaTemplate.test.ts +466 -0
  55. package/src/components/SocialMediaTemplate/SocialMediaTemplate.vue +130 -0
  56. package/src/components/SocialMediaType/SocialMediaType.stories.ts +43 -0
  57. package/src/components/SocialMediaType/SocialMediaType.test.ts +126 -0
  58. package/src/components/SocialMediaType/SocialMediaType.vue +117 -0
  59. package/src/components/StepperHeader/StepperHeader.stories.ts +47 -0
  60. package/src/components/StepperHeader/StepperHeader.test.ts +244 -0
  61. package/src/components/StepperHeader/StepperHeader.vue +37 -0
  62. package/src/components.json +16 -0
  63. package/src/env.d.ts +23 -0
  64. package/src/index.css +2 -0
  65. package/src/index.ts +15 -0
  66. package/src/nuxt.ts +50 -0
@@ -0,0 +1,131 @@
1
+ import { mount } from '@vue/test-utils'
2
+ import { describe, it, expect, vi } from 'vitest'
3
+ import SocialMediaCustomTemplate from './SocialMediaCustomTemplate.vue'
4
+
5
+ describe('SocialMediaCustomTemplate', () => {
6
+ it('renders correctly with video and poster', () => {
7
+ const wrapper = mount(SocialMediaCustomTemplate)
8
+ const video = wrapper.find('video')
9
+
10
+ expect(wrapper.element.tagName).toBe('BUTTON')
11
+ expect(video.exists()).toBe(true)
12
+ // Check video properties directly
13
+ const videoElement = video.element as HTMLVideoElement
14
+ expect(videoElement.muted).toBe(true)
15
+ expect(video.attributes('poster')).toContain('Template_aanvragen.jpg')
16
+ })
17
+
18
+ it('handles video ended event correctly', async () => {
19
+ const wrapper = mount(SocialMediaCustomTemplate)
20
+ const videoElement = wrapper.find('video').element as HTMLVideoElement
21
+ const loadSpy = vi.spyOn(videoElement, 'load').mockImplementation(() => {})
22
+
23
+ // Simulate video ending
24
+ await wrapper.find('video').trigger('ended')
25
+
26
+ expect(videoElement.currentTime).toBe(0)
27
+ expect(loadSpy).toHaveBeenCalled()
28
+ })
29
+
30
+ it('plays video on mouseenter after first play', async () => {
31
+ const wrapper = mount(SocialMediaCustomTemplate)
32
+ const videoElement = wrapper.find('video').element as HTMLVideoElement
33
+ const playSpy = vi.spyOn(videoElement, 'play').mockImplementation(() => Promise.resolve())
34
+
35
+ // Set state to hasPlayedOnce
36
+ await wrapper.find('video').trigger('ended')
37
+
38
+ // Trigger mouseenter
39
+ await wrapper.trigger('mouseenter')
40
+
41
+ expect(playSpy).toHaveBeenCalled()
42
+ })
43
+
44
+ it('pauses video on mouseleave after first play', async () => {
45
+ const wrapper = mount(SocialMediaCustomTemplate)
46
+ const videoElement = wrapper.find('video').element as HTMLVideoElement
47
+ const pauseSpy = vi.spyOn(videoElement, 'pause')
48
+
49
+ // Set state to hasPlayedOnce
50
+ await wrapper.find('video').trigger('ended')
51
+
52
+ // Trigger mouseleave
53
+ await wrapper.trigger('mouseleave')
54
+
55
+ expect(pauseSpy).toHaveBeenCalled()
56
+ })
57
+
58
+ it('sets loop to true after first play', async () => {
59
+ const wrapper = mount(SocialMediaCustomTemplate)
60
+ const video = wrapper.find('video')
61
+ const videoElement = video.element as HTMLVideoElement
62
+
63
+ expect(videoElement.loop).toBe(false)
64
+
65
+ // Simulate video ending
66
+ await video.trigger('ended')
67
+
68
+ expect(videoElement.loop).toBe(true)
69
+ })
70
+
71
+ it('does not play on mouseenter before first play has ended', async () => {
72
+ const wrapper = mount(SocialMediaCustomTemplate)
73
+ const videoElement = wrapper.find('video').element as HTMLVideoElement
74
+ const playSpy = vi.spyOn(videoElement, 'play')
75
+
76
+ await wrapper.trigger('mouseenter')
77
+
78
+ expect(playSpy).not.toHaveBeenCalled()
79
+ })
80
+
81
+ it('does not pause on mouseleave before first play has ended', async () => {
82
+ const wrapper = mount(SocialMediaCustomTemplate)
83
+ const videoElement = wrapper.find('video').element as HTMLVideoElement
84
+ const pauseSpy = vi.spyOn(videoElement, 'pause')
85
+
86
+ await wrapper.trigger('mouseleave')
87
+
88
+ expect(pauseSpy).not.toHaveBeenCalled()
89
+ })
90
+
91
+ it('does not call handleEnded if videoRef is null', async () => {
92
+ const wrapper = mount(SocialMediaCustomTemplate)
93
+ // @ts-expect-error - manually setting ref to null for test
94
+ wrapper.vm.videoRef = null
95
+
96
+ // Trigger handleEnded directly (internally)
97
+ // @ts-expect-error - calling internal method
98
+ wrapper.vm.handleEnded()
99
+
100
+ // @ts-expect-error - checking internal state
101
+ expect(wrapper.vm.hasPlayedOnce).toBe(false)
102
+ })
103
+
104
+ it('internal methods do nothing if videoRef is null', async () => {
105
+ const wrapper = mount(SocialMediaCustomTemplate)
106
+ // @ts-expect-error - manually setting ref to null for test
107
+ wrapper.vm.videoRef = null
108
+ // @ts-expect-error - manually setting hasPlayedOnce for branch test
109
+ wrapper.vm.hasPlayedOnce = true
110
+
111
+ // Trigger handleMouseEnter directly (internally)
112
+ // @ts-expect-error - calling internal method
113
+ wrapper.vm.handleMouseEnter()
114
+ // Trigger handleMouseLeave directly (internally)
115
+ // @ts-expect-error - calling internal method
116
+ wrapper.vm.handleMouseLeave()
117
+
118
+ // No errors should occur
119
+ })
120
+
121
+ it('plays onMounted if videoRef is valid', async () => {
122
+ const wrapper = mount(SocialMediaCustomTemplate)
123
+ const videoElement = wrapper.find('video').element as HTMLVideoElement
124
+ const playSpy = vi.spyOn(videoElement, 'play').mockImplementation(() => Promise.resolve())
125
+
126
+ // Simulate onMounted behavior by calling it again (it already ran once on mount)
127
+ // @ts-expect-error - manually calling onMounted setup code
128
+ wrapper.vm.handleMouseEnter() // hasPlayedOnce is false, should not play
129
+ expect(playSpy).not.toHaveBeenCalled()
130
+ })
131
+ })
@@ -0,0 +1,55 @@
1
+ <script lang="ts" setup>
2
+ import missingVideo from '../../assets/video/Template_aanvragen.mp4'
3
+ import { ref, onMounted } from 'vue'
4
+
5
+ defineOptions({
6
+ name: 'NexxtSocialMediaCustomTemplate',
7
+ })
8
+
9
+ const videoRef = ref<HTMLVideoElement>()
10
+ const hasPlayedOnce = ref(false)
11
+
12
+ const handleEnded = () => {
13
+ if (videoRef.value) {
14
+ videoRef.value.load()
15
+ hasPlayedOnce.value = true
16
+ }
17
+ }
18
+
19
+ const handleMouseEnter = () => {
20
+ if (hasPlayedOnce.value && videoRef.value) {
21
+ videoRef.value.play()
22
+ }
23
+ }
24
+
25
+ const handleMouseLeave = () => {
26
+ if (hasPlayedOnce.value && videoRef.value) {
27
+ videoRef.value.pause()
28
+ }
29
+ }
30
+
31
+ onMounted(() => {
32
+ if (videoRef.value) {
33
+ videoRef.value.play()
34
+ }
35
+ })
36
+ </script>
37
+
38
+ <template>
39
+ <button
40
+ class="flex aspect-9/16 w-64 cursor-pointer items-center justify-center overflow-hidden rounded-3xl bg-gray-50 outline-1 -outline-offset-1 outline-gray-200 transition-all focus-visible:outline-2 focus-visible:outline-cornflower-blue-600"
41
+ @mouseenter="handleMouseEnter"
42
+ @mouseleave="handleMouseLeave"
43
+ >
44
+ <video
45
+ ref="videoRef"
46
+ :src="missingVideo"
47
+ muted
48
+ playsinline
49
+ :loop="hasPlayedOnce"
50
+ class="h-full w-full object-cover"
51
+ poster="../../assets/images/Template_aanvragen.jpg"
52
+ @ended.once="handleEnded"
53
+ />
54
+ </button>
55
+ </template>
@@ -0,0 +1,71 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite'
2
+ import SocialMediaTemplate from './SocialMediaTemplate.vue'
3
+
4
+ export default {
5
+ title: 'Components/Organisms/Social Media Template',
6
+ component: SocialMediaTemplate,
7
+ argTypes: {
8
+ variant: {
9
+ control: 'select',
10
+ options: ['post', 'video', 'slideshow'],
11
+ },
12
+ selected: {
13
+ control: 'boolean',
14
+ },
15
+ muted: {
16
+ control: 'boolean',
17
+ },
18
+ },
19
+ parameters: {
20
+ design: {
21
+ type: 'figma',
22
+ url: 'https://www.figma.com/design/CdbFJ7qUga6mtjagcPDvYK/Design-System?node-id=578-340&t=CbHvOQfEMIr7M5mO-11',
23
+ },
24
+ },
25
+ } satisfies Meta<typeof SocialMediaTemplate>
26
+
27
+ type Story = StoryObj<typeof SocialMediaTemplate>
28
+
29
+ export const Post: Story = {
30
+ args: {
31
+ variant: 'post',
32
+ media: 'https://loremflickr.com/400/600/house',
33
+ mediaType: 'image',
34
+ name: 'Amsterdam',
35
+ type: 'Woning',
36
+ selected: false,
37
+ },
38
+ }
39
+
40
+ export const Video: Story = {
41
+ args: {
42
+ variant: 'video',
43
+ media: '/barcelona.mp4',
44
+ mediaType: 'video',
45
+ muted: true,
46
+ name: 'Barcelona',
47
+ type: 'Woning',
48
+ selected: false,
49
+ },
50
+ }
51
+
52
+ export const Slideshow: Story = {
53
+ args: {
54
+ variant: 'slideshow',
55
+ media: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e',
56
+ mediaType: 'image',
57
+ name: 'Stockholm',
58
+ type: 'Bedrijfsunit',
59
+ },
60
+ }
61
+
62
+ export const Selected: Story = {
63
+ args: {
64
+ variant: 'post',
65
+ media: 'https://images.unsplash.com/photo-1551963831-b3b1ca40c98e',
66
+ mediaType: 'image',
67
+ name: 'Amsterdam',
68
+ type: 'Woning',
69
+ selected: true,
70
+ },
71
+ }