@mirweb/mir-web-components 1.15.3 → 2.0.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.
Files changed (184) hide show
  1. package/README.md +2 -2
  2. package/dist/assets/index-Cl4fzBs2.js +17 -0
  3. package/dist/assets/scss/globals.scss +231 -0
  4. package/dist/assets/scss/index.scss +4 -0
  5. package/dist/assets/scss/normalize.scss +393 -0
  6. package/dist/assets/scss/reset.scss +102 -0
  7. package/dist/assets/scss/variables.scss +95 -0
  8. package/dist/components/atoms/button/button.vue +81 -0
  9. package/dist/components/atoms/checkbox/checkbox.vue +125 -0
  10. package/dist/components/atoms/chip/chip.vue +55 -0
  11. package/dist/components/atoms/dropdown/dropdown.vue +490 -0
  12. package/dist/components/atoms/image/image.vue +42 -0
  13. package/dist/components/atoms/label/label.vue +52 -0
  14. package/dist/components/atoms/link/link.vue +166 -0
  15. package/dist/components/atoms/radio-button/radio-button.vue +110 -0
  16. package/dist/components/atoms/select/select.vue +116 -0
  17. package/dist/components/atoms/select-multiple/select-multiple.vue +210 -0
  18. package/dist/components/atoms/slider/slider.vue +322 -0
  19. package/dist/components/atoms/text-field/text-field.vue +273 -0
  20. package/dist/components/atoms/textarea/textarea.vue +179 -0
  21. package/dist/components/atoms/video/video.vue +98 -0
  22. package/dist/components/blocks/accordion/accordion.vue +222 -0
  23. package/dist/components/blocks/card-display/card-display.vue +125 -0
  24. package/dist/components/blocks/column-grid/column-grid.vue +201 -0
  25. package/dist/components/blocks/facts/facts.vue +156 -0
  26. package/dist/components/blocks/features/features.vue +176 -0
  27. package/dist/components/blocks/flashcards/flashcards.vue +212 -0
  28. package/dist/components/blocks/form-script/form-script.vue +172 -0
  29. package/dist/components/blocks/frontpage-hero/frontpage-hero.vue +214 -0
  30. package/dist/components/blocks/headline/headline.vue +93 -0
  31. package/dist/components/blocks/hero/hero.vue +173 -0
  32. package/dist/components/blocks/image/image.vue +93 -0
  33. package/dist/components/blocks/image-gallery/image-gallery.vue +289 -0
  34. package/dist/components/blocks/logo-wall/logo-wall.vue +125 -0
  35. package/dist/components/blocks/micro-stories/micro-stories.vue +316 -0
  36. package/dist/components/blocks/pallet-jack/pallet-jack.vue +440 -0
  37. package/dist/components/blocks/policy/policy.vue +106 -0
  38. package/dist/components/blocks/product-hero/product-hero.vue +140 -0
  39. package/dist/components/blocks/promo/promo.vue +403 -0
  40. package/dist/components/blocks/quote/quote.vue +127 -0
  41. package/dist/components/blocks/rich-text/rich-text-columns.vue +159 -0
  42. package/dist/components/blocks/rich-text/rich-text.vue +296 -0
  43. package/dist/components/blocks/timeline/timeline.vue +232 -0
  44. package/dist/components/blocks/vimeo/vimeo.vue +52 -0
  45. package/dist/components/index.ts +51 -0
  46. package/dist/components/molecules/address/address.vue +123 -0
  47. package/dist/components/molecules/bullet-list/bullet-list.vue +99 -0
  48. package/dist/components/molecules/card/card.vue +302 -0
  49. package/dist/components/molecules/column-card/column-card.vue +178 -0
  50. package/dist/components/molecules/event-card/event-card.vue +111 -0
  51. package/dist/components/molecules/flashcard/flashcard.vue +293 -0
  52. package/dist/components/molecules/modal/modal.vue +113 -0
  53. package/dist/components/molecules/text-card/text-card.vue +74 -0
  54. package/dist/components/organisms/404/404.vue +79 -0
  55. package/dist/components/organisms/filter/filter.vue +89 -0
  56. package/dist/components/organisms/footer/footer.vue +356 -0
  57. package/dist/components/organisms/header/header.vue +754 -0
  58. package/dist/components/organisms/language-switcher/language-switcher.vue +68 -0
  59. package/dist/components/organisms/pagination/pagination.vue +85 -0
  60. package/dist/components/organisms/search/search.vue +153 -0
  61. package/dist/components/templates/404-error-page.vue +0 -0
  62. package/dist/directives/clickOutside.ts +15 -0
  63. package/dist/fonts/OpenSans-Light.woff2 +0 -0
  64. package/dist/fonts/OpenSans-Medium.woff2 +0 -0
  65. package/dist/fonts/OpenSans-Regular.woff2 +0 -0
  66. package/dist/fonts/OpenSans-SemiBold.woff2 +0 -0
  67. package/dist/fonts/Oscine_Bd.woff2 +0 -0
  68. package/dist/fonts/Oscine_Lt.woff2 +0 -0
  69. package/dist/fonts/Oscine_Rg.woff2 +0 -0
  70. package/dist/index.html +12 -0
  71. package/dist/main.css +1 -0
  72. package/package.json +8 -10
  73. package/dist/components/atoms/button/button.vue.d.ts +0 -5
  74. package/dist/components/atoms/button/button.vue.d.ts.map +0 -1
  75. package/dist/components/atoms/checkbox/checkbox.vue.d.ts +0 -5
  76. package/dist/components/atoms/checkbox/checkbox.vue.d.ts.map +0 -1
  77. package/dist/components/atoms/chip/chip.vue.d.ts +0 -5
  78. package/dist/components/atoms/chip/chip.vue.d.ts.map +0 -1
  79. package/dist/components/atoms/dropdown/dropdown.vue.d.ts +0 -5
  80. package/dist/components/atoms/dropdown/dropdown.vue.d.ts.map +0 -1
  81. package/dist/components/atoms/image/image.vue.d.ts +0 -5
  82. package/dist/components/atoms/image/image.vue.d.ts.map +0 -1
  83. package/dist/components/atoms/label/label.vue.d.ts +0 -5
  84. package/dist/components/atoms/label/label.vue.d.ts.map +0 -1
  85. package/dist/components/atoms/link/link.vue.d.ts +0 -5
  86. package/dist/components/atoms/link/link.vue.d.ts.map +0 -1
  87. package/dist/components/atoms/radio-button/radio-button.vue.d.ts +0 -5
  88. package/dist/components/atoms/radio-button/radio-button.vue.d.ts.map +0 -1
  89. package/dist/components/atoms/select/select.vue.d.ts +0 -5
  90. package/dist/components/atoms/select/select.vue.d.ts.map +0 -1
  91. package/dist/components/atoms/select-multiple/select-multiple.vue.d.ts +0 -5
  92. package/dist/components/atoms/select-multiple/select-multiple.vue.d.ts.map +0 -1
  93. package/dist/components/atoms/slider/slider.vue.d.ts +0 -5
  94. package/dist/components/atoms/slider/slider.vue.d.ts.map +0 -1
  95. package/dist/components/atoms/text-field/text-field.vue.d.ts +0 -5
  96. package/dist/components/atoms/text-field/text-field.vue.d.ts.map +0 -1
  97. package/dist/components/atoms/textarea/textarea.vue.d.ts +0 -5
  98. package/dist/components/atoms/textarea/textarea.vue.d.ts.map +0 -1
  99. package/dist/components/atoms/video/video.vue.d.ts +0 -5
  100. package/dist/components/atoms/video/video.vue.d.ts.map +0 -1
  101. package/dist/components/blocks/accordion/accordion.vue.d.ts +0 -5
  102. package/dist/components/blocks/accordion/accordion.vue.d.ts.map +0 -1
  103. package/dist/components/blocks/card-display/card-display.vue.d.ts +0 -6
  104. package/dist/components/blocks/card-display/card-display.vue.d.ts.map +0 -1
  105. package/dist/components/blocks/column-grid/column-grid.vue.d.ts +0 -5
  106. package/dist/components/blocks/column-grid/column-grid.vue.d.ts.map +0 -1
  107. package/dist/components/blocks/facts/facts.vue.d.ts +0 -5
  108. package/dist/components/blocks/facts/facts.vue.d.ts.map +0 -1
  109. package/dist/components/blocks/features/features.vue.d.ts +0 -5
  110. package/dist/components/blocks/features/features.vue.d.ts.map +0 -1
  111. package/dist/components/blocks/flashcards/flashcards.vue.d.ts +0 -5
  112. package/dist/components/blocks/flashcards/flashcards.vue.d.ts.map +0 -1
  113. package/dist/components/blocks/form-script/form-script.vue.d.ts +0 -5
  114. package/dist/components/blocks/form-script/form-script.vue.d.ts.map +0 -1
  115. package/dist/components/blocks/frontpage-hero/frontpage-hero.vue.d.ts +0 -5
  116. package/dist/components/blocks/frontpage-hero/frontpage-hero.vue.d.ts.map +0 -1
  117. package/dist/components/blocks/headline/headline.vue.d.ts +0 -5
  118. package/dist/components/blocks/headline/headline.vue.d.ts.map +0 -1
  119. package/dist/components/blocks/hero/hero.vue.d.ts +0 -5
  120. package/dist/components/blocks/hero/hero.vue.d.ts.map +0 -1
  121. package/dist/components/blocks/image/image.vue.d.ts +0 -5
  122. package/dist/components/blocks/image/image.vue.d.ts.map +0 -1
  123. package/dist/components/blocks/image-gallery/image-gallery.vue.d.ts +0 -5
  124. package/dist/components/blocks/image-gallery/image-gallery.vue.d.ts.map +0 -1
  125. package/dist/components/blocks/logo-wall/logo-wall.vue.d.ts +0 -5
  126. package/dist/components/blocks/logo-wall/logo-wall.vue.d.ts.map +0 -1
  127. package/dist/components/blocks/micro-stories/micro-stories.vue.d.ts +0 -5
  128. package/dist/components/blocks/micro-stories/micro-stories.vue.d.ts.map +0 -1
  129. package/dist/components/blocks/pallet-jack/pallet-jack.vue.d.ts +0 -5
  130. package/dist/components/blocks/pallet-jack/pallet-jack.vue.d.ts.map +0 -1
  131. package/dist/components/blocks/policy/policy.vue.d.ts +0 -4
  132. package/dist/components/blocks/policy/policy.vue.d.ts.map +0 -1
  133. package/dist/components/blocks/product-hero/product-hero.vue.d.ts +0 -5
  134. package/dist/components/blocks/product-hero/product-hero.vue.d.ts.map +0 -1
  135. package/dist/components/blocks/promo/promo.vue.d.ts +0 -5
  136. package/dist/components/blocks/promo/promo.vue.d.ts.map +0 -1
  137. package/dist/components/blocks/quote/quote.vue.d.ts +0 -5
  138. package/dist/components/blocks/quote/quote.vue.d.ts.map +0 -1
  139. package/dist/components/blocks/rich-text/rich-text-columns.vue.d.ts +0 -4
  140. package/dist/components/blocks/rich-text/rich-text-columns.vue.d.ts.map +0 -1
  141. package/dist/components/blocks/rich-text/rich-text.vue.d.ts +0 -5
  142. package/dist/components/blocks/rich-text/rich-text.vue.d.ts.map +0 -1
  143. package/dist/components/blocks/timeline/timeline.vue.d.ts +0 -5
  144. package/dist/components/blocks/timeline/timeline.vue.d.ts.map +0 -1
  145. package/dist/components/blocks/vimeo/vimeo.vue.d.ts +0 -5
  146. package/dist/components/blocks/vimeo/vimeo.vue.d.ts.map +0 -1
  147. package/dist/components/index.d.ts +0 -51
  148. package/dist/components/main.d.ts +0 -59
  149. package/dist/components/molecules/address/address.vue.d.ts +0 -5
  150. package/dist/components/molecules/address/address.vue.d.ts.map +0 -1
  151. package/dist/components/molecules/bullet-list/bullet-list.vue.d.ts +0 -5
  152. package/dist/components/molecules/bullet-list/bullet-list.vue.d.ts.map +0 -1
  153. package/dist/components/molecules/card/card.vue.d.ts +0 -5
  154. package/dist/components/molecules/card/card.vue.d.ts.map +0 -1
  155. package/dist/components/molecules/column-card/column-card.vue.d.ts +0 -5
  156. package/dist/components/molecules/column-card/column-card.vue.d.ts.map +0 -1
  157. package/dist/components/molecules/event-card/event-card.vue.d.ts +0 -5
  158. package/dist/components/molecules/event-card/event-card.vue.d.ts.map +0 -1
  159. package/dist/components/molecules/flashcard/flashcard.vue.d.ts +0 -5
  160. package/dist/components/molecules/flashcard/flashcard.vue.d.ts.map +0 -1
  161. package/dist/components/molecules/modal/modal.vue.d.ts +0 -5
  162. package/dist/components/molecules/modal/modal.vue.d.ts.map +0 -1
  163. package/dist/components/molecules/text-card/text-card.vue.d.ts +0 -5
  164. package/dist/components/molecules/text-card/text-card.vue.d.ts.map +0 -1
  165. package/dist/components/organisms/404/404.vue.d.ts +0 -5
  166. package/dist/components/organisms/404/404.vue.d.ts.map +0 -1
  167. package/dist/components/organisms/filter/filter.vue.d.ts +0 -5
  168. package/dist/components/organisms/filter/filter.vue.d.ts.map +0 -1
  169. package/dist/components/organisms/footer/footer.vue.d.ts +0 -5
  170. package/dist/components/organisms/footer/footer.vue.d.ts.map +0 -1
  171. package/dist/components/organisms/header/header.vue.d.ts +0 -6
  172. package/dist/components/organisms/header/header.vue.d.ts.map +0 -1
  173. package/dist/components/organisms/language-switcher/language-switcher.vue.d.ts +0 -5
  174. package/dist/components/organisms/language-switcher/language-switcher.vue.d.ts.map +0 -1
  175. package/dist/components/organisms/pagination/pagination.vue.d.ts +0 -5
  176. package/dist/components/organisms/pagination/pagination.vue.d.ts.map +0 -1
  177. package/dist/components/organisms/search/search.vue.d.ts +0 -4
  178. package/dist/components/organisms/search/search.vue.d.ts.map +0 -1
  179. package/dist/directives/clickOutside.d.ts +0 -3
  180. package/dist/main.d.ts +0 -1
  181. package/dist/mir-web-components.cjs.js +0 -1
  182. package/dist/mir-web-components.css +0 -1
  183. package/dist/mir-web-components.es.js +0 -3187
  184. package/dist/mir-web-components.umd.js +0 -2
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <div class="label__wrapper">
3
+ <span
4
+ :aria-label="ariaLabel"
5
+ :label-dark="labelDark"
6
+ :class="labelDark ? 'label--dark' : 'label--light'"
7
+ >
8
+ {{ text }}
9
+ </span>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ import { computed } from "vue";
15
+
16
+ export type Props = {
17
+ text: string;
18
+ labelDark?: boolean;
19
+ };
20
+
21
+ const props = withDefaults(defineProps<Props>(), {
22
+ labelDark: false,
23
+ });
24
+
25
+ const ariaLabel = computed(() => `Label: ${props.text}`);
26
+ </script>
27
+
28
+ <style lang="scss" scoped>
29
+ @use "../../../assets/scss/variables.scss" as *;
30
+ .label {
31
+ &--dark {
32
+ background-color: $blue-800;
33
+ color: $white;
34
+ }
35
+ &--light {
36
+ background-color: $blue-200;
37
+ color: $blue-900;
38
+ }
39
+
40
+ &__wrapper {
41
+ span {
42
+ display: inline-block;
43
+ height: 27px;
44
+ padding: 0px 10px;
45
+ font-size: $font-size-xxsm;
46
+ line-height: $line-height-md;
47
+ font-family: $font-opensans;
48
+ border-radius: 3px;
49
+ }
50
+ }
51
+ }
52
+ </style>
@@ -0,0 +1,166 @@
1
+ <template>
2
+ <div class="link__wrapper">
3
+ <div
4
+ v-bind="attrs"
5
+ class="mir-link"
6
+ :class="[
7
+ selectedLinkType,
8
+ disabled ? 'disabled' : '',
9
+ selectedUnderline,
10
+ arrow ? 'link-arrow' : '',
11
+ ]"
12
+ >
13
+ <slot></slot>
14
+ </div>
15
+ </div>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ import { computed, toRefs } from "vue";
20
+
21
+ const LINKTYPES = {
22
+ primary: "mir-link--btn button button--primary",
23
+ primary_dark: "mir-link--btn button button--primary-dark",
24
+ secondary: "mir-link--btn button button--secondary",
25
+ secondary_dark: "mir-link--btn button button--secondary-dark",
26
+ regular: "regular-link",
27
+ regular_dark: "regular-link-dark",
28
+ regular_light: "regular-link-light",
29
+ regular_blue: "regular-link-blue",
30
+ } as const;
31
+
32
+ type LinkType = keyof typeof LINKTYPES;
33
+
34
+ const UNDERLINE = {
35
+ hover: "underline-hover",
36
+ true: "add-underline",
37
+ false: "remove-underline",
38
+ } as const;
39
+
40
+ type Underline = keyof typeof UNDERLINE;
41
+
42
+ export type Props = {
43
+ linkType: LinkType;
44
+ arrow?: boolean;
45
+ underline?: Underline;
46
+ disabled?: boolean;
47
+ };
48
+
49
+ const props = withDefaults(defineProps<Props>(), {
50
+ linkType: "regular",
51
+ arrow: false,
52
+ underline: "false",
53
+ disabled: false,
54
+ });
55
+
56
+ const selectedLinkType = computed(() => LINKTYPES[props.linkType]);
57
+ const selectedUnderline = computed(() => UNDERLINE[props.underline]);
58
+
59
+ const attrs = computed(() => {
60
+ const { ...rest } = toRefs(props);
61
+ return rest;
62
+ });
63
+ </script>
64
+
65
+ <style lang="scss">
66
+ @use "../../../assets/scss/variables.scss" as *;
67
+ .link {
68
+ &__wrapper {
69
+ .mir-link {
70
+ a {
71
+ display: inline-block;
72
+ cursor: pointer;
73
+ width: fit-content;
74
+ }
75
+ &--btn {
76
+ a {
77
+ font-size: $font-size-xsm;
78
+ font-family: $font-opensans;
79
+ font-weight: 600;
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ .link-arrow {
87
+ a {
88
+ position: relative;
89
+ &:hover::after {
90
+ transform: translate(5px);
91
+ }
92
+
93
+ &::after {
94
+ content: "";
95
+ background-image: url("https://a.storyblok.com/f/230581/5x10/53d983a1cb/link-arrow.svg?cv=1695125713966");
96
+ background-repeat: no-repeat;
97
+ position: absolute;
98
+ height: 10px;
99
+ width: 5px;
100
+ bottom: 4.2px;
101
+ margin-left: 7px;
102
+ transition: transform 0.2s ease-out;
103
+ }
104
+ }
105
+ }
106
+
107
+ @keyframes slideRight {
108
+ 0% {
109
+ }
110
+ 100% {
111
+ transform: translate(5px);
112
+ }
113
+ }
114
+
115
+ .remove-underline a {
116
+ text-decoration: none;
117
+ }
118
+ .add-underline a {
119
+ text-decoration: underline;
120
+ }
121
+ .underline-hover a {
122
+ text-decoration: none;
123
+ &:hover {
124
+ text-decoration: underline;
125
+ }
126
+ }
127
+
128
+ .regular-link a {
129
+ color: $blue-900;
130
+ &:hover,
131
+ &:active,
132
+ &:focus,
133
+ &:target {
134
+ transition: $transition-color;
135
+ color: $blue-600;
136
+ }
137
+ }
138
+ .regular-link-dark a {
139
+ color: $white;
140
+ }
141
+ .regular-link-light a {
142
+ color: $blue-600;
143
+ font-weight: 500;
144
+ &:hover,
145
+ &:active,
146
+ &:focus,
147
+ &:target {
148
+ transition: $transition-color;
149
+ color: $blue-700;
150
+ }
151
+ }
152
+
153
+ .regular-link-blue a {
154
+ color: $blue-800;
155
+ }
156
+
157
+ .regular-link:focus a {
158
+ outline: 2px solid $blue-400;
159
+ outline-offset: 2px;
160
+ }
161
+
162
+ .disabled a {
163
+ opacity: 0.5;
164
+ pointer-events: none;
165
+ }
166
+ </style>
@@ -0,0 +1,110 @@
1
+ <template>
2
+ <div class="radio__wrapper" :class="disabled ? 'disabled' : ''">
3
+ <input
4
+ :id="id"
5
+ type="radio"
6
+ :name="name"
7
+ :value="value"
8
+ :checked="checked"
9
+ :disabled="disabled"
10
+ :required="required"
11
+ class="radio__radio"
12
+ @change="onChange"
13
+ />
14
+ <label :for="id" class="radio__label" :class="required ? 'required' : ''">
15
+ <span class="radiomark"></span>
16
+ <slot></slot>
17
+ </label>
18
+ </div>
19
+ </template>
20
+
21
+ <script lang="ts" setup>
22
+ export type Props = {
23
+ name: string;
24
+ value: string | number | boolean;
25
+ checked: boolean;
26
+ disabled: boolean;
27
+ id: string;
28
+ required: boolean;
29
+ };
30
+
31
+ withDefaults(defineProps<Props>(), {
32
+ name: "radio",
33
+ value: "value",
34
+ checked: false,
35
+ disabled: false,
36
+ id: "radio",
37
+ required: false,
38
+ });
39
+
40
+ const emit = defineEmits(["input"]);
41
+
42
+ const onChange = (event: Event) => {
43
+ const target = event.target as HTMLInputElement;
44
+ emit("input", target.checked);
45
+ };
46
+ </script>
47
+
48
+ <style lang="scss" scoped>
49
+ @use "../../../assets/scss/variables.scss" as *;
50
+ .required {
51
+ &::after {
52
+ content: " *";
53
+ display: inline-block;
54
+ }
55
+ }
56
+
57
+ .radio {
58
+ &__radio {
59
+ position: absolute;
60
+ opacity: 0;
61
+ cursor: pointer;
62
+ height: 0;
63
+ width: 0;
64
+
65
+ &:checked ~ .radio__label .radiomark {
66
+ background-color: $blue-800;
67
+ border-color: $grey-400;
68
+ &:after {
69
+ display: block;
70
+ }
71
+ }
72
+ }
73
+
74
+ &__label {
75
+ position: relative;
76
+ padding-left: 30px;
77
+ cursor: pointer;
78
+ user-select: none;
79
+ .radiomark:after {
80
+ left: 4px;
81
+ top: 4px;
82
+ width: 10px;
83
+ height: 10px;
84
+ background-color: $white;
85
+ border-radius: 50%;
86
+ }
87
+ }
88
+ }
89
+
90
+ .radiomark {
91
+ position: absolute;
92
+ top: 0;
93
+ left: 0;
94
+ height: 20px;
95
+ width: 20px;
96
+ background-color: $white;
97
+ border-radius: 50%;
98
+ border: 1px solid $grey-400;
99
+
100
+ &::after {
101
+ content: "";
102
+ position: absolute;
103
+ display: none;
104
+ }
105
+ }
106
+ .disabled {
107
+ opacity: 0.5;
108
+ pointer-events: none;
109
+ }
110
+ </style>
@@ -0,0 +1,116 @@
1
+ <template>
2
+ <div class="select__wrapper">
3
+ <label
4
+ :for="id"
5
+ :class="[required ? 'required' : '', disabled ? 'disabled' : '']"
6
+ >{{ label }}</label
7
+ >
8
+ <select
9
+ :id="id"
10
+ :class="disabled ? 'disabled' : ''"
11
+ :disabled="disabled"
12
+ :name="name"
13
+ :value="modelValue"
14
+ @change="
15
+ $emit('update:modelValue', ($event.target as HTMLSelectElement).value);
16
+ ($event.target as HTMLSelectElement).blur();
17
+ "
18
+ >
19
+ <option
20
+ v-for="option in options"
21
+ :key="option.value"
22
+ :value="option.value"
23
+ >
24
+ {{ option.text }}
25
+ </option>
26
+ </select>
27
+ </div>
28
+ </template>
29
+
30
+ <script setup lang="ts">
31
+ interface Option {
32
+ value: string;
33
+ text: string;
34
+ }
35
+
36
+ export type Props = {
37
+ id: string;
38
+ name: string;
39
+ options: Array<Option>;
40
+ modelValue: string;
41
+ label: string;
42
+ required: boolean;
43
+ disabled: boolean;
44
+ };
45
+
46
+ withDefaults(defineProps<Props>(), {
47
+ required: false,
48
+ disabled: false,
49
+ });
50
+
51
+ defineEmits(["update:modelValue"]);
52
+ </script>
53
+
54
+ <style scoped lang="scss">
55
+ @use "../../../assets/scss/variables.scss" as *;
56
+ .select {
57
+ &__wrapper {
58
+ label {
59
+ font-family: $font-opensans;
60
+ font-size: $font-size-xsm;
61
+ margin-bottom: 7px;
62
+ display: block;
63
+ font-weight: 300;
64
+
65
+ &.disabled {
66
+ color: $grey-600;
67
+ }
68
+
69
+ &.required::after {
70
+ content: "\00a0*";
71
+ display: inline-block;
72
+ }
73
+ }
74
+
75
+ select {
76
+ width: 100%;
77
+ padding: 10px 15px;
78
+ border-radius: $border-radius;
79
+ border: 1px solid $grey-400;
80
+ font-family: $font-opensans;
81
+ font-size: $font-size-xsm;
82
+ line-height: 21px;
83
+ cursor: pointer;
84
+ height: 42px;
85
+ appearance: none;
86
+ font-weight: 300;
87
+ background-image: url("https://a.storyblok.com/f/230581/9x6/8cecdca15f/arrow-down.svg?cv=1695125714195");
88
+ background-repeat: no-repeat;
89
+ background-position: center right 15px;
90
+ background-color: $white;
91
+
92
+ &:hover,
93
+ &:target,
94
+ &:focus,
95
+ &:active {
96
+ border: 1px solid $blue-500;
97
+ border-radius: $border-radius;
98
+ box-shadow: $box-shadow;
99
+ transition: $transition-box-shadow;
100
+ transition: $transition-border;
101
+ }
102
+
103
+ &:focus-within {
104
+ background-image: url("https://a.storyblok.com/f/230581/9x6/0fd60539b9/arrow-up.svg?cv=1695125714780");
105
+ }
106
+
107
+ &.disabled {
108
+ background-color: $grey-100;
109
+ color: $grey-400;
110
+ pointer-events: none;
111
+ fill: $grey-400;
112
+ }
113
+ }
114
+ }
115
+ }
116
+ </style>
@@ -0,0 +1,210 @@
1
+ <template>
2
+ <div v-click-outside="collapse" class="dropdown">
3
+ <button
4
+ class="dropdown-button"
5
+ :class="{ clicked: isOpen }"
6
+ :style="{ 'z-index': isOpen ? 2 : 0 }"
7
+ :aria-expanded="isOpen ? 'true' : 'false'"
8
+ @click="isOpen = !isOpen"
9
+ >
10
+ <slot name="button">{{ label }}</slot>
11
+ </button>
12
+ <div
13
+ :class="{ hidden: !isOpen, 'adjust-height': adjustHeight }"
14
+ class="dropdown-content"
15
+ >
16
+ <atom-checkbox
17
+ v-for="option in options"
18
+ :id="option.value"
19
+ :key="option.value"
20
+ :name="option.text"
21
+ :required="false"
22
+ :disabled="false"
23
+ :value="option.value"
24
+ :checked="
25
+ selectedOptions.includes(option.value) ||
26
+ selectedOptions.includes(option.text)
27
+ "
28
+ @input="handleInput(option.value, option.text)"
29
+ >
30
+ {{ option.text }}
31
+ </atom-checkbox>
32
+ </div>
33
+ </div>
34
+ </template>
35
+
36
+ <script setup lang="ts">
37
+ import AtomCheckbox from "../../atoms/checkbox/checkbox.vue";
38
+ import { ref, computed } from "vue";
39
+ import { vClickOutside } from "../../../directives/clickOutside";
40
+
41
+ const isOpen = ref(false);
42
+
43
+ export type Props = {
44
+ label: string;
45
+ options: Array<{ value: string; text: string }>;
46
+ selectedOptions: Array<string>;
47
+ };
48
+
49
+ const props = withDefaults(defineProps<Props>(), {
50
+ label: "",
51
+ options: () => [],
52
+ selectedOptions: () => [],
53
+ });
54
+
55
+ const emit = defineEmits<{
56
+ (e: "filter", value: string): void;
57
+ (e: "remove-filter", value: string): void;
58
+ }>();
59
+
60
+ /**
61
+ * Handles the input value and text for the select-multiple component.
62
+ * If the value or text is not already selected, it emits a "filter" event with the value.
63
+ * If the value is already selected, it emits a "remove-filter" event with the value.
64
+ *
65
+ * @param {string} value - The value of the selected option.
66
+ * @param {string} text - The text of the selected option.
67
+ */
68
+ function handleInput(value: string, text: string) {
69
+ if (
70
+ !props.selectedOptions.includes(value) &&
71
+ !props.selectedOptions.includes(text)
72
+ ) {
73
+ emit("filter", value);
74
+ } else {
75
+ emit("remove-filter", value);
76
+ }
77
+ }
78
+
79
+ function collapse() {
80
+ isOpen.value = false;
81
+ }
82
+
83
+ const adjustHeight = computed(() => {
84
+ return props.options.length > 8;
85
+ });
86
+ </script>
87
+
88
+ <style lang="scss" scoped>
89
+ @use "../../../assets/scss/variables.scss" as *;
90
+
91
+ .dropdown {
92
+ position: relative;
93
+ display: inline-block;
94
+ flex: 1;
95
+
96
+ @media screen and (min-width: 581px) {
97
+ flex: none;
98
+ }
99
+
100
+ &-button {
101
+ padding: 10px 15px;
102
+ border-radius: 0.4rem;
103
+ border: 1px solid #ced4da;
104
+ font-family: $font-opensans;
105
+ font-size: 0.875rem;
106
+ line-height: 21px;
107
+ cursor: pointer;
108
+ height: 42px;
109
+ appearance: none;
110
+ font-weight: 300;
111
+ background-image: url(https://a.storyblok.com/f/230581/9x6/8cecdca15f/arrow-down.svg?cv=1695125714195);
112
+ background-repeat: no-repeat;
113
+ background-position: center right 15px;
114
+ background-color: #fff;
115
+ width: 100%;
116
+ padding-right: 60px;
117
+ position: relative;
118
+ text-transform: capitalize;
119
+
120
+ &:after {
121
+ content: "";
122
+ display: none;
123
+ position: absolute;
124
+ bottom: -1px;
125
+ left: 0;
126
+ right: 0;
127
+ height: 2px;
128
+ background-color: white;
129
+ z-index: 1;
130
+ }
131
+ &:hover,
132
+ &:focus {
133
+ box-shadow: $box-shadow;
134
+ }
135
+ &:active {
136
+ box-shadow: none;
137
+ }
138
+
139
+ &.clicked {
140
+ box-shadow: none;
141
+
142
+ &:hover,
143
+ &:focus {
144
+ box-shadow: none;
145
+ }
146
+ }
147
+ }
148
+ }
149
+
150
+ .dropdown-content {
151
+ position: absolute;
152
+ background-color: white;
153
+ border: 1px solid #ced4da;
154
+ position: absolute;
155
+ width: 100%;
156
+ top: 42px;
157
+ left: 0;
158
+ z-index: 1;
159
+ width: max-content;
160
+ min-width: 100%;
161
+ border-radius: 0 6px 6px 6px;
162
+ display: flex;
163
+ flex-direction: column;
164
+ flex-wrap: wrap;
165
+ gap: 20px;
166
+ padding: 15px;
167
+
168
+ :deep(.checkbox__label) {
169
+ padding-right: 15px;
170
+ }
171
+
172
+ &.adjust-height {
173
+ max-height: max-content;
174
+
175
+ @include md {
176
+ max-height: 260px;
177
+ padding: 15px 30px 15px 15px;
178
+ }
179
+ }
180
+ }
181
+
182
+ .dropdown-button[aria-expanded="true"]::after {
183
+ display: block;
184
+ position: absolute;
185
+ bottom: -6px;
186
+ left: 0;
187
+ right: 0;
188
+ height: 6px;
189
+ background-color: white;
190
+ }
191
+
192
+ .dropdown-button[aria-expanded="true"] {
193
+ border-radius: 6px 6px 0 0;
194
+ background-image: url(https://a.storyblok.com/f/230581/9x6/0fd60539b9/arrow-up.svg);
195
+ }
196
+
197
+ .checkbox {
198
+ display: flex;
199
+ align-items: center;
200
+ cursor: pointer;
201
+
202
+ :deep(label) {
203
+ display: block;
204
+ width: max-content;
205
+ }
206
+ }
207
+ .hidden {
208
+ display: none;
209
+ }
210
+ </style>