mirror of
https://github.com/navikt/aksel.git
synced 2026-10-13 09:12:03 +00:00
Compare commits
16
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4174f9a7b4 | ||
|
|
608f158d70 | ||
|
|
34d41ecc78 | ||
|
|
7e62365a60 | ||
|
|
8565f410a1 | ||
|
|
46d70820df | ||
|
|
67e66ffe02 | ||
|
|
e19bf67b33 | ||
|
|
97c5f60e91 | ||
|
|
ea5293c28d | ||
|
|
6a58efa9a9 | ||
|
|
c95f33679e | ||
|
|
b52a5e02a0 | ||
|
|
ab3ef0d34b | ||
|
|
69798f6ee2 | ||
|
|
ee14586beb |
No files matched your search
@@ -15,3 +15,7 @@
|
||||
.rowgap[data-theme="dark"] {
|
||||
background-color: #262626;
|
||||
}
|
||||
|
||||
.rowgap-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@@ -1,5 +1,17 @@
|
||||
# @navikt/ds-codemod
|
||||
|
||||
## 1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
## 1.4.4
|
||||
|
||||
## 1.4.3
|
||||
|
||||
## 1.4.2
|
||||
|
||||
## 1.4.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-codemod",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.3",
|
||||
"description": "NAV designsystem codemods",
|
||||
"author": "NAV Designsystem team",
|
||||
"license": "MIT",
|
||||
|
||||
@@ -1,5 +1,39 @@
|
||||
# @navikt/ds-css
|
||||
|
||||
## 1.5.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Byttet om på alt-farge rekkefølge
|
||||
|
||||
## 1.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- :memo: Rename FilterChips to ToggleChips
|
||||
|
||||
## 1.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Flex-wrap chips.css
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1684](https://github.com/navikt/Designsystemet/pull/1684) [`e19bf67b3`](https://github.com/navikt/Designsystemet/commit/e19bf67b337dea39989c68b5e9c2591cf0d5b40f) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Oppdaterte tag-varianter
|
||||
|
||||
- [#1668](https://github.com/navikt/Designsystemet/pull/1668) [`97c5f60e9`](https://github.com/navikt/Designsystemet/commit/97c5f60e9111da7e08f55c8d0aa29581f0a9b1ca) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Chips komponent :sparkles:
|
||||
|
||||
## 1.4.4
|
||||
|
||||
## 1.4.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- :sparkles: Validering og inputFormat i Date-komponenter
|
||||
|
||||
## 1.4.2
|
||||
|
||||
## 1.4.1
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
.navds-chips {
|
||||
display: flex;
|
||||
gap: var(--navds-spacing-2);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.navds-chips :where(li) {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.navds-chips__chip {
|
||||
all: unset;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 0.125rem;
|
||||
margin: 0;
|
||||
padding: 0 var(--navds-spacing-3);
|
||||
text-decoration: none;
|
||||
border-radius: var(--navds-border-radius-full);
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.navds-chips--small .navds-chips__chip {
|
||||
min-height: 24px;
|
||||
padding: 0 var(--navds-spacing-2);
|
||||
}
|
||||
|
||||
.navds-chips__toggle {
|
||||
box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-border, var(--navds-global-color-gray-500));
|
||||
background-color: var(--ac-chip-toggle-bg, rgb(0 0 0 / 0.055));
|
||||
}
|
||||
|
||||
.navds-chips__toggle:hover {
|
||||
box-shadow: inset 0 0 0 1px var(--ac-chip-toggle-border-hover, var(--navds-global-color-gray-600));
|
||||
background-color: var(--ac-chip-toggle-bg-hover, rgb(0 0 0 / 0.1));
|
||||
}
|
||||
|
||||
.navds-chips__toggle[aria-pressed="true"] {
|
||||
box-shadow: none;
|
||||
background-color: var(--ac-chip-toggle-bg-pressed, var(--navds-global-color-deepblue-500));
|
||||
color: var(--ac-chip-toggle-text-pressed, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-chips__toggle[aria-pressed="true"]:hover {
|
||||
background-color: var(--ac-chip-toggle-bg-pressed-hover, var(--navds-global-color-deepblue-600));
|
||||
}
|
||||
|
||||
.navds-chips__toggle:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--navds-global-color-blue-800);
|
||||
}
|
||||
|
||||
.navds-chips__toggle[aria-pressed="true"]:focus-visible,
|
||||
.navds-chips__toggle:active:focus-visible {
|
||||
box-shadow: inset 0 0 0 1px var(--navds-global-color-white), 0 0 0 2px var(--navds-global-color-blue-800);
|
||||
}
|
||||
|
||||
.navds-chips__removable--action {
|
||||
background-color: var(--ac-chip-removable-action-bg, var(--navds-global-color-deepblue-500));
|
||||
color: var(--ac-chip-removable-action-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-chips__removable--neutral {
|
||||
color: var(--ac-chip-removable-neutral-text, var(--navds-global-color-gray-900));
|
||||
background-color: var(--ac-chip-removable-neutral-bg, rgb(0 0 0/ 0.055));
|
||||
box-shadow: inset 0 0 0 1px var(--ac-chip-removable-neutral-border, var(--navds-global-color-gray-500));
|
||||
}
|
||||
|
||||
.navds-chips__removable-icon,
|
||||
.navds-chips__toggle-icon {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: var(--navds-border-radius-full);
|
||||
}
|
||||
|
||||
.navds-chips--small .navds-chips__removable-icon {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
}
|
||||
|
||||
.navds-chips--small .navds-chips__removable-icon > svg {
|
||||
width: 0.75rem;
|
||||
}
|
||||
|
||||
.navds-chips__removable--action:focus-visible {
|
||||
box-shadow: inset 0 0 0 1px var(--navds-global-color-white), 0 0 0 2px var(--navds-global-color-blue-800);
|
||||
}
|
||||
|
||||
.navds-chips__removable--neutral:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--navds-global-color-blue-800);
|
||||
}
|
||||
|
||||
.navds-chips__removable--action:hover {
|
||||
background-color: var(--ac-chip-removable-action-bg-hover, var(--navds-global-color-deepblue-700));
|
||||
}
|
||||
|
||||
.navds-chips__removable--neutral:hover {
|
||||
background-color: var(--ac-chip-removable-action-bg-hover, rgb(0 0 0 / 0.1));
|
||||
box-shadow: inset 0 0 0 1px var(--ac-chip-removable-neutral-border-hover, var(--navds-global-color-gray-600));
|
||||
}
|
||||
|
||||
.navds-chips--icon-left {
|
||||
padding-left: var(--navds-spacing-1);
|
||||
}
|
||||
|
||||
.navds-chips--icon-right {
|
||||
padding-right: var(--navds-spacing-1);
|
||||
}
|
||||
|
||||
.navds-chips--small .navds-chips--icon-right {
|
||||
padding-right: 0.125rem;
|
||||
}
|
||||
|
||||
.navds-chips--small .navds-chips--icon-left {
|
||||
padding-left: 0.125rem;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
@import "button.css";
|
||||
@import "content-container.css";
|
||||
@import "chat.css";
|
||||
@import "chips.css";
|
||||
@import "guide-panel.css";
|
||||
@import "form/index.css";
|
||||
@import "help-text.css";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.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.5.3",
|
||||
"normalize.css": "^8.0.1",
|
||||
"postcss": "^8.4.0",
|
||||
"postcss-cli": "^9.0.0",
|
||||
|
||||
+93
-14
@@ -14,38 +14,117 @@
|
||||
|
||||
.navds-tag {
|
||||
border: 1px solid;
|
||||
border-color: var(--navds-tag-color-border);
|
||||
border-radius: var(--navds-border-radius-medium);
|
||||
background-color: var(--navds-tag-color-background);
|
||||
border-radius: var(--navds-border-radius-small);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.125rem var(--navds-spacing-3);
|
||||
padding: 0.125rem var(--navds-spacing-2);
|
||||
min-height: 32px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.navds-tag--small {
|
||||
min-height: 24px;
|
||||
padding-right: var(--navds-spacing-1);
|
||||
padding-left: var(--navds-spacing-1);
|
||||
padding: 0 0.375rem;
|
||||
}
|
||||
|
||||
.navds-tag--xsmall {
|
||||
min-height: 20px;
|
||||
padding: 0 var(--navds-spacing-1);
|
||||
}
|
||||
|
||||
.navds-tag--error {
|
||||
background-color: var(--navds-tag-color-error-background);
|
||||
border-color: var(--navds-tag-color-error-border);
|
||||
border-color: var(--ac-tag-error-border, var(--navds-global-color-red-500));
|
||||
background-color: var(--ac-tag-error-bg, var(--navds-global-color-red-50));
|
||||
color: var(--ac-tag-error-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--error-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-error-filled-bg, var(--navds-global-color-red-500));
|
||||
color: var(--ac-tag-error-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-tag--success {
|
||||
background-color: var(--navds-tag-color-success-background);
|
||||
border-color: var(--navds-tag-color-success-border);
|
||||
border-color: var(--ac-tag-success-border, var(--navds-global-color-green-500));
|
||||
background-color: var(--ac-tag-success-bg, var(--navds-global-color-green-50));
|
||||
color: var(--ac-tag-success-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--success-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-success-filled-bg, var(--navds-global-color-green-500));
|
||||
color: var(--ac-tag-success-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-tag--warning {
|
||||
background-color: var(--navds-tag-color-warning-background);
|
||||
border-color: var(--navds-tag-color-warning-border);
|
||||
border-color: var(--ac-tag-warning-border, var(--navds-global-color-orange-600));
|
||||
background-color: var(--ac-tag-warning-bg, var(--navds-global-color-orange-50));
|
||||
color: var(--ac-tag-warning-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--warning-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-warning-filled-bg, var(--navds-global-color-orange-500));
|
||||
color: var(--ac-tag-warning-filled-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--info {
|
||||
background-color: var(--navds-tag-color-info-background);
|
||||
border-color: var(--navds-tag-color-info-border);
|
||||
border-color: var(--ac-tag-info-border, var(--navds-global-color-lightblue-700));
|
||||
background-color: var(--ac-tag-info-bg, var(--navds-global-color-lightblue-50));
|
||||
color: var(--ac-tag-info-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--info-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-info-filled-bg, var(--navds-global-color-lightblue-500));
|
||||
color: var(--ac-tag-info-filled-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--neutral {
|
||||
border-color: var(--ac-tag-neutral-border, var(--navds-global-color-gray-500));
|
||||
background-color: var(--ac-tag-neutral-bg, var(--navds-global-color-gray-100));
|
||||
color: var(--ac-tag-neutral-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--neutral-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-neutral-filled-bg, var(--navds-global-color-gray-800));
|
||||
color: var(--ac-tag-neutral-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-tag--alt1 {
|
||||
border-color: var(--ac-tag-alt1-border, var(--navds-global-color-purple-400));
|
||||
background-color: var(--ac-tag-alt1-bg, var(--navds-global-color-purple-100));
|
||||
color: var(--ac-tag-alt1-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--alt1-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-alt1-filled-bg, var(--navds-global-color-purple-400));
|
||||
color: var(--ac-tag-alt1-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-tag--alt2 {
|
||||
border-color: var(--ac-tag-alt2-border, var(--navds-global-color-limegreen-500));
|
||||
background-color: var(--ac-tag-alt2-bg, var(--navds-global-color-limegreen-100));
|
||||
color: var(--ac-tag-alt2-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--alt2-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-alt2-filled-bg, var(--navds-global-color-limegreen-400));
|
||||
color: var(--ac-tag-alt2-filled-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--alt3 {
|
||||
border-color: var(--ac-tag-alt3-border, var(--navds-global-color-deepblue-400));
|
||||
background-color: var(--ac-tag-alt3-bg, var(--navds-global-color-deepblue-100));
|
||||
color: var(--ac-tag-alt3-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--alt3-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-alt3-filled-bg, var(--navds-global-color-deepblue-500));
|
||||
color: var(--ac-tag-alt3-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
@@ -1,5 +1,61 @@
|
||||
# @navikt/ds-react
|
||||
|
||||
## 1.5.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-icons@1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- :memo: Rename FilterChips to ToggleChips
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-icons@1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Flex-wrap chips.css
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-icons@1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#1684](https://github.com/navikt/Designsystemet/pull/1684) [`e19bf67b3`](https://github.com/navikt/Designsystemet/commit/e19bf67b337dea39989c68b5e9c2591cf0d5b40f) Thanks [@KenAJoh](https://github.com/KenAJoh)! - :sparkles: Oppdaterte tag-varianter
|
||||
|
||||
- [#1668](https://github.com/navikt/Designsystemet/pull/1668) [`97c5f60e9`](https://github.com/navikt/Designsystemet/commit/97c5f60e9111da7e08f55c8d0aa29581f0a9b1ca) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Chips komponent :sparkles:
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-icons@1.5.0
|
||||
|
||||
## 1.4.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Eksponerer validation-typer
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-icons@1.4.4
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.3",
|
||||
"description": "NAV designsystem react components",
|
||||
"author": "NAV Designsystem team",
|
||||
"license": "MIT",
|
||||
@@ -33,11 +33,11 @@
|
||||
"clean": "rimraf cjs esm",
|
||||
"build": "concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
|
||||
"watch": "tsc --watch -p tsconfig.esm.json",
|
||||
"test": "jest"
|
||||
"test": "TZ=UTC jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom-interactions": "0.9.2",
|
||||
"@navikt/ds-icons": "^1.4.2",
|
||||
"@navikt/ds-icons": "^1.5.3",
|
||||
"@radix-ui/react-tabs": "1.0.0",
|
||||
"@radix-ui/react-toggle-group": "1.0.0",
|
||||
"clsx": "^1.2.1",
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import ToggleChips, { ToggleChipsType } from "./Toggle";
|
||||
import RemovableChips, { RemovableChipsType } from "./Removable";
|
||||
|
||||
export interface ChipsProps extends HTMLAttributes<HTMLUListElement> {
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes padding and font-sizes
|
||||
* @default "medium"
|
||||
*/
|
||||
size?: "medium" | "small";
|
||||
}
|
||||
|
||||
interface ChipsComponent
|
||||
extends React.ForwardRefExoticComponent<
|
||||
ChipsProps & React.RefAttributes<HTMLUListElement>
|
||||
> {
|
||||
Toggle: ToggleChipsType;
|
||||
Removable: RemovableChipsType;
|
||||
}
|
||||
|
||||
export const Chips: ChipsComponent = forwardRef<HTMLUListElement, ChipsProps>(
|
||||
({ className, size = "medium", children, ...rest }, ref) => {
|
||||
return (
|
||||
<ul
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl("navds-chips", className, `navds-chips--${size}`, {
|
||||
"navds-body-short navds-body-short--small": size === "medium",
|
||||
"navds-detail navds-detail--small": size === "small",
|
||||
})}
|
||||
>
|
||||
{React.Children.map(children, (chip, index) => {
|
||||
return <li key={index + (chip?.toString() ?? "")}>{chip}</li>;
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
) as ChipsComponent;
|
||||
|
||||
Chips.Toggle = ToggleChips;
|
||||
Chips.Removable = RemovableChips;
|
||||
|
||||
export default Chips;
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Close } from "@navikt/ds-icons";
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef } from "react";
|
||||
import { OverridableComponent } from "..";
|
||||
|
||||
export interface RemovableChipsProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
children: string;
|
||||
/**
|
||||
* Chip-variants
|
||||
* @default "action"
|
||||
*/
|
||||
variant?: "action" | "neutral";
|
||||
/**
|
||||
* Replaces label read for screen-readers
|
||||
* @default "slett filter"
|
||||
*/
|
||||
removeLabel?: string;
|
||||
/**
|
||||
* Click callback
|
||||
*/
|
||||
onDelete?: () => void;
|
||||
}
|
||||
|
||||
export interface RemovableChipsType
|
||||
extends OverridableComponent<RemovableChipsProps, HTMLButtonElement> {}
|
||||
|
||||
export const RemovableChips: OverridableComponent<
|
||||
RemovableChipsProps,
|
||||
HTMLButtonElement
|
||||
> = forwardRef(
|
||||
(
|
||||
{
|
||||
className,
|
||||
children,
|
||||
variant = "action",
|
||||
as: Component = "button",
|
||||
removeLabel = "slett",
|
||||
onDelete,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<Component
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl(
|
||||
"navds-chips__chip navds-chips__removable navds-chips--icon-right",
|
||||
className,
|
||||
`navds-chips__removable--${variant}`
|
||||
)}
|
||||
aria-label={`${children} ${removeLabel}`}
|
||||
onClick={(e) => {
|
||||
onDelete?.();
|
||||
rest?.onClick?.(e);
|
||||
}}
|
||||
>
|
||||
<span className="navds-chips__chip-text">{children}</span>
|
||||
<span className="navds-chips__removable-icon">
|
||||
<Close aria-hidden />
|
||||
</span>
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
) as RemovableChipsType;
|
||||
|
||||
export default RemovableChips;
|
||||
@@ -0,0 +1,41 @@
|
||||
import { SuccessStroke } from "@navikt/ds-icons";
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef } from "react";
|
||||
import { OverridableComponent } from "..";
|
||||
|
||||
export interface ToggleChipsProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
children: string;
|
||||
/**
|
||||
* Toggles aria-pressed and visual-changes
|
||||
*/
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
export interface ToggleChipsType
|
||||
extends OverridableComponent<ToggleChipsProps, HTMLButtonElement> {}
|
||||
|
||||
export const ToggleChips: ToggleChipsType = forwardRef(
|
||||
(
|
||||
{ className, children, selected, as: Component = "button", ...rest },
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<Component
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl("navds-chips__chip navds-chips__toggle", className, {
|
||||
"navds-chips--icon-left": selected,
|
||||
})}
|
||||
aria-pressed={selected}
|
||||
>
|
||||
{selected && (
|
||||
<SuccessStroke aria-hidden className="navds-chips__toggle-icon" />
|
||||
)}
|
||||
<span className="navds-chips__chip-text">{children}</span>
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ToggleChips;
|
||||
@@ -0,0 +1,165 @@
|
||||
import React, { useState } from "react";
|
||||
import { Chips } from ".";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Chips",
|
||||
component: Chips,
|
||||
argTypes: {
|
||||
type: {
|
||||
control: {
|
||||
type: "radio",
|
||||
options: ["toggle", "removable"],
|
||||
},
|
||||
},
|
||||
size: {
|
||||
control: {
|
||||
type: "radio",
|
||||
options: ["medium", "small"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
|
||||
|
||||
export const Default = (props) => {
|
||||
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
|
||||
const [filter, setFilter] = useState(options);
|
||||
|
||||
if (props.type === "toggle") {
|
||||
return (
|
||||
<Chips size={props.size ?? "medium"}>
|
||||
{options.map((c) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(c)}
|
||||
key={c}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(c)
|
||||
? selected.filter((x) => x !== c)
|
||||
: [...selected, c]
|
||||
)
|
||||
}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Chips size={props.size ?? "medium"}>
|
||||
{filter.map((c) => (
|
||||
<Chips.Removable
|
||||
key={c}
|
||||
onClick={() => setFilter((x) => x.filter((y) => y !== c))}
|
||||
>
|
||||
{c}
|
||||
</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
);
|
||||
};
|
||||
|
||||
export const Toggle = () => {
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
return (
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(y)}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(y)
|
||||
? selected.filter((x) => x !== y)
|
||||
: [...selected, y]
|
||||
)
|
||||
}
|
||||
key={y}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
);
|
||||
};
|
||||
|
||||
export const Removable = () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Removable key={y}>{c}</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Removable variant="neutral" key={y}>
|
||||
{c}
|
||||
</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Regular = () => {
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
return (
|
||||
<div className="colgap">
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Removable key={y}>{c}</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(y)}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(y)
|
||||
? selected.filter((x) => x !== y)
|
||||
: [...selected, y]
|
||||
)
|
||||
}
|
||||
key={y}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Small = () => {
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
return (
|
||||
<div className="colgap">
|
||||
<Chips size="small">
|
||||
{options.map((c, y) => (
|
||||
<Chips.Removable key={y}>{c}</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
<Chips size="small">
|
||||
{options.map((c, y) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(y)}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(y)
|
||||
? selected.filter((x) => x !== y)
|
||||
: [...selected, y]
|
||||
)
|
||||
}
|
||||
key={y}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { default as Chips, ChipsProps } from "./Chips";
|
||||
@@ -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-03T00:00:00.000Z",
|
||||
to: "2022-08-03T00: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-03T00: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,
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ export {
|
||||
UNSAFE_useDatepicker,
|
||||
UNSAFE_useMonthpicker,
|
||||
UNSAFE_useRangeDatepicker,
|
||||
RangeValidationT,
|
||||
DateValidationT,
|
||||
MonthValidationT,
|
||||
} from "./hooks";
|
||||
export {
|
||||
default as UNSAFE_MonthPicker,
|
||||
|
||||
@@ -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");
|
||||
};
|
||||
@@ -16,6 +16,7 @@ export * from "./panel";
|
||||
export * from "./popover";
|
||||
export * from "./read-more";
|
||||
export * from "./chat";
|
||||
export * from "./chips";
|
||||
export * from "./stepper";
|
||||
export * from "./tag";
|
||||
export * from "./toggle-group";
|
||||
|
||||
@@ -3,19 +3,31 @@ import cl from "clsx";
|
||||
import { BodyShort, Detail } from "..";
|
||||
|
||||
export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
|
||||
/**
|
||||
* Tag label
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes background and border color
|
||||
* Changes visual profile of tag
|
||||
*/
|
||||
variant: "warning" | "error" | "info" | "success";
|
||||
variant:
|
||||
| "warning"
|
||||
| "warning-filled"
|
||||
| "error"
|
||||
| "error-filled"
|
||||
| "info"
|
||||
| "info-filled"
|
||||
| "success"
|
||||
| "success-filled"
|
||||
| "neutral"
|
||||
| "neutral-filled"
|
||||
| "alt1"
|
||||
| "alt1-filled"
|
||||
| "alt2"
|
||||
| "alt2-filled"
|
||||
| "alt3"
|
||||
| "alt3-filled";
|
||||
/**
|
||||
* Changes padding and font-sizes
|
||||
* @default "medium"
|
||||
*/
|
||||
size?: "medium" | "small";
|
||||
size?: "medium" | "small" | "xsmall";
|
||||
}
|
||||
|
||||
export const Tag = forwardRef<HTMLSpanElement, TagProps>(
|
||||
@@ -27,7 +39,7 @@ export const Tag = forwardRef<HTMLSpanElement, TagProps>(
|
||||
{...rest}
|
||||
ref={ref}
|
||||
as="span"
|
||||
size={size}
|
||||
size={size === "medium" ? "medium" : "small"}
|
||||
className={cl(
|
||||
"navds-tag",
|
||||
className,
|
||||
|
||||
@@ -9,17 +9,70 @@ export default {
|
||||
defaultValue: "info",
|
||||
control: {
|
||||
type: "radio",
|
||||
options: ["error", "warning", "info", "success"],
|
||||
options: [
|
||||
"warning",
|
||||
"error",
|
||||
"info",
|
||||
"success",
|
||||
"neutral",
|
||||
"alt1",
|
||||
"alt2",
|
||||
"alt3",
|
||||
"warning-filled",
|
||||
"error-filled",
|
||||
"info-filled",
|
||||
"success-filled",
|
||||
"neutral-filled",
|
||||
"alt1-filled",
|
||||
"alt2-filled",
|
||||
"alt3-filled",
|
||||
],
|
||||
},
|
||||
},
|
||||
size: {
|
||||
defaultValue: "medium",
|
||||
control: {
|
||||
type: "radio",
|
||||
options: ["xsmall", "small", "medium"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const variants: Array<"error" | "warning" | "info" | "success"> = [
|
||||
"error",
|
||||
const variants: Array<
|
||||
| "warning"
|
||||
| "warning-filled"
|
||||
| "error"
|
||||
| "error-filled"
|
||||
| "info"
|
||||
| "info-filled"
|
||||
| "success"
|
||||
| "success-filled"
|
||||
| "neutral"
|
||||
| "neutral-filled"
|
||||
| "alt1"
|
||||
| "alt1-filled"
|
||||
| "alt2"
|
||||
| "alt2-filled"
|
||||
| "alt3"
|
||||
| "alt3-filled"
|
||||
> = [
|
||||
"warning",
|
||||
"error",
|
||||
"info",
|
||||
"success",
|
||||
"neutral",
|
||||
"alt1",
|
||||
"alt2",
|
||||
"alt3",
|
||||
"warning-filled",
|
||||
"error-filled",
|
||||
"info-filled",
|
||||
"success-filled",
|
||||
"neutral-filled",
|
||||
"alt1-filled",
|
||||
"alt2-filled",
|
||||
"alt3-filled",
|
||||
];
|
||||
|
||||
export const Default = (props) => (
|
||||
@@ -34,10 +87,34 @@ Default.args = {
|
||||
|
||||
export const Small = () => {
|
||||
return (
|
||||
<div className="rowgap">
|
||||
<div className="rowgap rowgap-wrap">
|
||||
{variants.map((variant, i) => (
|
||||
<Tag key={variant} variant={variant} size="small">
|
||||
{new Array(i + 1).fill("Id elit esse")}
|
||||
{variant}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const xSmall = () => {
|
||||
return (
|
||||
<div className="rowgap rowgap-wrap">
|
||||
{variants.map((variant, i) => (
|
||||
<Tag key={variant} variant={variant} size="xsmall">
|
||||
{variant}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Variants = () => {
|
||||
return (
|
||||
<div className="rowgap rowgap-wrap">
|
||||
{variants.map((variant, i) => (
|
||||
<Tag key={variant} variant={variant}>
|
||||
{variant}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @navikt/ds-tailwind
|
||||
|
||||
## 1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
## 1.4.4
|
||||
|
||||
## 1.4.3
|
||||
|
||||
## 1.4.2
|
||||
|
||||
## 1.4.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tailwind",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.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.5.3",
|
||||
"@types/jest": "^29.0.0",
|
||||
"@types/node": "^17.0.35",
|
||||
"jest": "^29.0.0",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @navikt/ds-tokens
|
||||
|
||||
## 1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
## 1.4.4
|
||||
|
||||
## 1.4.3
|
||||
|
||||
## 1.4.2
|
||||
|
||||
## 1.4.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tokens",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.3",
|
||||
"description": "Auto-generated design-tokens for NAV design-systems framework",
|
||||
"author": "NAV Designsystem team",
|
||||
"keywords": [
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @navikt/ds-icons
|
||||
|
||||
## 1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
## 1.4.4
|
||||
|
||||
## 1.4.3
|
||||
|
||||
## 1.4.2
|
||||
|
||||
## 1.4.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-icons",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.3",
|
||||
"description": "Aksel icons",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# @navikt/ds-css-internal
|
||||
|
||||
## 1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
## 1.4.4
|
||||
|
||||
## 1.4.3
|
||||
|
||||
## 1.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css-internal",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.3",
|
||||
"description": "Css for NAV internal Designsystem components",
|
||||
"author": "NAV Designsystem team",
|
||||
"keywords": [
|
||||
|
||||
@@ -1,5 +1,53 @@
|
||||
# @navikt/ds-react-internal
|
||||
|
||||
## 1.5.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-react@1.5.3
|
||||
- @navikt/ds-icons@1.5.3
|
||||
|
||||
## 1.5.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-react@1.5.2
|
||||
- @navikt/ds-icons@1.5.2
|
||||
|
||||
## 1.5.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-react@1.5.1
|
||||
- @navikt/ds-icons@1.5.1
|
||||
|
||||
## 1.5.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`e19bf67b3`](https://github.com/navikt/Designsystemet/commit/e19bf67b337dea39989c68b5e9c2591cf0d5b40f), [`97c5f60e9`](https://github.com/navikt/Designsystemet/commit/97c5f60e9111da7e08f55c8d0aa29581f0a9b1ca)]:
|
||||
- @navikt/ds-react@1.5.0
|
||||
- @navikt/ds-icons@1.5.0
|
||||
|
||||
## 1.4.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-react@1.4.4
|
||||
- @navikt/ds-icons@1.4.4
|
||||
|
||||
## 1.4.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-react@1.4.3
|
||||
- @navikt/ds-icons@1.4.3
|
||||
|
||||
## 1.4.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react-internal",
|
||||
"version": "1.4.2",
|
||||
"version": "1.5.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.5.3",
|
||||
"@navikt/ds-react": "^1.5.3",
|
||||
"clsx": "^1.1.1",
|
||||
"copy-to-clipboard": "^3.3.1"
|
||||
},
|
||||
|
||||
@@ -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.5.3",
|
||||
"@navikt/ds-css": "^1.5.3",
|
||||
"@navikt/ds-css-internal": "^1.5.3",
|
||||
"@navikt/ds-icons": "^1.5.3",
|
||||
"@navikt/ds-react": "^1.5.3",
|
||||
"@navikt/ds-react-internal": "^1.5.3",
|
||||
"@navikt/ds-tailwind": "^1.5.3",
|
||||
"@navikt/ds-tokens": "^1.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier-plugin-tailwindcss": "^0.1.13"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Expand } from "@navikt/ds-icons";
|
||||
import { BodyShort, Detail } from "@navikt/ds-react";
|
||||
import { BodyShort, Detail, Tag } from "@navikt/ds-react";
|
||||
import cl from "classnames";
|
||||
import NextLink from "next/link";
|
||||
import React, { useContext, useMemo, useState } from "react";
|
||||
@@ -59,22 +59,23 @@ const NavItem = ({
|
||||
)}
|
||||
>
|
||||
{item.title}
|
||||
{item?.link?.status &&
|
||||
["deprecated", "beta"].includes(item.link.status?.tag) && (
|
||||
<Detail
|
||||
className={cl(
|
||||
"font-regular ml-2 rounded-full border-none px-2 capitalize",
|
||||
{
|
||||
"text-text bg-gray-200 capitalize ring-1 ring-inset ring-gray-900/10":
|
||||
item.link.status?.tag === "deprecated",
|
||||
"text-text bg-purple-50 ring-1 ring-inset ring-purple-900/10":
|
||||
item.link.status?.tag === "beta",
|
||||
<span className="ml-2 capitalize">
|
||||
{item?.link?.status &&
|
||||
["deprecated", "beta", "new"].includes(item.link.status?.tag) && (
|
||||
<Tag
|
||||
size="xsmall"
|
||||
variant={
|
||||
item.link.status?.tag === "beta"
|
||||
? "alt1"
|
||||
: item.link.status?.tag === "deprecated"
|
||||
? "neutral"
|
||||
: "info"
|
||||
}
|
||||
)}
|
||||
>
|
||||
{item.link.status?.tag}
|
||||
</Detail>
|
||||
)}
|
||||
>
|
||||
{item.link.status?.tag}
|
||||
</Tag>
|
||||
)}
|
||||
</span>
|
||||
</BodyShort>
|
||||
</NextLink>
|
||||
</li>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { capitalize, Snippet } from "@/components";
|
||||
import { withErrorBoundary } from "@/error-boundary";
|
||||
import { SanityT } from "@/lib";
|
||||
import { SuccessStroke } from "@navikt/ds-icons";
|
||||
import { BodyLong, Link } from "@navikt/ds-react";
|
||||
import * as Tabs from "@radix-ui/react-tabs";
|
||||
import { BodyLong, Link, Chips } from "@navikt/ds-react";
|
||||
import cl from "classnames";
|
||||
import { useEffect, useState } from "react";
|
||||
import { CodeSandbox } from "./CodeSandbox";
|
||||
@@ -57,8 +55,6 @@ const ComponentExamples = ({
|
||||
str
|
||||
.replace(/[^\w]|_/g, " ")
|
||||
.replace(/\s+/g, " ")
|
||||
.match(/\D/g)
|
||||
.join("")
|
||||
.trim()
|
||||
) ?? str;
|
||||
|
||||
@@ -107,51 +103,46 @@ const ComponentExamples = ({
|
||||
);
|
||||
}
|
||||
|
||||
const active = activeExample ?? node?.dir?.filer?.[0]?.navn;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tabs.Root
|
||||
defaultValue={node.dir.filer[0].navn}
|
||||
onValueChange={(v) => setActiveExample(v)}
|
||||
>
|
||||
<Tabs.List className="mb-5 flex max-w-xl flex-wrap gap-2">
|
||||
<div>
|
||||
<div className="mb-5 max-w-xl">
|
||||
<Chips>
|
||||
{node.dir.filer.map((fil) => {
|
||||
return (
|
||||
<Tabs.Trigger
|
||||
<Chips.Toggle
|
||||
key={fil._key}
|
||||
value={fil.navn}
|
||||
className={cl(
|
||||
"flex h-8 items-center justify-center rounded-full text-base ring-inset ring-gray-600 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-800",
|
||||
{
|
||||
"gap-1 bg-gray-200 pr-3 pl-[10px] ring-2 hover:bg-gray-100":
|
||||
activeExample === fil.navn,
|
||||
"bg-white px-3 ring-1 hover:bg-gray-100":
|
||||
activeExample !== fil.navn,
|
||||
}
|
||||
)}
|
||||
selected={active === fil.navn}
|
||||
onClick={() => setActiveExample(fil.navn)}
|
||||
>
|
||||
{activeExample === fil.navn && (
|
||||
<SuccessStroke aria-hidden className="h-6 w-6" />
|
||||
)}
|
||||
{fixName(fil.navn)}
|
||||
</Tabs.Trigger>
|
||||
</Chips.Toggle>
|
||||
);
|
||||
})}
|
||||
</Tabs.List>
|
||||
{node.dir.filer.map((fil) => {
|
||||
return (
|
||||
<Tabs.Content key={fil._key} value={fil.navn} tabIndex={-1}>
|
||||
{fil?.description && (
|
||||
<BodyLong className="mb-2">{fil.description}</BodyLong>
|
||||
)}
|
||||
{element(
|
||||
`/eksempler/${node.dir.title}/${fil.navn.replace(".tsx", "")}`,
|
||||
fil.innhold
|
||||
)}
|
||||
</Tabs.Content>
|
||||
);
|
||||
})}
|
||||
</Tabs.Root>
|
||||
</>
|
||||
</Chips>
|
||||
</div>
|
||||
{node.dir.filer.map((fil) => {
|
||||
return (
|
||||
<div
|
||||
key={fil._key}
|
||||
className={cl({
|
||||
visible: active === fil.navn,
|
||||
hidden: active !== fil.navn,
|
||||
})}
|
||||
>
|
||||
{fil?.description && (
|
||||
<BodyLong className="mb-2">{fil.description}</BodyLong>
|
||||
)}
|
||||
{element(
|
||||
`/eksempler/${node.dir.title}/${fil.navn.replace(".tsx", "")}`,
|
||||
fil.innhold
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -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"
|
||||
);
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
import { test, expect } from "@playwright/test";
|
||||
|
||||
test("Test sandbox-examples", async ({ page }) => {
|
||||
await page.goto("http://localhost:3000/designsystem/komponenter/checkbox");
|
||||
|
||||
await page.frameLocator("#Kode-eksempler").getByLabel("Bakerst").check();
|
||||
|
||||
await page.frameLocator("#Kode-eksempler").getByLabel("Midterst").check();
|
||||
|
||||
await page.frameLocator("#Kode-eksempler").getByLabel("Fremst").check();
|
||||
|
||||
await page.getByRole("tab", { name: "Small" }).click();
|
||||
|
||||
await page.frameLocator("#Kode-eksempler").getByLabel("Midterst").check();
|
||||
|
||||
await page.getByRole("tab", { name: "Description" }).click();
|
||||
|
||||
await page.frameLocator("#Kode-eksempler").getByLabel("Midterst").check();
|
||||
|
||||
await page.getByRole("tab", { name: "Indeterminate" }).click();
|
||||
|
||||
await page.frameLocator("#Kode-eksempler").getByLabel("Fremst").check();
|
||||
|
||||
await page.frameLocator("#Kode-eksempler").getByLabel("Bakerst").check();
|
||||
|
||||
await page.frameLocator("#Kode-eksempler").getByLabel("Midterst").check();
|
||||
|
||||
await page.getByRole("link", { name: "Button" }).click();
|
||||
|
||||
await expect(page).toHaveURL(
|
||||
"http://localhost:3000/designsystem/komponenter/button"
|
||||
);
|
||||
|
||||
await page
|
||||
.frameLocator("#Kode-eksempler")
|
||||
.getByRole("button", { name: "Primary" })
|
||||
.click();
|
||||
|
||||
await page.getByRole("tab", { name: "Icon" }).click();
|
||||
|
||||
await page
|
||||
.frameLocator("#Kode-eksempler")
|
||||
.getByRole("button", { name: "Rediger" })
|
||||
.click();
|
||||
|
||||
await page.getByRole("link", { name: "Search" }).click();
|
||||
await expect(page).toHaveURL(
|
||||
"http://localhost:3000/designsystem/komponenter/search"
|
||||
);
|
||||
|
||||
await page
|
||||
.frameLocator("#Kode-eksempler")
|
||||
.getByLabel("Søk alle NAV sine sider")
|
||||
.click();
|
||||
|
||||
await page
|
||||
.frameLocator("#Kode-eksempler")
|
||||
.getByLabel("Søk alle NAV sine sider")
|
||||
.fill("test");
|
||||
|
||||
await page
|
||||
.frameLocator("#Kode-eksempler")
|
||||
.getByRole("button", { name: "Søk" })
|
||||
.click();
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Chips } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
import { useState } from "react";
|
||||
|
||||
const Example = () => {
|
||||
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
|
||||
|
||||
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
|
||||
const [filter, setFilter] = useState(options);
|
||||
|
||||
return (
|
||||
<div className="grid gap-4">
|
||||
<Chips>
|
||||
{options.map((c) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(c)}
|
||||
key={c}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(c)
|
||||
? selected.filter((x) => x !== c)
|
||||
: [...selected, c]
|
||||
)
|
||||
}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
<Chips>
|
||||
{filter.map((c) => (
|
||||
<Chips.Removable
|
||||
key={c}
|
||||
onClick={() =>
|
||||
setFilter((x) =>
|
||||
x.length === 1 ? options : x.filter((y) => y !== c)
|
||||
)
|
||||
}
|
||||
>
|
||||
{c}
|
||||
</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 0,
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Chips } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
import { useState } from "react";
|
||||
|
||||
const Example = () => {
|
||||
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
|
||||
|
||||
const [filter, setFilter] = useState(options);
|
||||
|
||||
return (
|
||||
<Chips>
|
||||
{filter.map((c) => (
|
||||
<Chips.Removable
|
||||
key={c}
|
||||
onClick={() =>
|
||||
setFilter((x) =>
|
||||
x.length === 1 ? options : x.filter((y) => y !== c)
|
||||
)
|
||||
}
|
||||
>
|
||||
{c}
|
||||
</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 2,
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
import { Chips } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
import { useState } from "react";
|
||||
|
||||
const Example = () => {
|
||||
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
|
||||
|
||||
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
|
||||
const [filter, setFilter] = useState(options);
|
||||
|
||||
return (
|
||||
<div className="grid gap-4">
|
||||
<Chips size="small">
|
||||
{options.map((c) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(c)}
|
||||
key={c}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(c)
|
||||
? selected.filter((x) => x !== c)
|
||||
: [...selected, c]
|
||||
)
|
||||
}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
<Chips size="small">
|
||||
{filter.map((c) => (
|
||||
<Chips.Removable
|
||||
key={c}
|
||||
onClick={() =>
|
||||
setFilter((x) =>
|
||||
x.length === 1 ? options : x.filter((y) => y !== c)
|
||||
)
|
||||
}
|
||||
>
|
||||
{c}
|
||||
</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 3,
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Chips } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
import { useState } from "react";
|
||||
|
||||
const Example = () => {
|
||||
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
|
||||
|
||||
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
|
||||
|
||||
return (
|
||||
<Chips>
|
||||
{options.map((c) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(c)}
|
||||
key={c}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(c)
|
||||
? selected.filter((x) => x !== c)
|
||||
: [...selected, c]
|
||||
)
|
||||
}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 1,
|
||||
};
|
||||
@@ -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.",
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Tag variant="alt1">Alt1</Tag>
|
||||
<Tag variant="alt1-filled">Alt1</Tag>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 5,
|
||||
desc: "Har ingen global betydning. Tjenesten/produktet kan bestemme hva de symboliserer.",
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Tag variant="alt2">Alt2</Tag>
|
||||
<Tag variant="alt2-filled">Alt2</Tag>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 6,
|
||||
desc: "Har ingen global betydning. Tjenesten/produktet kan bestemme hva de symboliserer.",
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Tag variant="alt3">Alt3</Tag>
|
||||
<Tag variant="alt3-filled">Alt3</Tag>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 7,
|
||||
desc: "Har ingen global betydning. Tjenesten/produktet kan bestemme hva de symboliserer.",
|
||||
};
|
||||
@@ -2,11 +2,17 @@ import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return <Tag variant="error">Error</Tag>;
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Tag variant="error">Error</Tag>
|
||||
<Tag variant="error-filled">Error</Tag>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 3,
|
||||
index: 4,
|
||||
desc: "Beskriver noe som er farlig, tjenestebrudd, irreversibelt, etc.",
|
||||
};
|
||||
@@ -2,11 +2,17 @@ import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return <Tag variant="info">Info</Tag>;
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Tag variant="info">Info</Tag>
|
||||
<Tag variant="info-filled">Info</Tag>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 0,
|
||||
index: 1,
|
||||
desc: "Beskriver noe som er til opplysning, nyhet, etc.",
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Tag variant="neutral">Neutral</Tag>
|
||||
<Tag variant="neutral-filled">Neutral</Tag>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 0,
|
||||
desc: "Beskriver noe nøytralt",
|
||||
};
|
||||
@@ -12,5 +12,5 @@ const Example = () => {
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 4,
|
||||
index: 20,
|
||||
};
|
||||
@@ -2,11 +2,17 @@ import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return <Tag variant="success">Success</Tag>;
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Tag variant="success">Success</Tag>
|
||||
<Tag variant="success-filled">Success</Tag>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 1,
|
||||
index: 2,
|
||||
desc: "Beskriver noe som er positivt, gjennomført, vellykket, etc.",
|
||||
};
|
||||
@@ -2,11 +2,17 @@ import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return <Tag variant="warning">Warning</Tag>;
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Tag variant="warning">Warning</Tag>
|
||||
<Tag variant="warning-filled">Warning</Tag>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 2,
|
||||
index: 3,
|
||||
desc: "Beskriver noe som er en advarsel, usikkert, noe som må utbedres, etc.",
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Tag } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return (
|
||||
<Tag variant="info" size="xsmall">
|
||||
Info
|
||||
</Tag>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 21,
|
||||
};
|
||||
@@ -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.5.3",
|
||||
"@navikt/ds-icons": "^1.5.3",
|
||||
"@navikt/ds-react": "^1.5.3",
|
||||
"@navikt/ds-react-internal": "^1.5.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.5.3",
|
||||
"@types/node": "^17.0.35",
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
|
||||
@@ -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.5.2, @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.5.2, @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.5.2, @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.5.2
|
||||
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.5.2, @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.5.2, @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.5.2
|
||||
"@navikt/ds-react": ^1.5.2
|
||||
"@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.5.2, @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.5.2
|
||||
"@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.5.2, @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.5.2
|
||||
"@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.5.2, @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.5.2
|
||||
"@navikt/ds-css": ^1.5.2
|
||||
"@navikt/ds-css-internal": ^1.5.2
|
||||
"@navikt/ds-icons": ^1.5.2
|
||||
"@navikt/ds-react": ^1.5.2
|
||||
"@navikt/ds-react-internal": ^1.5.2
|
||||
"@navikt/ds-tailwind": ^1.5.2
|
||||
"@navikt/ds-tokens": ^1.5.2
|
||||
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.5.2
|
||||
"@navikt/ds-icons": ^1.5.2
|
||||
"@navikt/ds-react": ^1.5.2
|
||||
"@navikt/ds-react-internal": ^1.5.2
|
||||
"@navikt/ds-tailwind": ^1.5.2
|
||||
"@types/node": ^17.0.35
|
||||
"@types/react": ^18.0.0
|
||||
"@types/react-dom": ^18.0.0
|
||||
|
||||
Reference in new issue
Block a user