@navikt/ds-react 7.5.0 → 7.5.2
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/cjs/expansion-card/ExpansionCardContent.js +1 -1
- package/cjs/expansion-card/ExpansionCardContent.js.map +1 -1
- package/cjs/expansion-card/ExpansionCardHeader.js +1 -1
- package/cjs/expansion-card/ExpansionCardHeader.js.map +1 -1
- package/cjs/form/combobox/FilteredOptions/useVirtualFocus.js +1 -1
- package/cjs/form/combobox/FilteredOptions/useVirtualFocus.js.map +1 -1
- package/cjs/form/file-upload/parts/dropzone/Dropzone.js +1 -1
- package/cjs/form/file-upload/parts/dropzone/Dropzone.js.map +1 -1
- package/cjs/help-text/HelpText.js +3 -1
- package/cjs/help-text/HelpText.js.map +1 -1
- package/cjs/help-text/HelpTextIcon.js +3 -1
- package/cjs/help-text/HelpTextIcon.js.map +1 -1
- package/cjs/pagination/Pagination.d.ts +5 -0
- package/cjs/pagination/Pagination.js +5 -0
- package/cjs/pagination/Pagination.js.map +1 -1
- package/cjs/pagination/PaginationItem.js +3 -1
- package/cjs/pagination/PaginationItem.js.map +1 -1
- package/cjs/popover/Popover.js +4 -2
- package/cjs/popover/Popover.js.map +1 -1
- package/cjs/timeline/AxisLabels.d.ts +4 -3
- package/cjs/timeline/AxisLabels.js +22 -13
- package/cjs/timeline/AxisLabels.js.map +1 -1
- package/cjs/timeline/Pin.js +5 -1
- package/cjs/timeline/Pin.js.map +1 -1
- package/cjs/timeline/TimelineRow.js +7 -2
- package/cjs/timeline/TimelineRow.js.map +1 -1
- package/cjs/timeline/period/ClickablePeriod.d.ts +1 -1
- package/cjs/timeline/period/ClickablePeriod.js +3 -1
- package/cjs/timeline/period/ClickablePeriod.js.map +1 -1
- package/cjs/timeline/period/NonClickablePeriod.d.ts +1 -1
- package/cjs/timeline/period/NonClickablePeriod.js +3 -1
- package/cjs/timeline/period/NonClickablePeriod.js.map +1 -1
- package/cjs/timeline/period/index.d.ts +1 -1
- package/cjs/timeline/period/types.d.ts +2 -1
- package/cjs/timeline/utils/period.d.ts +3 -1
- package/cjs/timeline/utils/period.js +9 -20
- package/cjs/timeline/utils/period.js.map +1 -1
- package/cjs/timeline/zoom/ZoomButton.js +8 -2
- package/cjs/timeline/zoom/ZoomButton.js.map +1 -1
- package/cjs/util/i18n/get.d.ts +1 -1
- package/cjs/util/i18n/get.js +2 -2
- package/cjs/util/i18n/get.js.map +1 -1
- package/cjs/util/i18n/i18n.context.d.ts +4 -1
- package/cjs/util/i18n/i18n.context.js +21 -3
- package/cjs/util/i18n/i18n.context.js.map +1 -1
- package/cjs/util/i18n/locales/en.d.ts +26 -0
- package/cjs/util/i18n/locales/en.js +27 -0
- package/cjs/util/i18n/locales/en.js.map +1 -1
- package/cjs/util/i18n/locales/nb.d.ts +27 -0
- package/cjs/util/i18n/locales/nb.js +27 -0
- package/cjs/util/i18n/locales/nb.js.map +1 -1
- package/cjs/util/i18n/locales/nn.d.ts +26 -0
- package/cjs/util/i18n/locales/nn.js +27 -0
- package/cjs/util/i18n/locales/nn.js.map +1 -1
- package/esm/expansion-card/ExpansionCardContent.js +1 -1
- package/esm/expansion-card/ExpansionCardContent.js.map +1 -1
- package/esm/expansion-card/ExpansionCardHeader.js +1 -1
- package/esm/expansion-card/ExpansionCardHeader.js.map +1 -1
- package/esm/form/combobox/FilteredOptions/useVirtualFocus.js +1 -1
- package/esm/form/combobox/FilteredOptions/useVirtualFocus.js.map +1 -1
- package/esm/form/file-upload/parts/dropzone/Dropzone.js +1 -1
- package/esm/form/file-upload/parts/dropzone/Dropzone.js.map +1 -1
- package/esm/help-text/HelpText.js +3 -1
- package/esm/help-text/HelpText.js.map +1 -1
- package/esm/help-text/HelpTextIcon.js +3 -1
- package/esm/help-text/HelpTextIcon.js.map +1 -1
- package/esm/pagination/Pagination.d.ts +5 -0
- package/esm/pagination/Pagination.js +5 -0
- package/esm/pagination/Pagination.js.map +1 -1
- package/esm/pagination/PaginationItem.js +3 -1
- package/esm/pagination/PaginationItem.js.map +1 -1
- package/esm/popover/Popover.js +4 -2
- package/esm/popover/Popover.js.map +1 -1
- package/esm/timeline/AxisLabels.d.ts +4 -3
- package/esm/timeline/AxisLabels.js +22 -13
- package/esm/timeline/AxisLabels.js.map +1 -1
- package/esm/timeline/Pin.js +5 -1
- package/esm/timeline/Pin.js.map +1 -1
- package/esm/timeline/TimelineRow.js +7 -2
- package/esm/timeline/TimelineRow.js.map +1 -1
- package/esm/timeline/period/ClickablePeriod.d.ts +1 -1
- package/esm/timeline/period/ClickablePeriod.js +3 -1
- package/esm/timeline/period/ClickablePeriod.js.map +1 -1
- package/esm/timeline/period/NonClickablePeriod.d.ts +1 -1
- package/esm/timeline/period/NonClickablePeriod.js +3 -1
- package/esm/timeline/period/NonClickablePeriod.js.map +1 -1
- package/esm/timeline/period/index.d.ts +1 -1
- package/esm/timeline/period/types.d.ts +2 -1
- package/esm/timeline/utils/period.d.ts +3 -1
- package/esm/timeline/utils/period.js +9 -20
- package/esm/timeline/utils/period.js.map +1 -1
- package/esm/timeline/zoom/ZoomButton.js +8 -2
- package/esm/timeline/zoom/ZoomButton.js.map +1 -1
- package/esm/util/i18n/get.d.ts +1 -1
- package/esm/util/i18n/get.js +2 -2
- package/esm/util/i18n/get.js.map +1 -1
- package/esm/util/i18n/i18n.context.d.ts +4 -1
- package/esm/util/i18n/i18n.context.js +20 -3
- package/esm/util/i18n/i18n.context.js.map +1 -1
- package/esm/util/i18n/locales/en.d.ts +26 -0
- package/esm/util/i18n/locales/en.js +27 -0
- package/esm/util/i18n/locales/en.js.map +1 -1
- package/esm/util/i18n/locales/nb.d.ts +27 -0
- package/esm/util/i18n/locales/nb.js +27 -0
- package/esm/util/i18n/locales/nb.js.map +1 -1
- package/esm/util/i18n/locales/nn.d.ts +26 -0
- package/esm/util/i18n/locales/nn.js +27 -0
- package/esm/util/i18n/locales/nn.js.map +1 -1
- package/package.json +3 -3
- package/src/expansion-card/ExpansionCardContent.tsx +1 -0
- package/src/expansion-card/ExpansionCardHeader.tsx +1 -0
- package/src/form/combobox/FilteredOptions/useVirtualFocus.ts +1 -1
- package/src/form/file-upload/parts/dropzone/Dropzone.tsx +1 -0
- package/src/help-text/HelpText.tsx +5 -1
- package/src/help-text/HelpTextIcon.tsx +5 -1
- package/src/pagination/Pagination.tsx +6 -0
- package/src/pagination/PaginationItem.tsx +5 -1
- package/src/popover/Popover.tsx +6 -2
- package/src/timeline/AxisLabels.tsx +30 -16
- package/src/timeline/Pin.tsx +5 -1
- package/src/timeline/TimelineRow.tsx +7 -5
- package/src/timeline/period/ClickablePeriod.tsx +4 -2
- package/src/timeline/period/NonClickablePeriod.tsx +5 -2
- package/src/timeline/period/index.tsx +1 -1
- package/src/timeline/period/types.ts +3 -1
- package/src/timeline/utils/period.ts +13 -24
- package/src/timeline/zoom/ZoomButton.tsx +8 -5
- package/src/util/i18n/get.ts +2 -2
- package/src/util/i18n/i18n.context.ts +35 -13
- package/src/util/i18n/locales/en.ts +27 -0
- package/src/util/i18n/locales/nb.ts +29 -5
- package/src/util/i18n/locales/nn.ts +27 -0
- package/src/util/i18n/locales.test.tsx +4 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Locale,
|
|
2
3
|
addDays,
|
|
3
4
|
addMonths,
|
|
4
5
|
addYears,
|
|
@@ -13,9 +14,9 @@ import {
|
|
|
13
14
|
startOfYear,
|
|
14
15
|
subDays,
|
|
15
16
|
} from "date-fns";
|
|
16
|
-
import { nb as nbLocale } from "date-fns/locale";
|
|
17
17
|
import React from "react";
|
|
18
18
|
import { Detail } from "../typography/Detail";
|
|
19
|
+
import { TFunction, useDateLocale, useI18n } from "../util/i18n/i18n.context";
|
|
19
20
|
import { useTimelineContext } from "./hooks/useTimelineContext";
|
|
20
21
|
import { isVisible } from "./utils";
|
|
21
22
|
import { horizontalPositionAndWidth } from "./utils/calc";
|
|
@@ -26,7 +27,8 @@ export const dayLabels = (
|
|
|
26
27
|
end: Date,
|
|
27
28
|
totalDays: number,
|
|
28
29
|
direction: "left" | "right",
|
|
29
|
-
template: string
|
|
30
|
+
template: string,
|
|
31
|
+
locale: Locale,
|
|
30
32
|
): AxisLabel[] => {
|
|
31
33
|
const increment = Math.ceil(totalDays / 10);
|
|
32
34
|
const lastDay = startOfDay(end);
|
|
@@ -44,7 +46,7 @@ export const dayLabels = (
|
|
|
44
46
|
return {
|
|
45
47
|
direction,
|
|
46
48
|
horizontalPosition,
|
|
47
|
-
label: format(day, template, { locale
|
|
49
|
+
label: format(day, template, { locale }),
|
|
48
50
|
date: day,
|
|
49
51
|
width,
|
|
50
52
|
};
|
|
@@ -56,7 +58,8 @@ export const monthLabels = (
|
|
|
56
58
|
start: Date,
|
|
57
59
|
end: Date,
|
|
58
60
|
direction: "left" | "right",
|
|
59
|
-
template: string
|
|
61
|
+
template: string,
|
|
62
|
+
locale: Locale,
|
|
60
63
|
): AxisLabel[] => {
|
|
61
64
|
const startMonth = startOfMonth(start);
|
|
62
65
|
const endMonth = endOfMonth(end);
|
|
@@ -72,7 +75,7 @@ export const monthLabels = (
|
|
|
72
75
|
return {
|
|
73
76
|
direction,
|
|
74
77
|
horizontalPosition,
|
|
75
|
-
label: format(month, template, { locale
|
|
78
|
+
label: format(month, template, { locale }),
|
|
76
79
|
date: month,
|
|
77
80
|
width,
|
|
78
81
|
};
|
|
@@ -83,7 +86,8 @@ export const yearLabels = (
|
|
|
83
86
|
start: Date,
|
|
84
87
|
end: Date,
|
|
85
88
|
direction: "left" | "right",
|
|
86
|
-
template: string
|
|
89
|
+
template: string,
|
|
90
|
+
locale: Locale,
|
|
87
91
|
): AxisLabel[] => {
|
|
88
92
|
const firstYear = startOfYear(start);
|
|
89
93
|
const lastYear = endOfYear(end);
|
|
@@ -99,29 +103,33 @@ export const yearLabels = (
|
|
|
99
103
|
return {
|
|
100
104
|
direction,
|
|
101
105
|
horizontalPosition,
|
|
102
|
-
label: format(year, template, { locale
|
|
106
|
+
label: format(year, template, { locale }),
|
|
103
107
|
date: year,
|
|
104
108
|
width,
|
|
105
109
|
};
|
|
106
110
|
});
|
|
107
111
|
};
|
|
108
112
|
|
|
109
|
-
const
|
|
113
|
+
const getLabels = (
|
|
110
114
|
start: Date,
|
|
111
115
|
end: Date,
|
|
112
116
|
direction: "left" | "right",
|
|
113
|
-
|
|
117
|
+
locale: Locale,
|
|
118
|
+
translate: TFunction<"Timeline">,
|
|
114
119
|
): AxisLabel[] => {
|
|
115
120
|
const totalDays = differenceInDays(end, start);
|
|
116
121
|
if (totalDays < 40) {
|
|
117
|
-
|
|
122
|
+
const dayTemplate = translate("dayFormat");
|
|
123
|
+
return dayLabels(start, end, totalDays, direction, dayTemplate, locale);
|
|
118
124
|
}
|
|
119
125
|
|
|
120
126
|
if (totalDays < 370) {
|
|
121
|
-
|
|
127
|
+
const monthTemplate = translate("monthFormat");
|
|
128
|
+
return monthLabels(start, end, direction, monthTemplate, locale);
|
|
122
129
|
}
|
|
123
130
|
|
|
124
|
-
|
|
131
|
+
const yearTemplate = translate("yearFormat");
|
|
132
|
+
return yearLabels(start, end, direction, yearTemplate, locale);
|
|
125
133
|
};
|
|
126
134
|
|
|
127
135
|
export const AxisLabels = ({
|
|
@@ -130,13 +138,19 @@ export const AxisLabels = ({
|
|
|
130
138
|
templates?: AxisLabelTemplates;
|
|
131
139
|
}) => {
|
|
132
140
|
const { endDate, startDate, direction } = useTimelineContext();
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
141
|
+
|
|
142
|
+
const translate = useI18n("Timeline", {
|
|
143
|
+
dayFormat: templates?.day,
|
|
144
|
+
monthFormat: templates?.month,
|
|
145
|
+
yearFormat: templates?.year,
|
|
146
|
+
});
|
|
147
|
+
const locale = useDateLocale();
|
|
148
|
+
|
|
149
|
+
const labels = getLabels(startDate, endDate, direction, locale, translate);
|
|
136
150
|
|
|
137
151
|
return (
|
|
138
152
|
<div className="navds-timeline__axislabels" aria-hidden="true">
|
|
139
|
-
{labels.map((etikett) => (
|
|
153
|
+
{labels.filter(isVisible).map((etikett) => (
|
|
140
154
|
<Detail
|
|
141
155
|
className="navds-timeline__axislabels-label"
|
|
142
156
|
as="div"
|
package/src/timeline/Pin.tsx
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { format } from "date-fns";
|
|
17
17
|
import React, { forwardRef, useRef, useState } from "react";
|
|
18
18
|
import { useMergeRefs } from "../util/hooks/useMergeRefs";
|
|
19
|
+
import { useI18n } from "../util/i18n/i18n.context";
|
|
19
20
|
import { useTimelineContext } from "./hooks/useTimelineContext";
|
|
20
21
|
import { position } from "./utils/calc";
|
|
21
22
|
import { TimelineComponentTypes } from "./utils/types.internal";
|
|
@@ -44,6 +45,7 @@ export const Pin = forwardRef<HTMLButtonElement, TimelinePinProps>(
|
|
|
44
45
|
const { startDate, endDate, direction } = useTimelineContext();
|
|
45
46
|
const [open, setOpen] = useState(false);
|
|
46
47
|
const arrowRef = useRef<HTMLDivElement | null>(null);
|
|
48
|
+
const translate = useI18n("Timeline");
|
|
47
49
|
|
|
48
50
|
const {
|
|
49
51
|
context,
|
|
@@ -100,7 +102,9 @@ export const Pin = forwardRef<HTMLButtonElement, TimelinePinProps>(
|
|
|
100
102
|
{...rest}
|
|
101
103
|
ref={mergedRef}
|
|
102
104
|
className="navds-timeline__pin-button"
|
|
103
|
-
aria-label={
|
|
105
|
+
aria-label={translate("Pin.pin", {
|
|
106
|
+
date: format(date, translate("dateFormat")),
|
|
107
|
+
})}
|
|
104
108
|
type="button"
|
|
105
109
|
aria-expanded={children ? open : undefined}
|
|
106
110
|
{...getReferenceProps({
|
|
@@ -2,6 +2,7 @@ import cl from "clsx";
|
|
|
2
2
|
import { format } from "date-fns";
|
|
3
3
|
import React, { forwardRef } from "react";
|
|
4
4
|
import { BodyShort } from "../typography/BodyShort";
|
|
5
|
+
import { useI18n } from "../util/i18n/i18n.context";
|
|
5
6
|
import { PeriodContext } from "./hooks/usePeriodContext";
|
|
6
7
|
import { useRowContext } from "./hooks/useRowContext";
|
|
7
8
|
import { useTimelineContext } from "./hooks/useTimelineContext";
|
|
@@ -39,6 +40,7 @@ export const TimelineRow = forwardRef<HTMLOListElement, TimelineRowProps>(
|
|
|
39
40
|
({ label, className, headingTag = "h3", icon, ...rest }, ref) => {
|
|
40
41
|
const { periods, id, active } = useRowContext();
|
|
41
42
|
const { setActiveRow } = useTimelineContext();
|
|
43
|
+
const translate = useI18n("Timeline");
|
|
42
44
|
|
|
43
45
|
const latest = periods.reduce((a, b) => {
|
|
44
46
|
return a.end > b.end ? a : b;
|
|
@@ -77,11 +79,11 @@ export const TimelineRow = forwardRef<HTMLOListElement, TimelineRowProps>(
|
|
|
77
79
|
ref={ref}
|
|
78
80
|
aria-label={
|
|
79
81
|
periods.length === 0
|
|
80
|
-
? "
|
|
81
|
-
:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
82
|
+
? translate("Row.noPeriods")
|
|
83
|
+
: translate("Row.period", {
|
|
84
|
+
start: format(earliest.start, translate("dateFormat")),
|
|
85
|
+
end: format(latest.end, translate("dateFormat")),
|
|
86
|
+
})
|
|
85
87
|
}
|
|
86
88
|
className={cl("navds-timeline__row-periods", className)}
|
|
87
89
|
onKeyDown={(e) => {
|
|
@@ -16,11 +16,12 @@ import {
|
|
|
16
16
|
import cl from "clsx";
|
|
17
17
|
import React, { useRef, useState } from "react";
|
|
18
18
|
import { useMergeRefs } from "../../util/hooks/useMergeRefs";
|
|
19
|
+
import { useI18n } from "../../util/i18n/i18n.context";
|
|
19
20
|
import { usePeriodContext } from "../hooks/usePeriodContext";
|
|
20
21
|
import { useRowContext } from "../hooks/useRowContext";
|
|
21
22
|
import { useTimelineContext } from "../hooks/useTimelineContext";
|
|
22
23
|
import { ariaLabel, getConditionalClasses } from "../utils/period";
|
|
23
|
-
import { PeriodProps } from "./types";
|
|
24
|
+
import type { PeriodProps } from "./types";
|
|
24
25
|
|
|
25
26
|
interface TimelineClickablePeriodProps extends PeriodProps {
|
|
26
27
|
onSelectPeriod?: (
|
|
@@ -52,6 +53,7 @@ const ClickablePeriod = React.memo(
|
|
|
52
53
|
const { firstFocus } = usePeriodContext();
|
|
53
54
|
const { initiate, addFocusable } = useTimelineContext();
|
|
54
55
|
const arrowRef = useRef<HTMLDivElement | null>(null);
|
|
56
|
+
const translate = useI18n("Timeline");
|
|
55
57
|
|
|
56
58
|
const {
|
|
57
59
|
context,
|
|
@@ -107,7 +109,7 @@ const ClickablePeriod = React.memo(
|
|
|
107
109
|
firstFocus && addFocusable(r, index);
|
|
108
110
|
mergedRef(r);
|
|
109
111
|
}}
|
|
110
|
-
aria-label={ariaLabel(start, end, status, statusLabel)}
|
|
112
|
+
aria-label={ariaLabel(start, end, status, statusLabel, translate)}
|
|
111
113
|
className={cl(
|
|
112
114
|
"navds-timeline__period--clickable",
|
|
113
115
|
getConditionalClasses(cropped, direction, status),
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import cl from "clsx";
|
|
2
2
|
import React from "react";
|
|
3
|
+
import { useI18n } from "../../util/i18n/i18n.context";
|
|
3
4
|
import { ariaLabel, getConditionalClasses } from "../utils/period";
|
|
4
|
-
import { PeriodProps } from "./types";
|
|
5
|
+
import type { PeriodProps } from "./types";
|
|
5
6
|
|
|
6
7
|
interface TimelineNonClickablePeriodProps extends PeriodProps {
|
|
7
8
|
periodRef?: React.ForwardedRef<HTMLDivElement>;
|
|
@@ -20,6 +21,8 @@ const NonClickablePeriod = ({
|
|
|
20
21
|
restProps,
|
|
21
22
|
periodRef,
|
|
22
23
|
}: TimelineNonClickablePeriodProps) => {
|
|
24
|
+
const translate = useI18n("Timeline");
|
|
25
|
+
|
|
23
26
|
return (
|
|
24
27
|
<div
|
|
25
28
|
ref={periodRef}
|
|
@@ -36,7 +39,7 @@ const NonClickablePeriod = ({
|
|
|
36
39
|
<span className="navds-timeline__period--inner">
|
|
37
40
|
{icon}
|
|
38
41
|
<span className="sr-only">
|
|
39
|
-
{ariaLabel(start, end, status, statusLabel)}
|
|
42
|
+
{ariaLabel(start, end, status, statusLabel, translate)}
|
|
40
43
|
</span>
|
|
41
44
|
</span>
|
|
42
45
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { forwardRef } from "react";
|
|
2
2
|
import { usePeriodContext } from "../hooks/usePeriodContext";
|
|
3
3
|
import { useRowContext } from "../hooks/useRowContext";
|
|
4
|
-
import { TimelineComponentTypes } from "../utils/types.internal";
|
|
4
|
+
import type { TimelineComponentTypes } from "../utils/types.internal";
|
|
5
5
|
import ClickablePeriod from "./ClickablePeriod";
|
|
6
6
|
import NonClickablePeriod from "./NonClickablePeriod";
|
|
7
7
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import cl from "clsx";
|
|
2
2
|
import { format } from "date-fns";
|
|
3
|
+
import type { TFunction } from "../../util/i18n/i18n.context";
|
|
4
|
+
import type { PeriodProps } from "../period/types";
|
|
3
5
|
|
|
4
6
|
export const getConditionalClasses = (
|
|
5
7
|
cropped: string,
|
|
@@ -17,32 +19,19 @@ export const getConditionalClasses = (
|
|
|
17
19
|
});
|
|
18
20
|
};
|
|
19
21
|
|
|
20
|
-
const translateStatus = (status: string): string => {
|
|
21
|
-
switch (status) {
|
|
22
|
-
case "success":
|
|
23
|
-
return "Suksess";
|
|
24
|
-
case "warning":
|
|
25
|
-
return "Advarsel";
|
|
26
|
-
case "danger":
|
|
27
|
-
return "Fare";
|
|
28
|
-
case "info":
|
|
29
|
-
return "Info";
|
|
30
|
-
case "neutral":
|
|
31
|
-
return "Nøytral";
|
|
32
|
-
default:
|
|
33
|
-
return status;
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
22
|
export const ariaLabel = (
|
|
38
23
|
startDate: Date,
|
|
39
24
|
endDate: Date,
|
|
40
|
-
status:
|
|
41
|
-
statusLabel
|
|
25
|
+
status: PeriodProps["status"],
|
|
26
|
+
statusLabel: string | undefined,
|
|
27
|
+
translate: TFunction<"Timeline">,
|
|
42
28
|
): string => {
|
|
43
|
-
const
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
29
|
+
const dateFormat = translate("dateFormat");
|
|
30
|
+
const start = format(startDate, dateFormat);
|
|
31
|
+
const end = format(endDate, dateFormat);
|
|
32
|
+
return translate("Period.period", {
|
|
33
|
+
status: statusLabel || translate(`Period.${status}`),
|
|
34
|
+
start,
|
|
35
|
+
end,
|
|
36
|
+
});
|
|
48
37
|
};
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
} from "date-fns";
|
|
9
9
|
import React, { forwardRef } from "react";
|
|
10
10
|
import { Detail } from "../../typography/Detail";
|
|
11
|
+
import { useI18n } from "../../util/i18n/i18n.context";
|
|
11
12
|
import { useTimelineContext } from "../hooks/useTimelineContext";
|
|
12
13
|
|
|
13
14
|
export interface TimelineZoomButtonProps {
|
|
@@ -33,6 +34,8 @@ export type ZoomButtonType = React.ForwardRefExoticComponent<
|
|
|
33
34
|
export const ZoomButton: ZoomButtonType = forwardRef(
|
|
34
35
|
({ label, interval, count, ...rest }, ref) => {
|
|
35
36
|
const { setStart, endDate, startDate, direction } = useTimelineContext();
|
|
37
|
+
const translate = useI18n("Timeline");
|
|
38
|
+
const dateFormat = translate("dateFormat");
|
|
36
39
|
|
|
37
40
|
let startOfRange: Date;
|
|
38
41
|
|
|
@@ -59,11 +62,11 @@ export const ZoomButton: ZoomButtonType = forwardRef(
|
|
|
59
62
|
type="button"
|
|
60
63
|
aria-label={
|
|
61
64
|
!currentZoom
|
|
62
|
-
?
|
|
63
|
-
startOfRange,
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
: "
|
|
65
|
+
? translate("Zoom.zoom", {
|
|
66
|
+
start: format(startOfRange, dateFormat),
|
|
67
|
+
end: format(endDate, dateFormat),
|
|
68
|
+
})
|
|
69
|
+
: translate("Zoom.reset")
|
|
67
70
|
}
|
|
68
71
|
ref={ref}
|
|
69
72
|
{...rest}
|
package/src/util/i18n/get.ts
CHANGED
|
@@ -7,7 +7,7 @@ const OBJECT_NOTATION_MATCHER = /(\w+)/g;
|
|
|
7
7
|
|
|
8
8
|
export function get(
|
|
9
9
|
keypath: string | string[],
|
|
10
|
-
|
|
10
|
+
objs: (PartialTranslations | undefined)[],
|
|
11
11
|
) {
|
|
12
12
|
const keys = Array.isArray(keypath) ? keypath : getKeypath(keypath);
|
|
13
13
|
|
|
@@ -32,7 +32,7 @@ export function get(
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
throw new Error(
|
|
35
|
-
|
|
35
|
+
`Error translating key. Keypath '${keypath}' does not resolve to a string.`,
|
|
36
36
|
);
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
import { Locale } from "date-fns";
|
|
1
2
|
import { useContext } from "react";
|
|
2
3
|
import { LanguageProviderContext } from "../../provider/i18n/LanguageProvider";
|
|
3
4
|
import { get } from "./get";
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
Component,
|
|
7
|
+
ComponentTranslation,
|
|
8
|
+
PartialTranslations,
|
|
9
|
+
Translations,
|
|
10
|
+
} from "./i18n.types";
|
|
5
11
|
|
|
6
12
|
/**
|
|
7
13
|
* https://regex101.com/r/LYKWi3/1
|
|
@@ -15,27 +21,29 @@ type NestedKeyOf<ObjectType extends object> = {
|
|
|
15
21
|
: `${Key}`;
|
|
16
22
|
}[keyof ObjectType & (string | number)];
|
|
17
23
|
|
|
24
|
+
export type TFunction<T extends Component> = (
|
|
25
|
+
keypath: NestedKeyOf<Translations[T]>,
|
|
26
|
+
replacements?: Record<string, string | number>,
|
|
27
|
+
) => string;
|
|
28
|
+
|
|
18
29
|
export function useI18n<T extends Component>(
|
|
19
30
|
componentName: T,
|
|
20
31
|
...local: (ComponentTranslation<T> | undefined)[]
|
|
21
32
|
) {
|
|
22
33
|
const languageProviderContext = useContext(LanguageProviderContext);
|
|
23
34
|
const i18n = languageProviderContext.translations;
|
|
35
|
+
const i18nObjects: (PartialTranslations | undefined)[] = [
|
|
36
|
+
...local,
|
|
37
|
+
...(Array.isArray(i18n)
|
|
38
|
+
? i18n.map((t) => t[componentName])
|
|
39
|
+
: [i18n[componentName]]),
|
|
40
|
+
];
|
|
24
41
|
|
|
25
42
|
/**
|
|
26
43
|
* https://github.com/Shopify/polaris/blob/2115f9ba2f5bcbf2ad15745233501bff2db81ecf/polaris-react/src/utilities/i18n/I18n.ts#L24
|
|
27
44
|
*/
|
|
28
|
-
const translate = (
|
|
29
|
-
keypath
|
|
30
|
-
replacements?: Record<string, string | number>,
|
|
31
|
-
) => {
|
|
32
|
-
const text = get(
|
|
33
|
-
keypath,
|
|
34
|
-
...local,
|
|
35
|
-
...(Array.isArray(i18n)
|
|
36
|
-
? i18n.map((t) => t[componentName])
|
|
37
|
-
: [i18n[componentName]]),
|
|
38
|
-
);
|
|
45
|
+
const translate: TFunction<T> = (keypath, replacements) => {
|
|
46
|
+
const text = get(keypath, i18nObjects);
|
|
39
47
|
|
|
40
48
|
if (replacements) {
|
|
41
49
|
return text.replace(REPLACE_REGEX, (match) => {
|
|
@@ -43,7 +51,6 @@ export function useI18n<T extends Component>(
|
|
|
43
51
|
|
|
44
52
|
if (replacements[replacement] === undefined) {
|
|
45
53
|
const replacementData = JSON.stringify(replacements);
|
|
46
|
-
|
|
47
54
|
throw new Error(
|
|
48
55
|
`Error translating key '${keypath}'. No replacement syntax ({}) found for key '${replacement}'. The following replacements were passed: '${replacementData}'`,
|
|
49
56
|
);
|
|
@@ -58,3 +65,18 @@ export function useI18n<T extends Component>(
|
|
|
58
65
|
|
|
59
66
|
return translate;
|
|
60
67
|
}
|
|
68
|
+
|
|
69
|
+
export function useDateLocale() {
|
|
70
|
+
const languageProviderContext = useContext(LanguageProviderContext);
|
|
71
|
+
const i18n = languageProviderContext.translations;
|
|
72
|
+
const i18nObjects = Array.isArray(i18n)
|
|
73
|
+
? i18n.map((t) => t.global)
|
|
74
|
+
: [i18n.global];
|
|
75
|
+
|
|
76
|
+
for (const obj of i18nObjects) {
|
|
77
|
+
if (obj?.dateLocale) {
|
|
78
|
+
return obj.dateLocale as Locale;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
throw new Error("dateLocale not found.");
|
|
82
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { enGB } from "date-fns/locale";
|
|
1
2
|
import type { Translations } from "../i18n.types";
|
|
2
3
|
|
|
3
4
|
export default {
|
|
4
5
|
global: {
|
|
6
|
+
dateLocale: enGB,
|
|
5
7
|
showMore: "Show more",
|
|
6
8
|
showLess: "Show less",
|
|
7
9
|
readOnly: "Read-only",
|
|
@@ -70,4 +72,29 @@ export default {
|
|
|
70
72
|
charsTooMany: "{chars} characters too many",
|
|
71
73
|
charsLeft: "{chars} characters left",
|
|
72
74
|
},
|
|
75
|
+
Timeline: {
|
|
76
|
+
dateFormat: "yyyy-MM-dd",
|
|
77
|
+
dayFormat: "d MMM",
|
|
78
|
+
monthFormat: "MMM yyyy",
|
|
79
|
+
yearFormat: "yyyy",
|
|
80
|
+
Row: {
|
|
81
|
+
noPeriods: "No periods",
|
|
82
|
+
period: "{start} to {end}",
|
|
83
|
+
},
|
|
84
|
+
Period: {
|
|
85
|
+
success: "Success",
|
|
86
|
+
warning: "Warning",
|
|
87
|
+
danger: "Danger",
|
|
88
|
+
info: "Info",
|
|
89
|
+
neutral: "Neutral",
|
|
90
|
+
period: "{status} from {start} to {end}",
|
|
91
|
+
},
|
|
92
|
+
Pin: {
|
|
93
|
+
pin: "Pin: {date}",
|
|
94
|
+
},
|
|
95
|
+
Zoom: {
|
|
96
|
+
zoom: "Zoom timeline {start} to {end}",
|
|
97
|
+
reset: "Reset zoom",
|
|
98
|
+
},
|
|
99
|
+
},
|
|
73
100
|
} satisfies Translations;
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
+
import { Locale, nb } from "date-fns/locale";
|
|
2
|
+
|
|
1
3
|
interface TranslationMap {
|
|
2
|
-
[component: string]:
|
|
3
|
-
| Record<string, string>
|
|
4
|
-
| {
|
|
5
|
-
[subComponent: string]: Record<string, string>;
|
|
6
|
-
};
|
|
4
|
+
[component: string]: Record<string, string | Record<string, string> | Locale>;
|
|
7
5
|
}
|
|
8
6
|
|
|
9
7
|
export default {
|
|
10
8
|
global: {
|
|
9
|
+
dateLocale: nb,
|
|
11
10
|
showMore: "Vis mer",
|
|
12
11
|
showLess: "Vis mindre",
|
|
13
12
|
readOnly: "Skrivebeskyttet",
|
|
@@ -78,4 +77,29 @@ export default {
|
|
|
78
77
|
charsTooMany: "{chars} tegn for mye",
|
|
79
78
|
charsLeft: "{chars} tegn igjen",
|
|
80
79
|
},
|
|
80
|
+
Timeline: {
|
|
81
|
+
dateFormat: "dd.MM.yyyy",
|
|
82
|
+
dayFormat: "dd.MM",
|
|
83
|
+
monthFormat: "MMM yy",
|
|
84
|
+
yearFormat: "yyyy",
|
|
85
|
+
Row: {
|
|
86
|
+
noPeriods: "Ingen perioder",
|
|
87
|
+
period: "{start} til {end}",
|
|
88
|
+
},
|
|
89
|
+
Period: {
|
|
90
|
+
success: "Suksess",
|
|
91
|
+
warning: "Advarsel",
|
|
92
|
+
danger: "Fare",
|
|
93
|
+
info: "Info",
|
|
94
|
+
neutral: "Nøytral", // TODO: Consider making these global
|
|
95
|
+
period: "{status} fra {start} til {end}",
|
|
96
|
+
},
|
|
97
|
+
Pin: {
|
|
98
|
+
pin: "Pin: {date}",
|
|
99
|
+
},
|
|
100
|
+
Zoom: {
|
|
101
|
+
zoom: "Zoom tidslinjen {start} til {end}",
|
|
102
|
+
reset: "Tilbakestill tidsperspektiv",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
81
105
|
} satisfies TranslationMap;
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { nn } from "date-fns/locale";
|
|
1
2
|
import type { Translations } from "../i18n.types";
|
|
2
3
|
|
|
3
4
|
export default {
|
|
4
5
|
global: {
|
|
6
|
+
dateLocale: nn,
|
|
5
7
|
showMore: "Vis meir",
|
|
6
8
|
showLess: "Vis mindre",
|
|
7
9
|
readOnly: "Skrivebeskytta",
|
|
@@ -70,4 +72,29 @@ export default {
|
|
|
70
72
|
charsTooMany: "{chars} teikn for mykje",
|
|
71
73
|
charsLeft: "{chars} teikn igjen",
|
|
72
74
|
},
|
|
75
|
+
Timeline: {
|
|
76
|
+
dateFormat: "dd.MM.yyyy",
|
|
77
|
+
dayFormat: "dd.MM",
|
|
78
|
+
monthFormat: "MMM yy",
|
|
79
|
+
yearFormat: "yyyy",
|
|
80
|
+
Row: {
|
|
81
|
+
noPeriods: "Ingen periodar",
|
|
82
|
+
period: "{start} til {end}",
|
|
83
|
+
},
|
|
84
|
+
Period: {
|
|
85
|
+
success: "Suksess",
|
|
86
|
+
warning: "Åtvaring",
|
|
87
|
+
danger: "Fare",
|
|
88
|
+
info: "Info",
|
|
89
|
+
neutral: "Nøytral",
|
|
90
|
+
period: "{status} frå {start} til {end}",
|
|
91
|
+
},
|
|
92
|
+
Pin: {
|
|
93
|
+
pin: "Pin: {date}",
|
|
94
|
+
},
|
|
95
|
+
Zoom: {
|
|
96
|
+
zoom: "Zoom tidslina {start} til {end}",
|
|
97
|
+
reset: "Tilbakestill tidsperspektiv",
|
|
98
|
+
},
|
|
99
|
+
},
|
|
73
100
|
} satisfies Translations;
|
|
@@ -6,7 +6,10 @@ import nb from "./locales/nb";
|
|
|
6
6
|
import nn from "./locales/nn";
|
|
7
7
|
|
|
8
8
|
function checkValues(obj: Translations | Record<string, string>) {
|
|
9
|
-
Object.
|
|
9
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
10
|
+
if (key === "dateLocale") {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
10
13
|
if (typeof value === "object") {
|
|
11
14
|
checkValues(value);
|
|
12
15
|
} else {
|