Compare commits

...
Author SHA1 Message Date
Ken b52a5e02a0 ✨ Patch-versjoner 2022-11-01 23:57:38 +01:00
Ken ab3ef0d34b ✨ Validering i Date-komponenter
🐛 Date-formats skaper problemer for ranged-input

🐛 UX tweaks for inputs

🐛 Fikset weekendValidation

🎨 Custom input-format

🎨 validation api

🎉 range-validation

🎨 Export validation-types

🎨 Datepicker-validation

🎨 monthpicker validation

🎨 Småbugs med disabled datepicker

💄 reversert capitalization i månedsnavn
2022-11-01 23:54:27 +01:00
Ken 69798f6ee2 🔥 Fjernet flaky e2e test 2022-11-01 11:00:35 +01:00
Ken ee14586beb ⬆️ yarn-lock 2022-11-01 10:40:34 +01:00
34 changed files with 680 additions and 346 deletions

No files matched your search

+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-codemod
## 1.4.3
## 1.4.2
## 1.4.1
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-codemod",
"version": "1.4.2",
"version": "1.4.3",
"description": "NAV designsystem codemods",
"author": "NAV Designsystem team",
"license": "MIT",
+6
View File
@@ -1,5 +1,11 @@
# @navikt/ds-css
## 1.4.3
### Patch Changes
- :sparkles: Validering og inputFormat i Date-komponenter
## 1.4.2
## 1.4.1
+5
View File
@@ -13,6 +13,10 @@
gap: var(--navds-spacing-5);
}
.navds-date__caption-label {
text-transform: capitalize;
}
.navds-date .rdp-head_cell {
text-transform: capitalize;
font-size: var(--navds-font-size-small);
@@ -86,6 +90,7 @@
text-align: center;
width: 3rem;
height: 2.75rem;
text-transform: capitalize;
border-radius: var(--navds-border-radius-medium);
cursor: pointer;
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "1.4.2",
"version": "1.4.3",
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
"keywords": [
@@ -20,7 +20,7 @@
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
},
"devDependencies": {
"@navikt/ds-tokens": "^1.4.2",
"@navikt/ds-tokens": "^1.4.3",
"normalize.css": "^8.0.1",
"postcss": "^8.4.0",
"postcss-cli": "^9.0.0",
+9
View File
@@ -1,5 +1,14 @@
# @navikt/ds-react
## 1.4.3
### Patch Changes
- :sparkles: Validering og inputFormat i Date-komponenter
- Updated dependencies []:
- @navikt/ds-icons@1.4.3
## 1.4.2
### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "1.4.2",
"version": "1.4.3",
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
"license": "MIT",
@@ -37,7 +37,7 @@
},
"dependencies": {
"@floating-ui/react-dom-interactions": "0.9.2",
"@navikt/ds-icons": "^1.4.2",
"@navikt/ds-icons": "^1.4.3",
"@radix-ui/react-tabs": "1.0.0",
"@radix-ui/react-toggle-group": "1.0.0",
"clsx": "^1.2.1",
@@ -1,4 +1,3 @@
import isSaturday from "date-fns/isSaturday";
import React, { useId, useState } from "react";
import { UNSAFE_useDatepicker, UNSAFE_useRangeDatepicker } from "..";
import { Button } from "../..";
@@ -221,8 +220,13 @@ export const UserControlled = () => {
};
export const Validering = () => {
const { datepickerProps, selectedDay, inputProps } = UNSAFE_useDatepicker({
fromDate: new Date("Aug 23 2019"),
const [error, setError] = useState(false);
const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
fromDate: new Date("Aug 2 2019"),
onValidate: (val) => setError(val.isWeekend),
defaultSelected: new Date("Nov 26 2022"),
disableWeekends: true,
onDateChange: console.log,
});
return (
@@ -230,8 +234,8 @@ export const Validering = () => {
<DatePicker {...datepickerProps}>
<DatePicker.Input
error={
selectedDay && isSaturday(selectedDay)
? "NAV-kontoret er ikke åpent på lørdager. Velg en annen dag."
error
? "NAV-kontoret er ikke åpent i helger. Velg en annen dag."
: undefined
}
{...inputProps}
@@ -261,3 +265,24 @@ export const ErrorInput = () => {
</div>
);
};
export const UseRangedDatepickerValidation = () => {
const { datepickerProps, fromInputProps, toInputProps } =
UNSAFE_useRangeDatepicker({
fromDate: new Date("Aug 23 2019"),
disableWeekends: true,
disabled: [new Date("Oct 10 2022")],
onValidate: console.table,
});
return (
<div style={{ display: "flex", gap: "1rem" }}>
<DatePicker {...datepickerProps}>
<div style={{ display: "flex", gap: "1rem" }}>
<DatePicker.Input {...fromInputProps} label="Fra" />
<DatePicker.Input {...toInputProps} label="Til" />
</div>
</DatePicker>
</div>
);
};
@@ -1,6 +1,9 @@
export { useDatepicker as UNSAFE_useDatepicker } from "./useDatepicker";
export type { DateValidationT } from "./useDatepicker";
export { useRangeDatepicker as UNSAFE_useRangeDatepicker } from "./useRangeDatepicker";
export type { RangeValidationT } from "./useRangeDatepicker";
export { useMonthpicker as UNSAFE_useMonthpicker } from "./useMonthPicker";
export type { MonthValidationT } from "./useMonthPicker";
export { useDateInputContext, DateContext } from "./useDateInputContext";
export {
useSharedMonthContext,
@@ -36,6 +36,15 @@ export interface UseDatepickerOptions
* Callback for changed state
*/
onDateChange?: (val?: Date) => void;
/**
* Input-format
* @default "dd.MM.yyyy"
*/
inputFormat?: string;
/**
* validation-callback
*/
onValidate?: (val: DateValidationT) => void;
}
interface UseDatepickerValue {
@@ -62,6 +71,27 @@ interface UseDatepickerValue {
setSelected: (date?: Date) => void;
}
export type DateValidationT = {
isDisabled: boolean;
isWeekend: boolean;
isEmpty: boolean;
isInvalid: boolean;
isValidDate: boolean;
isBefore: boolean;
isAfter: boolean;
};
const getValidationMessage = (val = {}): DateValidationT => ({
isDisabled: false,
isWeekend: false,
isEmpty: false,
isInvalid: false,
isBefore: false,
isAfter: false,
isValidDate: true,
...val,
});
export const useDatepicker = (
opt: UseDatepickerOptions = {}
): UseDatepickerValue => {
@@ -75,6 +105,8 @@ export const useDatepicker = (
disabled,
disableWeekends,
onDateChange,
inputFormat,
onValidate,
} = opt;
const locale = getLocaleFromString(_locale);
@@ -90,7 +122,7 @@ export const useDatepicker = (
const [open, setOpen] = useState(false);
const defaultInputValue = defaultSelected
? formatDateForInput(defaultSelected, locale, "date")
? formatDateForInput(defaultSelected, locale, "date", inputFormat)
: "";
const [inputValue, setInputValue] = useState(defaultInputValue);
@@ -99,6 +131,11 @@ export const useDatepicker = (
setSelectedDay(date);
};
const updateValidation = (val: Partial<DateValidationT> = {}) => {
const msg = getValidationMessage(val);
onValidate?.(msg);
};
const handleFocusIn = useCallback(
(e) => {
if (!e?.target || !e?.target?.nodeType) {
@@ -134,7 +171,9 @@ export const useDatepicker = (
const setSelected = (date: Date | undefined) => {
updateDate(date);
setMonth(date ?? today);
setInputValue(date ? formatDateForInput(date, locale, "date") : "");
setInputValue(
date ? formatDateForInput(date, locale, "date", inputFormat) : ""
);
};
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
@@ -143,13 +182,14 @@ export const useDatepicker = (
let day = parseDate(e.target.value, today, locale, "date");
if (isValidDate(day)) {
setMonth(day);
setInputValue(formatDateForInput(day, locale, "date"));
setInputValue(formatDateForInput(day, locale, "date", inputFormat));
}
};
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
let day = parseDate(e.target.value, today, locale, "date");
isValidDate(day) && setInputValue(formatDateForInput(day, locale, "date"));
isValidDate(day) &&
setInputValue(formatDateForInput(day, locale, "date", inputFormat));
};
/* Only allow de-selecting if not required */
@@ -162,11 +202,15 @@ export const useDatepicker = (
if (!required && selected) {
updateDate(undefined);
setInputValue("");
updateValidation({ isValidDate: false, isEmpty: true });
return;
}
updateDate(day);
updateValidation();
setMonth(day);
setInputValue(day ? formatDateForInput(day, locale, "date") : "");
setInputValue(
day ? formatDateForInput(day, locale, "date", inputFormat) : ""
);
};
// When changing the input field, save its value in state and check if the
@@ -176,22 +220,39 @@ export const useDatepicker = (
setInputValue(e.target.value);
const day = parseDate(e.target.value, today, locale, "date");
const isBefore =
fromDate && day && differenceInCalendarDays(fromDate, day) > 0;
const isAfter = toDate && day && differenceInCalendarDays(day, toDate) > 0;
if (
!isValidDate(day) ||
(disabled &&
((disableWeekends && isWeekend(day)) || isMatch(day, disabled)))
(disableWeekends && isWeekend(day)) ||
(disabled && isMatch(day, disabled))
) {
updateDate(undefined);
updateValidation({
isInvalid: isValidDate(day),
isWeekend: disableWeekends && isWeekend(day),
isDisabled: disabled && isMatch(day, disabled),
isValidDate: false,
isEmpty: !e.target.value,
isBefore: isBefore ?? false,
isAfter: isAfter ?? false,
});
return;
}
const isBefore = fromDate && differenceInCalendarDays(fromDate, day) > 0;
const isAfter = toDate && differenceInCalendarDays(day, toDate) > 0;
if (isBefore || isAfter) {
updateDate(undefined);
updateValidation({
isValidDate: false,
isBefore: isBefore ?? false,
isAfter: isAfter ?? false,
});
return;
}
updateDate(day);
updateValidation();
setMonth(day);
};
@@ -217,13 +278,15 @@ export const useDatepicker = (
month,
onMonthChange: (month) => setMonth(month),
onDayClick: handleDayClick,
selected: selectedDay,
selected: selectedDay ?? new Date("Invalid date"),
locale: _locale,
fromDate,
toDate,
today,
open,
onOpenToggle: () => setOpen((x) => !x),
disabled,
disableWeekends,
ref: daypickerRef,
};
@@ -22,6 +22,15 @@ export interface UseMonthPickerOptions
* Callback for month-change
*/
onMonthChange?: (date?: Date) => void;
/**
* Input-format
* @default "MMMM yyyy"
*/
inputFormat?: string;
/**
* validation-callback
*/
onValidate?: (val: MonthValidationT) => void;
}
interface UseMonthPickerValue {
@@ -48,6 +57,25 @@ interface UseMonthPickerValue {
reset: () => void;
}
export type MonthValidationT = {
isDisabled: boolean;
isEmpty: boolean;
isInvalid: boolean;
isValidMonth: boolean;
isBefore: boolean;
isAfter: boolean;
};
const getValidationMessage = (val = {}): MonthValidationT => ({
isDisabled: false,
isEmpty: false,
isInvalid: false,
isBefore: false,
isAfter: false,
isValidMonth: true,
...val,
});
export const useMonthpicker = (
opt: UseMonthPickerOptions = {}
): UseMonthPickerValue => {
@@ -59,6 +87,8 @@ export const useMonthpicker = (
disabled,
required,
onMonthChange,
inputFormat,
onValidate,
} = opt;
const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
@@ -75,7 +105,7 @@ export const useMonthpicker = (
const [open, setOpen] = useState(false);
const defaultInputValue = defaultSelected
? formatDateForInput(defaultSelected, locale, "month")
? formatDateForInput(defaultSelected, locale, "month", inputFormat)
: "";
const [inputValue, setInputValue] = useState(defaultInputValue);
@@ -85,6 +115,11 @@ export const useMonthpicker = (
setSelectedMonth(date);
};
const updateValidation = (val: Partial<MonthValidationT> = {}) => {
const msg = getValidationMessage(val);
onValidate?.(msg);
};
const handleFocusIn = useCallback(
(e) => {
if (!e?.target || !e?.target?.nodeType) {
@@ -120,7 +155,9 @@ export const useMonthpicker = (
const setSelected = (date: Date | undefined) => {
updateMonth(date);
setYear(date ?? today);
setInputValue(date ? formatDateForInput(date, locale, "month") : "");
setInputValue(
date ? formatDateForInput(date, locale, "month", inputFormat) : ""
);
};
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
@@ -128,13 +165,14 @@ export const useMonthpicker = (
let day = parseDate(e.target.value, today, locale, "month");
if (isValidDate(day)) {
setYear(day);
setInputValue(formatDateForInput(day, locale, "month"));
setInputValue(formatDateForInput(day, locale, "month", inputFormat));
}
};
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
let day = parseDate(e.target.value, today, locale, "month");
isValidDate(day) && setInputValue(formatDateForInput(day, locale, "month"));
isValidDate(day) &&
setInputValue(formatDateForInput(day, locale, "month", inputFormat));
};
/* Only allow de-selecting if not required */
@@ -146,11 +184,15 @@ export const useMonthpicker = (
if (!required && !month) {
updateMonth(undefined);
updateValidation({ isValidMonth: false, isEmpty: true });
setInputValue("");
return;
}
updateMonth(month);
setInputValue(month ? formatDateForInput(month, locale, "month") : "");
updateValidation();
setInputValue(
month ? formatDateForInput(month, locale, "month", inputFormat) : ""
);
};
// When changing the input field, save its value in state and check if the
@@ -160,32 +202,48 @@ export const useMonthpicker = (
setInputValue(e.target.value);
const month = parseDate(e.target.value, today, locale, "month");
if (!isValidDate(month) || (disabled && isMatch(month, disabled))) {
updateMonth(undefined);
return;
}
const isBefore =
fromDate &&
month &&
(fromDate.getFullYear() > month.getFullYear() ||
(fromDate.getFullYear() === month.getFullYear() &&
fromDate.getMonth() > month.getMonth()));
const isAfter =
toDate &&
month &&
(toDate.getFullYear() < month.getFullYear() ||
(toDate.getFullYear() === month.getFullYear() &&
toDate.getMonth() < month.getMonth()));
if (!isValidDate(month) || (disabled && isMatch(month, disabled))) {
updateMonth(undefined);
updateValidation({
isInvalid: isValidDate(month),
isDisabled: disabled && isMatch(month, disabled),
isValidMonth: false,
isEmpty: !e.target.value,
isBefore: isBefore ?? false,
isAfter: isAfter ?? false,
});
return;
}
if (
isAfter ||
isBefore ||
(fromDate && toDate && !isMatch(month, [{ from: fromDate, to: toDate }]))
) {
updateMonth(undefined);
updateValidation({
isValidMonth: false,
isBefore: isBefore ?? false,
isAfter: isAfter ?? false,
});
return;
}
updateMonth(month);
updateValidation();
setYear(month);
};
@@ -0,0 +1,59 @@
/* eslint-disable react/jsx-pascal-case */
import { act, render } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import React from "react";
import { UNSAFE_DatePicker, UNSAFE_useRangeDatepicker } from "..";
const RangeDemo = () => {
const { datepickerProps, fromInputProps, selectedRange, toInputProps } =
UNSAFE_useRangeDatepicker({
fromDate: new Date("Aug 23 2019"),
});
return (
<div style={{ display: "flex", gap: "1rem" }}>
<UNSAFE_DatePicker {...datepickerProps}>
<UNSAFE_DatePicker.Input {...fromInputProps} label="Fra" />
<UNSAFE_DatePicker.Input {...toInputProps} label="Til" />
</UNSAFE_DatePicker>
<div title="res">{JSON.stringify(selectedRange)}</div>
</div>
);
};
describe("Writing in input sets correct values", () => {
it("useRangeDatepicker same date", async () => {
const utils = render(<RangeDemo />);
const fraInput = utils.getByRole("textbox", { name: "Fra" });
const tilInput = utils.getByRole("textbox", { name: "Til" });
await act(async () => {
await userEvent.type(fraInput, "03.08.2022");
await userEvent.type(tilInput, "03.08.2022");
});
const res = utils.getByTitle("res");
expect(res.innerHTML).toEqual(
JSON.stringify({
from: "2022-08-02T22:00:00.000Z",
to: "2022-08-02T22:00:00.000Z",
})
);
});
it("useRangeDatepicker before after to ", async () => {
const utils = render(<RangeDemo />);
const fraInput = utils.getByRole("textbox", { name: "Fra" });
const tilInput = utils.getByRole("textbox", { name: "Til" });
await act(async () => {
await userEvent.type(fraInput, "03.08.2022");
await userEvent.type(tilInput, "02.08.2022");
});
const res = utils.getByTitle("res");
expect(res.innerHTML).toEqual(
JSON.stringify({
from: "2022-08-02T22:00:00.000Z",
})
);
});
});
@@ -10,10 +10,42 @@ import {
isValidDate,
parseDate,
} from "../utils";
import { UseDatepickerOptions } from "./useDatepicker";
import { DateValidationT, UseDatepickerOptions } from "./useDatepicker";
export type RangeValidationT = {
from: DateValidationT;
to: DateValidationT & { isBeforeFrom?: boolean };
};
const getValidationMessage = (from = {}, to = {}): RangeValidationT => ({
from: {
isDisabled: false,
isWeekend: false,
isEmpty: false,
isInvalid: false,
isBefore: false,
isAfter: false,
isValidDate: true,
...from,
},
to: {
isDisabled: false,
isWeekend: false,
isEmpty: false,
isInvalid: false,
isBefore: false,
isAfter: false,
isBeforeFrom: false,
isValidDate: true,
...to,
},
});
interface UseRangeDatepickerOptions
extends Omit<UseDatepickerOptions, "defaultSelected" | "onDateChange"> {
extends Omit<
UseDatepickerOptions,
"defaultSelected" | "onDateChange" | "onValidate"
> {
/**
* The initially selected DateRange
*/
@@ -22,6 +54,10 @@ interface UseRangeDatepickerOptions
* Callback for changed state
*/
onRangeChange?: (val?: DateRange) => void;
/**
* validation-callback
*/
onValidate?: (val: RangeValidationT) => void;
}
interface UseRangeDatepickerValue {
@@ -65,6 +101,92 @@ const RANGE = {
type RangeT = typeof RANGE[keyof typeof RANGE];
const fromValidation = (day: Date, opt?: UseRangeDatepickerOptions) => {
const isBefore =
opt?.fromDate && day && differenceInCalendarDays(opt?.fromDate, day) > 0;
const isAfter =
opt?.toDate && day && differenceInCalendarDays(day, opt?.toDate) > 0;
if (
isValidDate(day) &&
!(opt?.disableWeekends && isWeekend(day)) &&
!(opt?.disabled && isMatch(day, opt.disabled))
) {
return {
isValidDate: false,
isInvalid: !isValidDate(day),
isWeekend: opt?.disableWeekends && isWeekend(day),
isDisabled: opt?.disabled && isMatch(day, opt.disabled),
isBefore: isBefore,
isAfter: isAfter,
};
}
if (isBefore || isAfter) {
return {
isValidDate: false,
isBefore: isBefore,
isAfter: isAfter,
};
}
};
const toValidation = (
day: Date,
from: Date,
opt?: UseRangeDatepickerOptions
) => {
const isBefore =
opt?.fromDate && day && differenceInCalendarDays(opt?.fromDate, day) > 0;
const isAfter =
opt?.toDate && day && differenceInCalendarDays(day, opt?.toDate) > 0;
const isBeforeFrom =
(from && differenceInCalendarDays(from, day) > 0) ?? false;
if (
isValidDate(day) &&
!(opt?.disableWeekends && isWeekend(day)) &&
!(opt?.disabled && isMatch(day, opt.disabled))
) {
return {
isValidDate: false,
isInvalid: !isValidDate(day),
isWeekend: opt?.disableWeekends && isWeekend(day),
isDisabled: opt?.disabled && isMatch(day, opt.disabled),
isBefore,
isAfter,
isBeforeFrom,
};
}
if (isBefore || isAfter || isBeforeFrom) {
return {
isValidDate: false,
isBefore,
isAfter,
isBeforeFrom,
};
}
};
const initialValidation = (
range?: DateRange,
opt?: UseRangeDatepickerOptions
): RangeValidationT => {
if (!range || !range?.from) {
return getValidationMessage(
{ isEmpty: true, isValidDate: false },
{ isEmpty: true, isValidDate: false }
);
}
const fromVal = fromValidation(range.from, opt);
const toVal = range.to
? toValidation(range.to, range.from, opt)
: { isEmpty: true, isValidDate: false };
return getValidationMessage({ ...fromVal }, { ...toVal });
};
export const useRangeDatepicker = (
opt: UseRangeDatepickerOptions = {}
): UseRangeDatepickerValue => {
@@ -77,6 +199,8 @@ export const useRangeDatepicker = (
disabled,
disableWeekends,
onRangeChange,
inputFormat,
onValidate,
} = opt;
const locale = getLocaleFromString(_locale);
@@ -97,15 +221,20 @@ export const useRangeDatepicker = (
const [fromInputValue, setFromInputValue] = useState(
defaultSelected?.from
? formatDateForInput(defaultSelected.from, locale, "date")
? formatDateForInput(defaultSelected.from, locale, "date", inputFormat)
: ""
);
const [toInputValue, setToInputValue] = useState(
defaultSelected?.to
? formatDateForInput(defaultSelected.to, locale, "date")
? formatDateForInput(defaultSelected.to, locale, "date", inputFormat)
: ""
);
const [validation, setValidation] = useState<RangeValidationT>(
initialValidation(selectedRange, opt)
);
const [open, setOpen] = useState(false);
const updateRange = (range?: DateRange) => {
@@ -113,6 +242,15 @@ export const useRangeDatepicker = (
setSelectedRange(range);
};
const updateValidation = (
from: Partial<RangeValidationT["from"]> = {},
to: Partial<RangeValidationT["to"]> = {}
) => {
const msg = getValidationMessage(from, to);
setValidation(msg);
onValidate?.(msg);
};
const handleFocusIn = useCallback(
(e) => {
if (!e?.target || !e?.target?.nodeType) {
@@ -143,14 +281,20 @@ export const useRangeDatepicker = (
const reset = () => {
updateRange(defaultSelected ?? { from: undefined, to: undefined });
setMonth(defaultSelected ? defaultSelected?.from : today);
setValidation(
initialValidation(
defaultSelected ?? { from: undefined, to: undefined },
opt
)
);
setFromInputValue(
defaultSelected?.from
? formatDateForInput(defaultSelected.from, locale, "date")
? formatDateForInput(defaultSelected.from, locale, "date", inputFormat)
: ""
);
setToInputValue(
defaultSelected?.to
? formatDateForInput(defaultSelected.to, locale, "date")
? formatDateForInput(defaultSelected.to, locale, "date", inputFormat)
: ""
);
setDefaultSelected(_defaultSelected);
@@ -159,11 +303,16 @@ export const useRangeDatepicker = (
const setSelected = (range?: DateRange) => {
updateRange(range);
setFromInputValue(
range?.from ? formatDateForInput(range.from, locale, "date") : ""
range?.from
? formatDateForInput(range.from, locale, "date", inputFormat)
: ""
);
setToInputValue(
range?.to ? formatDateForInput(range?.to, locale, "date") : ""
range?.to
? formatDateForInput(range?.to, locale, "date", inputFormat)
: ""
);
setValidation(initialValidation(range, opt));
};
const handleFocus = (e, src: RangeT) => {
@@ -172,52 +321,10 @@ export const useRangeDatepicker = (
if (isValidDate(day)) {
setMonth(day);
src === RANGE.FROM
? setFromInputValue(formatDateForInput(day, locale, "date"))
: setToInputValue(formatDateForInput(day, locale, "date"));
}
};
const handleInputs = (day: Date, src: RangeT) => {
if (src === RANGE.FROM) {
const isAfter =
toInputValue &&
differenceInCalendarDays(
day,
parseDate(toInputValue, today, locale, "date")
) > 0;
if (isAfter) {
setFromInputValue(
formatDateForInput(
parseDate(toInputValue, today, locale, "date"),
locale,
"date"
? setFromInputValue(
formatDateForInput(day, locale, "date", inputFormat)
)
);
setToInputValue(formatDateForInput(day, locale, "date"));
} else {
setFromInputValue(formatDateForInput(day, locale, "date"));
}
} else if (src === RANGE.TO) {
const isBefore =
fromInputValue &&
differenceInCalendarDays(
parseDate(fromInputValue, today, locale, "date"),
day
) > 0;
if (isBefore) {
setToInputValue(
formatDateForInput(
parseDate(fromInputValue, today, locale, "date"),
locale,
"date"
)
);
setFromInputValue(formatDateForInput(day, locale, "date"));
} else {
setToInputValue(formatDateForInput(day, locale, "date"));
}
: setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
}
};
@@ -227,7 +334,19 @@ export const useRangeDatepicker = (
return;
}
handleInputs(day, src);
if (src === RANGE.FROM) {
setFromInputValue(formatDateForInput(day, locale, "date", inputFormat));
} else if (src === RANGE.TO) {
setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
}
};
const validateDay = (day: any) => {
return (
isValidDate(day) &&
!(disableWeekends && isWeekend(day)) &&
!(disabled && isMatch(day, disabled))
);
};
const handleSelect = (range) => {
@@ -238,68 +357,140 @@ export const useRangeDatepicker = (
!selectedRange?.from && selectedRange?.to ? selectedRange?.to : range?.to;
range?.from
? setFromInputValue(formatDateForInput(range?.from, locale, "date"))
? setFromInputValue(
formatDateForInput(range?.from, locale, "date", inputFormat)
)
: setFromInputValue("");
prevToRange
? setToInputValue(formatDateForInput(prevToRange, locale, "date"))
? setToInputValue(
formatDateForInput(prevToRange, locale, "date", inputFormat)
)
: setToInputValue("");
updateValidation(
{ isValidDate: !!range?.from, isEmpty: !range?.from },
{ isValidDate: !!range?.to, isEmpty: !prevToRange }
);
updateRange({ from: range?.from, to: prevToRange });
};
/* live-update datepicker based on changes in inputfields */
const handleChange = (e, src: RangeT) => {
src === RANGE.FROM
? setFromInputValue(e.target.value)
: setToInputValue(e.target.value);
const day = parseDate(e.target.value, today, locale, "date");
if (
!isValidDate(day) ||
(disabled &&
((disableWeekends && isWeekend(day)) || isMatch(day, disabled)))
) {
updateRange(
src === RANGE.FROM
? { ...selectedRange, from: undefined }
: { from: selectedRange?.from, to: undefined }
const fromChange = (
val: string = "",
day: Date,
isBefore = false,
isAfter = false
) => {
setFromInputValue(val);
if (!validateDay(day)) {
updateRange({ ...selectedRange, from: undefined });
updateValidation(
{
isEmpty: !val,
isValidDate: false,
isInvalid: !isValidDate(day),
isWeekend: disableWeekends && isWeekend(day),
isDisabled: disabled && isMatch(day, disabled),
isBefore,
isAfter,
},
validation.to
);
return;
}
if (isBefore || isAfter) {
updateRange({ ...selectedRange, from: undefined });
updateValidation(
{
isValidDate: false,
isBefore,
isAfter,
},
validation.to
);
return;
}
if (
selectedRange?.to &&
differenceInCalendarDays(day, selectedRange?.to) > 0
) {
updateRange({ to: day, from: day });
setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
setMonth(day);
updateValidation();
return;
}
if (toInputValue && !selectedRange?.to) {
const toDay = parseDate(toInputValue, today, locale, "date");
if (validateDay(toDay)) {
updateRange({ from: day, to: toDay });
setMonth(day);
updateValidation();
return;
}
}
updateRange({ ...selectedRange, from: day });
updateValidation({}, validation.to);
setMonth(day);
};
const toChange = (
val: string = "",
day: Date,
isBefore = false,
isAfter = false
) => {
setToInputValue(val);
if (!validateDay(day)) {
updateRange({ from: selectedRange?.from, to: undefined });
updateValidation(validation.from, {
isEmpty: !val,
isValidDate: false,
isInvalid: !isValidDate(day),
isWeekend: disableWeekends && isWeekend(day),
isDisabled: disabled && isMatch(day, disabled),
isBefore,
isAfter,
});
return;
}
if (isBefore || isAfter) {
updateRange({ from: selectedRange?.from, to: undefined });
updateValidation(validation.from, {
isValidDate: false,
isBefore,
isAfter,
});
return;
}
/* If to-value < from-value */
if (
selectedRange?.from &&
differenceInCalendarDays(selectedRange?.from, day) > 0
) {
updateRange({ from: selectedRange?.from, to: undefined });
updateValidation(validation.from, {
isValidDate: false,
isBeforeFrom: true,
});
return;
}
updateRange({ from: selectedRange?.from, to: day });
updateValidation(validation.from, {});
setMonth(day);
};
/* live-update datepicker based on changes in inputfields */
const handleChange = (e, src: RangeT) => {
const day = parseDate(e.target.value, today, locale, "date");
const isBefore = fromDate && differenceInCalendarDays(fromDate, day) > 0;
const isAfter = toDate && differenceInCalendarDays(day, toDate) > 0;
if (isBefore || isAfter) {
src === RANGE.FROM
? updateRange({ ...selectedRange, from: undefined })
: updateRange({ from: selectedRange?.from, to: undefined });
return;
}
/* If to-value < from-value, switch places in state */
if (
src === RANGE.TO &&
selectedRange?.from &&
differenceInCalendarDays(selectedRange?.from, day) >= 0
) {
updateRange({ from: day, to: selectedRange?.from });
setMonth(day);
return;
}
/* If from-value > to-value , switch places in state */
if (
src === RANGE.FROM &&
selectedRange?.to &&
differenceInCalendarDays(day, selectedRange?.to) >= 0
) {
updateRange({ to: day, from: selectedRange?.to });
setMonth(day);
return;
}
src === RANGE.FROM && updateRange({ ...selectedRange, from: day });
src === RANGE.TO && updateRange({ from: selectedRange?.from, to: day });
setMonth(day);
return src === RANGE.FROM
? fromChange(e.target.value, day, isBefore, isAfter)
: toChange(e.target.value, day, isBefore, isAfter);
};
const handleClose = useCallback(() => {
@@ -336,6 +527,8 @@ export const useRangeDatepicker = (
mode: "range" as const,
open,
onOpenToggle: () => setOpen((x) => !x),
disabled,
disableWeekends,
ref: datePickerRef,
};
@@ -90,6 +90,26 @@ export const UseMonthpicker = () => {
);
};
export const UseMonthpickerFormat = () => {
const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
disabled: [new Date("Apr 1 2022")],
onMonthChange: console.log,
inputFormat: "MM.yyyy",
});
return (
<div style={{ height: "20rem" }}>
<MonthPicker {...monthpickerProps}>
<MonthPicker.Input
{...inputProps}
label="Velg måned"
variant="monthpicker"
/>
</MonthPicker>
</div>
);
};
export const Required = () => {
const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
locale: "nb",
@@ -6,16 +6,16 @@ const parse = (inp: string) => parseDate(inp, new Date(), nb, "date");
describe("Format date to correct output", () => {
test("formatDateForInput", () => {
expect(formatDateForInput(parse("15/05/22"), nb, "date")).toEqual(
expect(formatDateForInput(parse("15/05/2022"), nb, "date")).toEqual(
"15.05.2022"
);
expect(formatDateForInput(parse("1/5/22"), nb, "date")).toEqual(
expect(formatDateForInput(parse("1/5/2022"), nb, "date")).toEqual(
"01.05.2022"
);
expect(formatDateForInput(parse("1/05/22"), nb, "date")).toEqual(
expect(formatDateForInput(parse("1/05/2022"), nb, "date")).toEqual(
"01.05.2022"
);
expect(formatDateForInput(parse("15/5/22"), nb, "date")).toEqual(
expect(formatDateForInput(parse("15/5/2022"), nb, "date")).toEqual(
"15.05.2022"
);
});
@@ -2,7 +2,6 @@ import { parseDate } from "..";
import { isValidDate } from "..";
import nb from "date-fns/locale/nb";
import getMonth from "date-fns/getMonth";
import getYear from "date-fns/getYear";
const check = (inp: string) =>
expect(isValidDate(parseDate(inp, new Date(), nb, "date")));
@@ -11,71 +10,32 @@ const parse = (inp: string) => parseDate(inp, new Date(), nb, "date");
describe("Parse date-inputs", () => {
test("No spaces", () => {
check("150522").toBeTruthy();
check("11052022").toBeTruthy();
check("15052022").toBeTruthy();
});
test(". divider", () => {
check("1.5.22").toBeTruthy();
check("1.5.2022").toBeTruthy();
check("11.05.22").toBeTruthy();
check("11.05.2022").toBeTruthy();
});
test("/ divider", () => {
check("1/5/22").toBeTruthy();
check("10/5/22").toBeTruthy();
check("1/5/2022").toBeTruthy();
check("10/5/2022").toBeTruthy();
check("1/05/22").toBeTruthy();
check("10/05/22").toBeTruthy();
check("1/05/2022").toBeTruthy();
check("10/05/2022").toBeTruthy();
});
test("- divider", () => {
check("1-5-22").toBeTruthy();
check("10-5-22").toBeTruthy();
check("1-5-2022").toBeTruthy();
check("10-5-2022").toBeTruthy();
check("1-05-22").toBeTruthy();
check("10-05-22").toBeTruthy();
check("1-05-2022").toBeTruthy();
check("10-05-2022").toBeTruthy();
});
});
describe("Parse date-inputs to correct year", () => {
test("No spaces", () => {
expect(getYear(parse("150522"))).toEqual(2022);
});
test(". divider", () => {
expect(getYear(parse("1.05.22"))).toEqual(2022);
expect(getYear(parse("11.05.22"))).toEqual(2022);
expect(getYear(parse("1.5.22"))).toEqual(2022);
expect(getYear(parse("11.5.22"))).toEqual(2022);
});
test("/ divider", () => {
expect(getYear(parse("1/5/22"))).toEqual(2022);
expect(getYear(parse("10/5/22"))).toEqual(2022);
expect(getYear(parse("1/05/22"))).toEqual(2022);
expect(getYear(parse("10/05/22"))).toEqual(2022);
});
test("- divider", () => {
expect(getYear(parse("1-5-22"))).toEqual(2022);
expect(getYear(parse("10-5-22"))).toEqual(2022);
expect(getYear(parse("1-05-22"))).toEqual(2022);
expect(getYear(parse("10-05-22"))).toEqual(2022);
});
});
describe("Parse date-inputs to correct month", () => {
test("No spaces", () => {
expect(getMonth(parse("150522"))).toEqual(4);
expect(getMonth(parse("11052022"))).toEqual(4);
expect(getMonth(parse("15052022"))).toEqual(4);
});
@@ -7,11 +7,13 @@ import {
export const formatDateForInput = (
date: Date,
locale: Locale,
type: "date" | "month"
type: "date" | "month",
inputFormat?: string
) => {
const INPUT_DATE_STRING_FORMAT =
type === "date"
inputFormat ??
(type === "date"
? INPUT_DATE_STRING_FORMAT_DATE
: INPUT_DATE_STRING_FORMAT_MONTH;
: INPUT_DATE_STRING_FORMAT_MONTH);
return format(date, INPUT_DATE_STRING_FORMAT, { locale });
};
@@ -6,16 +6,10 @@ export const INPUT_DATE_STRING_FORMAT_DATE = "dd.MM.yyyy";
export const INPUT_DATE_STRING_FORMAT_MONTH = "MMMM yyyy";
const ALLOWED_INPUT_FORMATS_DATE = [
"ddMMyy",
"d.M.yy",
"dd.MM.yy",
"dd/MM/yy",
"dd-MM-yy",
INPUT_DATE_STRING_FORMAT_DATE,
"ddMMyyyy",
"dd/MM/yyyy",
"dd-MM-yyyy",
"d.M.yyyy",
];
const ALLOWED_INPUT_FORMATS_MONTH = [
@@ -28,20 +22,35 @@ const ALLOWED_INPUT_FORMATS_MONTH = [
...ALLOWED_INPUT_FORMATS_DATE,
];
const isTwoDigitYear = (dateString, today, locale, formats) => {
let parsed;
const newFormat = formats.map((x) => x.replace("yyyy", "yy"));
for (const format of newFormat) {
parsed = parse(dateString, format, today, { locale });
if (isValidDate(parsed)) {
return true;
}
}
return false;
};
export const parseDate = (
date: string,
today: Date,
locale: Locale,
type: "date" | "month"
) => {
): Date => {
let parsed;
const ALLOWED_FORMATS =
type === "date" ? ALLOWED_INPUT_FORMATS_DATE : ALLOWED_INPUT_FORMATS_MONTH;
for (const format of ALLOWED_FORMATS) {
parsed = parse(date, format, today, { locale });
if (isValidDate(parsed)) {
if (
isValidDate(parsed) &&
!isTwoDigitYear(date, today, locale, ALLOWED_FORMATS)
) {
return parsed;
}
}
return parsed;
return new Date("Invalid date");
};
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-tailwind
## 1.4.3
## 1.4.2
## 1.4.1
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "1.4.2",
"version": "1.4.3",
"description": "Auto-generated tailwind config based on @navikt/ds-tokens",
"author": "NAV Designsystem team",
"keywords": [
@@ -22,7 +22,7 @@
"directory": "@navikt/core/tailwind"
},
"devDependencies": {
"@navikt/ds-tokens": "^1.4.2",
"@navikt/ds-tokens": "^1.4.3",
"@types/jest": "^29.0.0",
"@types/node": "^17.0.35",
"jest": "^29.0.0",
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-tokens
## 1.4.3
## 1.4.2
## 1.4.1
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "1.4.2",
"version": "1.4.3",
"description": "Auto-generated design-tokens for NAV design-systems framework",
"author": "NAV Designsystem team",
"keywords": [
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-icons
## 1.4.3
## 1.4.2
## 1.4.1
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "1.4.2",
"version": "1.4.3",
"description": "Aksel icons",
"repository": {
"type": "git",
+2
View File
@@ -1,5 +1,7 @@
# @navikt/ds-css-internal
## 1.4.3
## 1.4.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css-internal",
"version": "1.4.2",
"version": "1.4.3",
"description": "Css for NAV internal Designsystem components",
"author": "NAV Designsystem team",
"keywords": [
+8
View File
@@ -1,5 +1,13 @@
# @navikt/ds-react-internal
## 1.4.3
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.4.3
- @navikt/ds-icons@1.4.3
## 1.4.2
### Patch Changes
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react-internal",
"version": "1.4.2",
"version": "1.4.3",
"description": "NAV internal designsystem react components",
"author": "NAV Designsystem team",
"license": "MIT",
@@ -35,8 +35,8 @@
"watch": "tsc --watch -p tsconfig.esm.json"
},
"dependencies": {
"@navikt/ds-icons": "^1.4.2",
"@navikt/ds-react": "^1.4.2",
"@navikt/ds-icons": "^1.4.3",
"@navikt/ds-react": "^1.4.3",
"clsx": "^1.1.1",
"copy-to-clipboard": "^3.3.1"
},
+8 -8
View File
@@ -18,14 +18,14 @@
"website"
],
"dependencies": {
"@navikt/ds-codemod": "^1.4.2",
"@navikt/ds-css": "^1.4.2",
"@navikt/ds-css-internal": "^1.4.2",
"@navikt/ds-icons": "^1.4.2",
"@navikt/ds-react": "^1.4.2",
"@navikt/ds-react-internal": "^1.4.2",
"@navikt/ds-tailwind": "^1.4.2",
"@navikt/ds-tokens": "^1.4.2"
"@navikt/ds-codemod": "^1.4.3",
"@navikt/ds-css": "^1.4.3",
"@navikt/ds-css-internal": "^1.4.3",
"@navikt/ds-icons": "^1.4.3",
"@navikt/ds-react": "^1.4.3",
"@navikt/ds-react-internal": "^1.4.3",
"@navikt/ds-tailwind": "^1.4.3",
"@navikt/ds-tokens": "^1.4.3"
},
"devDependencies": {
"prettier-plugin-tailwindcss": "^0.1.13"
@@ -1,101 +0,0 @@
import { test, expect } from "@playwright/test";
test("Navigate tema and prinsipp", async ({ page }) => {
await page.goto("http://localhost:3000/tema/innholdsarbeid");
await page.getByRole("link", { name: "Temaer" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema");
await page.getByRole("link", { name: "Brukerinnsikt 16 Artikler" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema/brukerinnsikt");
await page.getByRole("link", { name: "Temaer" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema");
await page
.getByRole("link", { name: "Universell utforming 26 Artikler" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/tema/universell-utforming"
);
await page.getByRole("link", { name: "Temaer" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema");
await page.getByRole("link", { name: "Interne flater 3 Artikler" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema/interne-flater");
await page.getByRole("link", { name: "Temaer" }).click();
await expect(page).toHaveURL("http://localhost:3000/tema");
await page.getByRole("link", { name: "Aksel" }).click();
await expect(page).toHaveURL("http://localhost:3000/");
await page.getByRole("link", { name: "Utforsk alle prinsippene" }).click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
await page
.getByRole("link", { name: "1. Jeg får tillit og muligheter" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse/jeg-far-tillit-og-muligheter"
);
await page
.getByRole("link", { name: "Prinsipper for brukeropplevelse" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
await page
.getByRole("heading", {
name: "2. Jeg blir møtt på min situasjon og mine behov",
})
.getByRole("link", {
name: "2. Jeg blir møtt på min situasjon og mine behov",
})
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse/jeg-blir-mott-pa-min-situasjon-og-behov"
);
await page
.getByRole("link", { name: "Prinsipper for brukeropplevelse" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
await page
.getByRole("heading", { name: "3. NAV er min støttespiller" })
.getByRole("link", { name: "3. NAV er min støttespiller" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse/nav-er-min-stottespiller"
);
await page
.getByRole("link", { name: "Prinsipper for brukeropplevelse" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
await page
.getByRole("heading", { name: "4. Jeg blir inkludert" })
.getByRole("link", { name: "4. Jeg blir inkludert" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse/jeg-blir-inkludert"
);
await page
.getByRole("link", { name: "Prinsipper for brukeropplevelse" })
.click();
await expect(page).toHaveURL(
"http://localhost:3000/prinsipper/brukeropplevelse"
);
});
@@ -3,10 +3,13 @@ import { withDsExample } from "components/website-modules/examples/withDsExample
import { useState } from "react";
const Example = () => {
const [day, setDay] = useState<Date | undefined>();
const [hasError, setHasError] = useState(false);
const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
fromDate: new Date("Aug 23 2019"),
onDateChange: setDay,
onValidate: (val) => {
setHasError(val.isValidDate);
console.log(val);
},
});
return (
@@ -15,7 +18,7 @@ const Example = () => {
<UNSAFE_DatePicker.Input
{...inputProps}
label="Velg dato"
error={!day && "Må velge en dag"}
error={hasError && "Noe er feil"}
/>
</UNSAFE_DatePicker>
</div>
@@ -26,5 +29,5 @@ export default withDsExample(Example);
export const args = {
index: 9,
desc: "Vi anbefaler å bruke UNSAFE_useDatepicker-hook hvis man har et input-felt",
desc: "Bruk onValidate-callback for å håndtere validering.",
};
@@ -3,12 +3,14 @@ import { withDsExample } from "components/website-modules/examples/withDsExample
import { useState } from "react";
const Example = () => {
const [month, setMonth] = useState<Date | undefined>();
const [hasError, setHasError] = useState(false);
const { monthpickerProps, inputProps } = UNSAFE_useMonthpicker({
fromDate: new Date("Aug 23 2019"),
toDate: new Date("Aug 23 2025"),
onMonthChange: setMonth,
onValidate: (val) => {
setHasError(val.isValidMonth);
console.log(val);
},
});
return (
@@ -18,7 +20,7 @@ const Example = () => {
<UNSAFE_MonthPicker.Input
{...inputProps}
label="Velg månede"
error={!month && "Du må velge månede"}
error={hasError && "Du må velge månede"}
/>
</div>
</UNSAFE_MonthPicker>
@@ -30,5 +32,5 @@ export default withDsExample(Example);
export const args = {
index: 5,
desc: "Vi anbefaler å bruke UNSAFE_useMonthpicker-hook hvis man har et input-felt",
desc: "Bruk onValidate-callback for å håndtere validering.",
};
+5 -5
View File
@@ -9,16 +9,16 @@
"lint": "next lint"
},
"dependencies": {
"@navikt/ds-css": "^1.4.2",
"@navikt/ds-icons": "^1.4.2",
"@navikt/ds-react": "^1.4.2",
"@navikt/ds-react-internal": "^1.4.2",
"@navikt/ds-css": "^1.4.3",
"@navikt/ds-icons": "^1.4.3",
"@navikt/ds-react": "^1.4.3",
"@navikt/ds-react-internal": "^1.4.3",
"next": "^12.2.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"@navikt/ds-tailwind": "^1.4.2",
"@navikt/ds-tailwind": "^1.4.3",
"@types/node": "^17.0.35",
"@types/react": "^18.0.0",
"@types/react-dom": "^18.0.0",
+26 -26
View File
@@ -3166,7 +3166,7 @@ __metadata:
languageName: node
linkType: hard
"@navikt/ds-codemod@^1.4.0, @navikt/ds-codemod@workspace:@navikt/codemod":
"@navikt/ds-codemod@^1.4.3, @navikt/ds-codemod@workspace:@navikt/codemod":
version: 0.0.0-use.local
resolution: "@navikt/ds-codemod@workspace:@navikt/codemod"
dependencies:
@@ -3193,7 +3193,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-css-internal@^1.4.0, @navikt/ds-css-internal@workspace:@navikt/internal/css":
"@navikt/ds-css-internal@^1.4.3, @navikt/ds-css-internal@workspace:@navikt/internal/css":
version: 0.0.0-use.local
resolution: "@navikt/ds-css-internal@workspace:@navikt/internal/css"
dependencies:
@@ -3204,11 +3204,11 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-css@*, @navikt/ds-css@^1.4.0, @navikt/ds-css@workspace:@navikt/core/css":
"@navikt/ds-css@*, @navikt/ds-css@^1.4.3, @navikt/ds-css@workspace:@navikt/core/css":
version: 0.0.0-use.local
resolution: "@navikt/ds-css@workspace:@navikt/core/css"
dependencies:
"@navikt/ds-tokens": ^1.4.0
"@navikt/ds-tokens": ^1.4.3
normalize.css: ^8.0.1
postcss: ^8.4.0
postcss-cli: ^9.0.0
@@ -3217,7 +3217,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-icons@^1.4.0, @navikt/ds-icons@workspace:@navikt/icons":
"@navikt/ds-icons@^1.4.3, @navikt/ds-icons@workspace:@navikt/icons":
version: 0.0.0-use.local
resolution: "@navikt/ds-icons@workspace:@navikt/icons"
dependencies:
@@ -3247,12 +3247,12 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-react-internal@^1.4.0, @navikt/ds-react-internal@workspace:@navikt/internal/react":
"@navikt/ds-react-internal@^1.4.3, @navikt/ds-react-internal@workspace:@navikt/internal/react":
version: 0.0.0-use.local
resolution: "@navikt/ds-react-internal@workspace:@navikt/internal/react"
dependencies:
"@navikt/ds-icons": ^1.4.0
"@navikt/ds-react": ^1.4.0
"@navikt/ds-icons": ^1.4.3
"@navikt/ds-react": ^1.4.3
"@types/node": ^17.0.35
clsx: ^1.1.1
concurrently: 7.2.1
@@ -3269,12 +3269,12 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-react@*, @navikt/ds-react@^1.4.0, @navikt/ds-react@workspace:@navikt/core/react":
"@navikt/ds-react@*, @navikt/ds-react@^1.4.3, @navikt/ds-react@workspace:@navikt/core/react":
version: 0.0.0-use.local
resolution: "@navikt/ds-react@workspace:@navikt/core/react"
dependencies:
"@floating-ui/react-dom-interactions": 0.9.2
"@navikt/ds-icons": ^1.4.0
"@navikt/ds-icons": ^1.4.3
"@radix-ui/react-tabs": 1.0.0
"@radix-ui/react-toggle-group": 1.0.0
"@testing-library/dom": 8.13.0
@@ -3311,11 +3311,11 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-tailwind@^1.4.0, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
"@navikt/ds-tailwind@^1.4.3, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
version: 0.0.0-use.local
resolution: "@navikt/ds-tailwind@workspace:@navikt/core/tailwind"
dependencies:
"@navikt/ds-tokens": ^1.4.0
"@navikt/ds-tokens": ^1.4.3
"@types/jest": ^29.0.0
"@types/node": ^17.0.35
jest: ^29.0.0
@@ -3326,7 +3326,7 @@ __metadata:
languageName: unknown
linkType: soft
"@navikt/ds-tokens@^1.4.0, @navikt/ds-tokens@workspace:@navikt/core/tokens":
"@navikt/ds-tokens@^1.4.3, @navikt/ds-tokens@workspace:@navikt/core/tokens":
version: 0.0.0-use.local
resolution: "@navikt/ds-tokens@workspace:@navikt/core/tokens"
dependencies:
@@ -8341,14 +8341,14 @@ __metadata:
version: 0.0.0-use.local
resolution: "aksel.nav.no@workspace:aksel.nav.no"
dependencies:
"@navikt/ds-codemod": ^1.4.0
"@navikt/ds-css": ^1.4.0
"@navikt/ds-css-internal": ^1.4.0
"@navikt/ds-icons": ^1.4.0
"@navikt/ds-react": ^1.4.0
"@navikt/ds-react-internal": ^1.4.0
"@navikt/ds-tailwind": ^1.4.0
"@navikt/ds-tokens": ^1.4.0
"@navikt/ds-codemod": ^1.4.3
"@navikt/ds-css": ^1.4.3
"@navikt/ds-css-internal": ^1.4.3
"@navikt/ds-icons": ^1.4.3
"@navikt/ds-react": ^1.4.3
"@navikt/ds-react-internal": ^1.4.3
"@navikt/ds-tailwind": ^1.4.3
"@navikt/ds-tokens": ^1.4.3
prettier-plugin-tailwindcss: ^0.1.13
languageName: unknown
linkType: soft
@@ -21068,11 +21068,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "nextjs-demo@workspace:examples/next"
dependencies:
"@navikt/ds-css": ^1.4.0
"@navikt/ds-icons": ^1.4.0
"@navikt/ds-react": ^1.4.0
"@navikt/ds-react-internal": ^1.4.0
"@navikt/ds-tailwind": ^1.4.0
"@navikt/ds-css": ^1.4.3
"@navikt/ds-icons": ^1.4.3
"@navikt/ds-react": ^1.4.3
"@navikt/ds-react-internal": ^1.4.3
"@navikt/ds-tailwind": ^1.4.3
"@types/node": ^17.0.35
"@types/react": ^18.0.0
"@types/react-dom": ^18.0.0