fds-vue-core 6.2.8 → 6.2.11

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fds-vue-core",
3
- "version": "6.2.8",
3
+ "version": "6.2.11",
4
4
  "description": "FDS Vue Core Component Library",
5
5
  "type": "module",
6
6
  "main": "./dist/fds-vue-core.cjs.js",
@@ -64,9 +64,11 @@
64
64
  "@types/node": "22.16.5",
65
65
  "@vitejs/plugin-vue": "6.0.6",
66
66
  "@vitest/browser": "3.2.4",
67
+ "dotenv": "^17.4.2",
67
68
  "eslint-plugin-storybook": "10.1.10",
68
- "fg-devkit": "1.6.1",
69
+ "fg-devkit": "1.6.8",
69
70
  "storybook": "10.2.12",
71
+ "tsx": "^4.21.0",
70
72
  "vite": "7.3.2",
71
73
  "vite-plugin-dts": "4.5.4",
72
74
  "vite-plugin-vue-devtools": "8.1.1",
@@ -1,9 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { addWeeks, getISODay, getISOWeek, isBefore, isSameDay, isSameWeek, startOfISOWeek, subWeeks } from 'date-fns'
3
3
  import { computed, ref, watch } from 'vue'
4
+ import { useFdsI18n } from '../../plugin/useFdsI18n'
5
+
4
6
  import FdsButtonIcon from '../Buttons/FdsButtonIcon/FdsButtonIcon.vue'
5
7
  import FdsSpinner from '../FdsSpinner/FdsSpinner.vue'
6
- import WeekDay from './WeekDay.vue'
7
8
  import type { FdsWeekCalendarProps, WeekDateRange } from './types'
8
9
  import {
9
10
  checkIfDateIsBeforeToday,
@@ -13,6 +14,7 @@ import {
13
14
  getOverlappingMonths,
14
15
  getStartAndEndRangeFromWeek,
15
16
  } from './weekCalendar.utils'
17
+ import WeekDay from './WeekDay.vue'
16
18
 
17
19
  const props = withDefaults(defineProps<FdsWeekCalendarProps>(), {
18
20
  loading: undefined,
@@ -34,6 +36,8 @@ const emit = defineEmits<{
34
36
  (e: 'increment-week'): void
35
37
  }>()
36
38
 
39
+ const { locale, t } = useFdsI18n()
40
+
37
41
  const currentWeek = ref(props.minWeek ?? startOfISOWeek(new Date()))
38
42
  const selectedDay = ref<Date | null>(props.selected ?? null)
39
43
  const slideDirection = ref<'left' | 'right'>('left')
@@ -42,7 +46,10 @@ const weekToRender = computed(() => getDaysInWeek(currentWeek.value))
42
46
  const visibleWeekDays = computed(() => weekToRender.value.filter((day) => getISODay(day) <= 5))
43
47
  const lastWeek = computed(() => getDaysOfLastWeek(subWeeks(currentWeek.value, 1)))
44
48
 
45
- const weekText = computed(() => `${getOverlappingMonths(currentWeek.value)} (vecka ${getISOWeek(currentWeek.value)})`)
49
+ const weekText = computed(
50
+ () =>
51
+ `${getOverlappingMonths(currentWeek.value, locale.value)} (${t('FdsWeekCalendar.week')} ${getISOWeek(currentWeek.value)})`,
52
+ )
46
53
 
47
54
  const lastDayOfPreviousWeek = computed(() => lastWeek.value[lastWeek.value.length - 1])
48
55
  const disableLastWeekInteraction = computed(
@@ -173,13 +180,13 @@ const isTodayDate = (weekDay: Date) => isSameDay(weekDay, new Date())
173
180
  <FdsButtonIcon
174
181
  icon="arrowLeft"
175
182
  :disabled="disableLastWeekInteraction"
176
- aria-label="Previous week"
183
+ :aria-label="t('FdsWeekCalendar.previousWeek')"
177
184
  @click="decrementWeek"
178
185
  />
179
186
  <FdsButtonIcon
180
187
  icon="arrowRight"
181
188
  :disabled="disableNextWeekInteraction"
182
- aria-label="Next week"
189
+ :aria-label="t('FdsWeekCalendar.nextWeek')"
183
190
  @click="incrementWeek"
184
191
  />
185
192
  </div>
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { format } from 'date-fns'
3
- import { sv } from 'date-fns/locale'
4
3
  import { computed } from 'vue'
4
+ import { useFdsI18n } from '../../plugin/useFdsI18n'
5
5
  import FdsMeta from '../Typography/FdsMeta/FdsMeta.vue'
6
6
 
7
7
  const props = withDefaults(
@@ -22,6 +22,8 @@ const emit = defineEmits<{
22
22
  (e: 'select-date', date: Date | null): void
23
23
  }>()
24
24
 
25
+ const { locale, t } = useFdsI18n()
26
+
25
27
  const classes = computed(() => [
26
28
  'box-border flex h-[64px] w-full max-w-[100px] flex-1 basis-0 flex-col items-center justify-center border-2 border-transparent px-1 py-1 transition-colors cursor-pointer',
27
29
  props.disabled ? '' : 'hover:border-2 hover:border-blue-500 border-solid',
@@ -47,7 +49,7 @@ const onClick = () => {
47
49
  }
48
50
 
49
51
  const weekdayLabel = computed(() => {
50
- const value = format(props.date, 'EEE', { locale: sv })
52
+ const value = new Intl.DateTimeFormat(locale.value, { weekday: 'short' }).format(props.date)
51
53
  return value.charAt(0).toUpperCase() + value.slice(1).replace('.', '')
52
54
  })
53
55
  </script>
@@ -56,7 +58,7 @@ const weekdayLabel = computed(() => {
56
58
  <button type="button" :class="classes" :disabled="disabled" @click="onClick">
57
59
  <span :class="dayNumberClasses">{{ format(date, 'd') }}</span>
58
60
  <span :class="weekdayLabelClasses">
59
- <FdsMeta v-if="isToday">Idag</FdsMeta>
61
+ <FdsMeta v-if="isToday">{{ t('FdsWeekCalendar.today') }}</FdsMeta>
60
62
  <FdsMeta v-else>{{ weekdayLabel }}</FdsMeta>
61
63
  </span>
62
64
  </button>
@@ -1,14 +1,4 @@
1
- import {
2
- addDays,
3
- format,
4
- isAfter,
5
- isSameDay,
6
- isSameMonth,
7
- startOfDay,
8
- startOfISOWeek,
9
- subDays,
10
- } from 'date-fns'
11
- import { sv } from 'date-fns/locale'
1
+ import { addDays, format, isAfter, isSameDay, isSameMonth, startOfDay, startOfISOWeek, subDays } from 'date-fns'
12
2
  import type { WeekDateRange } from './types'
13
3
 
14
4
  const capitalizeFirstLetter = (value: string): string => {
@@ -16,17 +6,19 @@ const capitalizeFirstLetter = (value: string): string => {
16
6
  return value.charAt(0).toUpperCase() + value.slice(1)
17
7
  }
18
8
 
19
- export const getOverlappingMonths = (week: Date): string => {
9
+ export const getOverlappingMonths = (week: Date, locale = 'sv-SE'): string => {
20
10
  const startDayMonth = startOfISOWeek(week)
21
11
  const endDayMonth = addDays(startDayMonth, 6)
12
+ const shortMonthFormatter = new Intl.DateTimeFormat(locale, { month: 'short' })
13
+ const longMonthFormatter = new Intl.DateTimeFormat(locale, { month: 'long' })
22
14
 
23
15
  if (!isSameMonth(startDayMonth, endDayMonth)) {
24
- return `${capitalizeFirstLetter(format(startDayMonth, 'MMM', { locale: sv }).replace('.', ''))} - ${capitalizeFirstLetter(
25
- format(endDayMonth, 'MMM', { locale: sv }).replace('.', ''),
16
+ return `${capitalizeFirstLetter(shortMonthFormatter.format(startDayMonth).replace('.', ''))} - ${capitalizeFirstLetter(
17
+ shortMonthFormatter.format(endDayMonth).replace('.', ''),
26
18
  )}`
27
19
  }
28
20
 
29
- return capitalizeFirstLetter(format(startOfISOWeek(week), 'MMMM', { locale: sv }))
21
+ return capitalizeFirstLetter(longMonthFormatter.format(startOfISOWeek(week)))
30
22
  }
31
23
 
32
24
  export const getDaysInWeek = (weekStart: Date): Date[] => {
@@ -12,6 +12,7 @@ const props = withDefaults(defineProps<FdsWizardProps>(), {
12
12
  disableStepJump: false,
13
13
  activeRouteName: undefined,
14
14
  dataTestid: undefined,
15
+ wizardClass: 'max-w-[480px]',
15
16
  })
16
17
 
17
18
  const emit = defineEmits<{
@@ -457,7 +458,7 @@ defineSlots<{
457
458
 
458
459
  <template>
459
460
  <div v-bind="rootAttrs">
460
- <nav class="max-w-[480px] mx-auto">
461
+ <nav :class="wizardClass" class="mx-auto">
461
462
  <header class="mb-6">
462
463
  <h1 ref="mainHeader" tabindex="-1">
463
464
  {{ mainHeading }}
@@ -38,5 +38,6 @@ export interface FdsWizardProps<
38
38
  disableStepJump?: boolean
39
39
  activeRouteName?: string
40
40
  dataTestid?: string
41
+ wizardClass?: string
41
42
  onGo?: ((payload: FdsWizardGoPayload) => void) | Array<(payload: FdsWizardGoPayload) => void>
42
43
  }
package/src/index.ts CHANGED
@@ -65,6 +65,7 @@ import { useRouteScrollPositions } from './composables/useRouteScrollPositions'
65
65
  import { useViewportBreakpoint } from './composables/useViewportBreakpoint'
66
66
  import { capitalizeFirstLetter } from './helpers/capitalizeFirstLetter'
67
67
  import { useFileSizeValidation, useFileValidation } from './helpers/fileValidation'
68
+ import { FDS_VUE_CORE_I18N_KEY, type FdsI18nLike } from './plugin/i18n'
68
69
 
69
70
  // Export individual components
70
71
  export {
@@ -137,9 +138,19 @@ export {
137
138
  // Export logos
138
139
  export * from './assets/logos'
139
140
 
141
+ export interface FdsVueCorePluginOptions {
142
+ i18n?: FdsI18nLike
143
+ }
144
+
145
+ export { FDS_VUE_CORE_I18N_KEY } from './plugin/i18n'
146
+
140
147
  // Export component library plugin
141
148
  const FdsVueCorePlugin: Plugin = {
142
- install(app: App) {
149
+ install(app: App, options?: FdsVueCorePluginOptions) {
150
+ if (options?.i18n) {
151
+ app.provide(FDS_VUE_CORE_I18N_KEY, options.i18n)
152
+ }
153
+
143
154
  // Register all components globally
144
155
  app.component('FdsTreeView', FdsTreeView)
145
156
  // Register button variants with direct names
@@ -0,0 +1,6 @@
1
+ {
2
+ "FdsWeekCalendar.nextWeek": "Next week",
3
+ "FdsWeekCalendar.previousWeek": "Previous week",
4
+ "FdsWeekCalendar.today": "Today",
5
+ "FdsWeekCalendar.week": "week"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "FdsWeekCalendar.nextWeek": "Nästa vecka",
3
+ "FdsWeekCalendar.previousWeek": "Föregående vecka",
4
+ "FdsWeekCalendar.today": "Idag",
5
+ "FdsWeekCalendar.week": "vecka"
6
+ }
@@ -0,0 +1,15 @@
1
+ import type { InjectionKey } from 'vue'
2
+
3
+ export type FdsI18nTranslate = (key: string, ...args: unknown[]) => unknown
4
+ type FdsI18nLocale = string | { value: string }
5
+
6
+ export interface FdsI18nLike {
7
+ t?: FdsI18nTranslate
8
+ locale?: FdsI18nLocale
9
+ global?: {
10
+ t?: FdsI18nTranslate
11
+ locale?: FdsI18nLocale
12
+ }
13
+ }
14
+
15
+ export const FDS_VUE_CORE_I18N_KEY: InjectionKey<FdsI18nLike | undefined> = Symbol('fds-vue-core:i18n')
@@ -0,0 +1,40 @@
1
+ import { computed, inject } from 'vue'
2
+ import en from '../lang/en.json'
3
+ import sv from '../lang/sv.json'
4
+ import { FDS_VUE_CORE_I18N_KEY, type FdsI18nLike } from './i18n'
5
+
6
+ const translations = {
7
+ en,
8
+ sv,
9
+ } as const
10
+ type FdsDictionary = Record<string, string>
11
+
12
+ export const useFdsI18n = () => {
13
+ const i18n = inject<FdsI18nLike | undefined>(FDS_VUE_CORE_I18N_KEY, undefined)
14
+
15
+ const locale = computed(() => {
16
+ const locale = i18n?.global?.locale ?? i18n?.locale
17
+ if (typeof locale === 'string') return locale
18
+ if (locale && typeof locale === 'object' && 'value' in locale && typeof locale.value === 'string') {
19
+ return locale.value
20
+ }
21
+ return 'sv-SE'
22
+ })
23
+
24
+ const activeLanguage = computed(() => locale.value.toLowerCase().split('-')[0])
25
+ const dictionary = computed<FdsDictionary>(() => {
26
+ const currentDictionary = translations[activeLanguage.value as keyof typeof translations]
27
+ return (currentDictionary ?? translations.sv) as FdsDictionary
28
+ })
29
+
30
+ const t = (key: string): string => {
31
+ const value = dictionary.value[key]
32
+ return typeof value === 'string' ? value : ''
33
+ }
34
+
35
+ return {
36
+ i18n,
37
+ locale,
38
+ t,
39
+ }
40
+ }