Compare commits

...
Author SHA1 Message Date
Ken 7ef1be47b7 📝 Changeset 2022-11-16 15:29:46 +01:00
Ken dde30617e3 💄 Toggle-small gap 2022-11-16 15:29:03 +01:00
Ken 609678667f 🔥 Fjernet console.log 2022-11-16 09:46:42 +01:00
Ken 180ecd89bf 🎨 defaultMonth/Year prop 2022-11-15 12:15:09 +01:00
Ken 635b0859b8 defaultMonth/Year prop 2022-11-15 12:13:02 +01:00
Ken 10cbe105bc 🐛 Redirect funker nå med æøå 2022-11-12 21:20:11 +01:00
Ken f97eed8396 📝 Hide redirects from sanity search 2022-11-12 20:03:33 +01:00
Ken 119d9df7b5 📝 Sanity types 2022-11-12 19:45:02 +01:00
Ken 846d18cd23 🎨 Dynamic redirects 2022-11-12 19:40:14 +01:00
Ken 833c35cbbc 🐛 Headings i alert scrollet ikke ved linking 2022-11-11 12:43:35 +01:00
Ken 08353f50b5 💄 tema-lenker 2022-11-11 11:34:55 +01:00
Ken fba81fb4eb 🐛 Fikset tags komponentoversikt 2022-11-10 12:00:49 +01:00
Ken 9d9c6e9bfa 🐛 Fikset tags komponentoversikt 2022-11-10 11:07:34 +01:00
Ken 4dad81714f 🎨 Oppdatert tilbakemeldingsform for personvern 2022-11-09 13:19:34 +01:00
Ken 8e9135149b 🐛 Datepicker funket ikke i shadow-dom (open)
🐛 Datepicker funket ikke i shadow-dom

📝 Changeset@
2022-11-08 15:06:02 +01:00
KenandKenAJoh 852b53d6b9 Ikonsynk Figma (#1713)
Co-authored-by: KenAJoh <KenAJoh@users.noreply.github.com>
2022-11-08 09:34:22 +01:00
github-actions[bot]andgithub-actions[bot] ede1f5858a Version Packages (#1711)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-04 14:50:55 +01:00
Ken ad9e7165bb 💚 dispatch cdn-publish 2022-11-04 14:46:55 +01:00
Kenandolejorgenbakken 77302a30b8 Ikonsynk Figma (#1709)
Co-authored-by: olejorgenbakken <olejorgenbakken@users.noreply.github.com>
2022-11-04 14:45:15 +01:00
Andreas Nordahl 0ef12ef601 upload font files to cdn (#1710) 2022-11-04 14:29:56 +01:00
Ken 4174f9a7b4 📝 Patch-version 2022-11-02 23:37:19 +01:00
Ken 608f158d70 🐛 Datepicker validation error var flipped 2022-11-02 22:40:36 +01:00
Ken 34d41ecc78 📝 Patch-version 2022-11-02 20:42:21 +01:00
Ken 7e62365a60 🔥 Fjernet flaky e2e test 2022-11-02 19:29:52 +01:00
Ken 8565f410a1 💄 Nye tags i sidebar 2022-11-02 18:16:42 +01:00
Ken 46d70820df 📝 Version-bump 2022-11-02 18:09:27 +01:00
github-actions[bot]andgithub-actions[bot] 67e66ffe02 Version Packages (#1707)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-11-02 16:29:26 +01:00
Ken e19bf67b33 [FEATURE] Tag varianter (#1684) 2022-11-02 16:25:31 +01:00
Ken 97c5f60e91 Chips (#1668) 2022-11-02 16:20:42 +01:00
Ken ea5293c28d ⬆️ Patch-versjon 2022-11-02 10:57:45 +01:00
Ken 6a58efa9a9 changeset 2022-11-02 10:55:34 +01:00
Ken c95f33679e 💚 Fikset timezones for jest-tester
✨ Timekeeper-demo

✨ timezone for jest-tester
2022-11-02 10:53:19 +01:00
Ken b52a5e02a0 ✨ Patch-versjoner 2022-11-01 23:57:38 +01:00
Ken ab3ef0d34b ✨ Validering i Date-komponenter
🐛 Date-formats skaper problemer for ranged-input

🐛 UX tweaks for inputs

🐛 Fikset weekendValidation

🎨 Custom input-format

🎨 validation api

🎉 range-validation

🎨 Export validation-types

🎨 Datepicker-validation

🎨 monthpicker validation

🎨 Småbugs med disabled datepicker

💄 reversert capitalization i månedsnavn
2022-11-01 23:54:27 +01:00
Ken 69798f6ee2 🔥 Fjernet flaky e2e test 2022-11-01 11:00:35 +01:00
Ken ee14586beb ⬆️ yarn-lock 2022-11-01 10:40:34 +01:00
Ken 82470ba669 🐛 Synket dropdown med Figma 2022-11-01 10:18:40 +01:00
github-actions[bot]andgithub-actions[bot] 6286f0e8e6 Version Packages (#1705)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-31 13:34:55 +01:00
Ken 3c08651df2 ✨ Changeset 2022-10-31 13:26:02 +01:00
Ken e6d55fdcd6 changeset 2022-10-31 13:24:57 +01:00
Ken 8c445f020c 💚 Flere workers for e2e testing 2022-10-31 12:07:11 +01:00
Ken 78a76bac5d 🎉 Migrert aksel-website repo (#1704) 2022-10-31 11:44:38 +01:00
Ken 75b334af61 Merge branch 'master' of https://github.com/navikt/Designsystemet 2022-10-28 17:29:58 +02:00
Ken 5d98c50b80 🐛 Fikset eksempel 2022-10-28 17:28:30 +02:00
github-actions[bot]andgithub-actions[bot] 27803fd37c Version Packages (#1703)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-10-28 17:27:39 +02:00
Ken 1bdb7e3777 📝 changeset 2022-10-28 17:23:09 +02:00
Andreas NordahlandKen 20bcc28cb0 provider with modal config (#1702)
Co-authored-by: Ken <ken.aleksander@gmail.com>
2022-10-28 17:14:39 +02:00
577 changed files with 42723 additions and 1972 deletions

No files matched your search

+1 -1
View File
@@ -21,7 +21,7 @@
"access": "public",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"ignore": ["nextjs-demo", "shadow-dom"],
"ignore": ["nextjs-demo", "shadow-dom", "aksel.nav.no"],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"updateInternalDependents": "always"
+71
View File
@@ -0,0 +1,71 @@
name: Deploy aksel.dev.nav.no
on:
workflow_dispatch:
push:
branches:
- next
env:
IMAGE: ghcr.io/navikt/designsystemet
jobs:
build_and_deploy:
name: Build and deploy to dev-gcp
runs-on: ubuntu-20.04
steps:
- uses: actions/setup-node@v1
with:
node-version: "14"
- uses: actions/checkout@v2
with:
ref: "next"
- name: add tokens to .env
run: |
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ADMIN=${{ secrets.ALGOLIA_ADMIN }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ID=${{ secrets.ALGOLIA_ID}}" >> aksel.nav.no/website/.env
echo "TRELLO_TOKEN=${{ secrets.TRELLO_TOKEN }}" >> aksel.nav.no/website/.env
echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PREVIEW_TOKEN=${{ secrets.SANITY_PREVIEW_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PRIVATE_NO_DRAFTS=${{ secrets.SANITY_PRIVATE_NO_DRAFTS }}" >> aksel.nav.no/website/.env
- name: Restore cache
uses: actions/cache@v3
with:
path: "**/node_modules"
key: ${{ runner.os }}-dev-${{ github.sha }}
restore-keys: |
${{ runner.os }}-dev-
- name: Install dependencies
run: yarn
- name: Build application
run: |
yarn boot
yarn docgen
yarn workspace aksel.nav.no build:next
- name: Login to GitHub Container Registry
uses: docker/login-action@ab80d026d4753220c4243394c07c7d80f9638d06 # Use commit-sha1 instead of tag for security concerns
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get complete tag
run: echo "TAG=DEV-$( date +%s )" >> $GITHUB_ENV
- name: Create docker image tags
run: echo "DOCKER_TAG=${{ env.IMAGE }}:${{ env.TAG }}" >> $GITHUB_ENV
- name: Build docker image
run: docker build -t ${{ env.DOCKER_TAG }} . -f aksel.nav.no/Dockerfile
- name: Push docker image
run: |
docker push ${{ env.DOCKER_TAG }}
- name: Deploy to dev-gcp
uses: nais/deploy/actions/deploy@master
env:
APIKEY: ${{ secrets.NAIS_DEPLOY_APIKEY }}
RESOURCE: aksel.nav.no/nais-dev.yaml
CLUSTER: dev-gcp
IMAGE: ${{ env.DOCKER_TAG }}
+81
View File
@@ -0,0 +1,81 @@
name: Deploy aksel.nav.no
on:
push:
branches:
- master
paths:
- "aksel.nav.no/**"
env:
IMAGE: ghcr.io/navikt/designsystemet
jobs:
build_and_deploy:
name: Build and deploy to prod-gcp
runs-on: ubuntu-20.04
steps:
- uses: actions/setup-node@v1
with:
node-version: "14"
- uses: actions/checkout@v2
- name: add tokens to .env
run: |
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ADMIN=${{ secrets.ALGOLIA_ADMIN }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ID=${{ secrets.ALGOLIA_ID}}" >> aksel.nav.no/website/.env
echo "TRELLO_TOKEN=${{ secrets.TRELLO_TOKEN }}" >> aksel.nav.no/website/.env
echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PREVIEW_TOKEN=${{ secrets.SANITY_PREVIEW_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PRIVATE_NO_DRAFTS=${{ secrets.SANITY_PRIVATE_NO_DRAFTS }}" >> aksel.nav.no/website/.env
- name: Restore cache
uses: actions/cache@v3
with:
path: "**/node_modules"
key: ${{ runner.os }}-prod-${{ github.sha }}
restore-keys: |
${{ runner.os }}-prod-
- name: Install dependencies
run: yarn
- name: build packages
run: |
yarn boot
yarn docgen
- name: Tests
run: yarn workspace aksel.nav.no test
- name: E2E
run: NEXT_PUBLIC_TEST=true yarn workspace website e2e
- name: Update sanity sync
run: yarn workspace aksel.nav.no sanity:update
- name: Build application
run: yarn workspace aksel.nav.no build:next
- name: Login to GitHub Container Registry
uses: docker/login-action@ab80d026d4753220c4243394c07c7d80f9638d06 # Use commit-sha1 instead of tag for security concerns
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get complete tag
run: echo "TAG=$( date +%s )" >> $GITHUB_ENV
- name: Create docker image tags
run: echo "DOCKER_TAG=${{ env.IMAGE }}:${{ env.TAG }}" >> $GITHUB_ENV
- name: Build docker image
run: docker build -t ${{ env.DOCKER_TAG }} . -f aksel.nav.no/Dockerfile
- name: Push docker image
run: |
docker push ${{ env.DOCKER_TAG }}
- name: Deploy to prod-gcp
uses: nais/deploy/actions/deploy@master
env:
APIKEY: ${{ secrets.NAIS_DEPLOY_APIKEY }}
RESOURCE: aksel.nav.no/nais-prod.yaml
CLUSTER: prod-gcp
IMAGE: ${{ env.DOCKER_TAG }}
+41
View File
@@ -0,0 +1,41 @@
name: Redeploy image to for aksel.nav.no
on:
workflow_dispatch:
inputs:
tag:
description: "Docker image tag"
required: true
default: ""
dry:
description: "Dry-run"
required: true
default: "false"
env:
IMAGE: ghcr.io/navikt/designsystemet
jobs:
redeploy:
name: Redeploy image
runs-on: ubuntu-20.04
steps:
- uses: actions/setup-node@v1
with:
node-version: "14"
- uses: actions/checkout@v2
- name: Login to GitHub Container Registry
uses: docker/login-action@ab80d026d4753220c4243394c07c7d80f9638d06 # Use commit-sha1 instead of tag for security concerns
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create docker image tag
run: echo "DOCKER_TAG=${{ env.IMAGE }}:${{ github.event.inputs.tag }}" >> $GITHUB_ENV
- name: Deploy to prod-gcp
uses: nais/deploy/actions/deploy@master
env:
APIKEY: ${{ secrets.NAIS_DEPLOY_APIKEY }}
RESOURCE: aksel.nav.no/nais-prod.yaml
CLUSTER: prod-gcp
IMAGE: ${{ env.DOCKER_TAG }}
DRY_RUN: ${{ github.event.inputs.dry }}
+39
View File
@@ -0,0 +1,39 @@
name: Backup sanity dateset to gcp
on:
workflow_dispatch:
schedule:
# 12.00 every 3 days
- cron: "0 0 */3 * *"
jobs:
execute:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0 # Required to retrieve git history
- uses: actions/setup-node@v1
with:
node-version: 14
- name: Restore cache
uses: actions/cache@v3
with:
path: "**/node_modules"
key: ${{ runner.os }}-build-${{ github.sha }}
restore-keys: |
${{ runner.os }}-build-
- name: Install dependencies
run: yarn
- name: Export dataset
run: SANITY_TOKEN=${{secrets.SANITY_DATASET_EDITOR_TOKEN}} yarn workspace aksel.nav.no sanity:backup
- name: Upload GCP bucket
uses: "google-github-actions/auth@v0"
with:
credentials_json: "${{ secrets.gcp_credentials_prod }}"
- uses: "google-github-actions/upload-cloud-storage@v0"
with:
path: ./aksel.nav.no/sanity
destination: "aksel-website-prod/backups"
glob: "**/backup-*.tar.gz"
+1 -2
View File
@@ -4,11 +4,10 @@ on:
push:
branches:
- "master"
- "next"
paths:
- "@navikt/**"
pull_request:
branches: [master]
branches: [master, next]
paths:
- "@navikt/**"
+71
View File
@@ -0,0 +1,71 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [master, next]
pull_request:
# The branches below must be a subset of the branches above
branches: [master]
schedule:
- cron: "41 8 * * 6"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["javascript"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
+56
View File
@@ -0,0 +1,56 @@
name: E2E / Playwright Tests
on:
push:
branches: [master, next]
paths:
- "aksel.nav.no/**"
pull_request:
branches: [master, next]
paths:
- "aksel.nav.no/**"
jobs:
playwright:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: add tokens to .env
run: |
echo "SANITY_WRITE_KEY=${{ secrets.SANITY_FEEDBACK_WRITE_KEY }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ADMIN=${{ secrets.ALGOLIA_ADMIN }}" >> aksel.nav.no/website/.env
echo "ALGOLIA_ID=${{ secrets.ALGOLIA_ID}}" >> aksel.nav.no/website/.env
echo "TRELLO_TOKEN=${{ secrets.TRELLO_TOKEN }}" >> aksel.nav.no/website/.env
echo "SENTRY_AUTH_TOKEN=${{ secrets.SENTRY_AUTH_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PREVIEW_TOKEN=${{ secrets.SANITY_PREVIEW_TOKEN }}" >> aksel.nav.no/website/.env
echo "SANITY_PRIVATE_NO_DRAFTS=${{ secrets.SANITY_PRIVATE_NO_DRAFTS }}" >> aksel.nav.no/website/.env
- name: Restore cache
uses: actions/cache@v3
with:
path: "**/node_modules"
key: ${{ runner.os }}-e2e-${{ github.sha }}
restore-keys: |
${{ runner.os }}-e2e-
- name: Install dependencies
run: yarn
- name: build packages
run: |
yarn boot
yarn docgen
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: yarn workspace website e2e
- uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: aksel.nav.no/website/playwright-report/
retention-days: 10
+31
View File
@@ -0,0 +1,31 @@
name: "push-to-cdn"
on:
workflow_dispatch:
push:
branches:
- "master"
paths:
- "fonts/**"
jobs:
upload:
runs-on: ubuntu-latest
permissions:
contents: "read"
id-token: "write"
steps:
- uses: "actions/checkout@v3"
- id: upload
uses: nais/frontend-plattform-cdn-upload-action@main
with:
cdn-environment: cdn.nav.no
cdn-team-name: aksel
source: ./fonts
destination: "" # uploads folder to team root
- run: echo uploaded file ${{ steps.upload.outputs.uploaded }}
shell: bash
+2 -2
View File
@@ -27,9 +27,9 @@ jobs:
uses: actions/cache@v3
with:
path: "**/node_modules"
key: ${{ runner.os }}-test-${{ github.sha }}
key: ${{ runner.os }}-prod-${{ github.sha }}
restore-keys: |
${{ runner.os }}-test
${{ runner.os }}-prod
- name: Install dependencies
run: yarn
+25
View File
@@ -0,0 +1,25 @@
name: Indexing search
on:
workflow_dispatch:
schedule:
# 01.00 & 12.00 every day
- cron: "00 01,12 * * *"
jobs:
searchcrawl:
name: Search-indexing aksel.nav.no
runs-on: ubuntu-latest
env:
APPLICATION_ID: ${{ secrets.ALGOLIA_ID}}
API_KEY: ${{ secrets.ALGOLIA_ADMIN }}
steps:
- uses: actions/checkout@v2
- name: Read crawler.json
id: algolia_config
run: echo "::set-output name=config::$(cat ./aksel.nav.no/crawler.json | jq -r tostring)"
- name: Push indices to Algolia
uses: signcl/docsearch-scraper-action@master
env:
APPLICATION_ID: ${{ secrets.ALGOLIA_ID}}
API_KEY: ${{ secrets.ALGOLIA_ADMIN }}
CONFIG: ${{ steps.algolia_config.outputs.config }}
+19 -1
View File
@@ -129,4 +129,22 @@ _docs.json
*/icons/src
*/icons/png
*/core/icons
/storybook-static
/storybook-static
# Aksel.nav.no
.next
!*/website/lib/
!*/website/public/
!aksel.nav.no/**/*.d.ts
!*/sanity/lib/
!*/sanity/static/
out
test-urls.json
videos
sanity/scripts/renameField.js
tmp.json
/test-results/
/playwright-report/
/playwright/.cache/
playwright-report/
/test-results/
+2
View File
@@ -0,0 +1,2 @@
**/nais-dev.yaml
**/nais-prod.yaml
+4
View File
@@ -15,3 +15,7 @@
.rowgap[data-theme="dark"] {
background-color: #262626;
}
.rowgap-wrap {
flex-wrap: wrap;
}
+30
View File
@@ -1,5 +1,35 @@
# @navikt/ds-codemod
## 1.5.9
## 1.5.8
## 1.5.7
## 1.5.6
## 1.5.5
## 1.5.4
## 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.4.0
## 1.3.39
### Patch Changes
+5 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-codemod",
"version": "1.3.39",
"version": "1.5.9",
"description": "NAV designsystem codemods",
"author": "NAV Designsystem team",
"license": "MIT",
@@ -36,7 +36,7 @@
"globby": "11.0.1",
"inquirer": "7.3.3",
"is-git-clean": "1.1.0",
"jest": "^27.5.0",
"jest": "^29.0.0",
"jscodeshift": "0.13.1",
"jscodeshift-add-imports": "1.0.10",
"lodash": "4.17.21",
@@ -44,10 +44,12 @@
"prettier": "2.7.1"
},
"devDependencies": {
"@babel/preset-env": "^7.0.0",
"@types/jest": "^29.0.0",
"@types/jscodeshift": "0.11.5",
"@types/react": "^18.0.0",
"del": "7.0.0",
"typescript": "^4.7.2"
"typescript": "^4.8.0"
},
"sideEffects": false,
"engines": {
+64
View File
@@ -1,5 +1,69 @@
# @navikt/ds-css
## 1.5.9
### Patch Changes
- 4px -> 2px gap chips-toggle active
## 1.5.8
## 1.5.7
## 1.5.6
## 1.5.5
## 1.5.4
### Patch Changes
- [#1709](https://github.com/navikt/Designsystemet/pull/1709) [`77302a30b`](https://github.com/navikt/Designsystemet/commit/77302a30b8eef8dc00b2d2e9c904a3f57da81a11) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Oppdatert ikoner
## 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
### Patch Changes
- [`3c08651df`](https://github.com/navikt/Designsystemet/commit/3c08651df28c3e19dd8c8a7a1d0032200bec473d) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Date-komponenter følger språkrådets dato-formatering for måneder.
## 1.4.0
## 1.3.39
### Patch Changes
+137
View File
@@ -0,0 +1,137 @@
.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 {
width: 1.5rem;
height: 1.5rem;
display: grid;
place-items: center;
border-radius: var(--navds-border-radius-full);
}
.navds-chips__toggle-icon {
width: 1.25rem;
height: 1.25rem;
display: grid;
place-items: center;
border-radius: var(--navds-border-radius-full);
}
.navds-chips--small .navds-chips__toggle-icon {
width: 1rem;
height: 1rem;
}
.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: 0.375rem;
}
.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.375rem;
}
+1
View File
@@ -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";
+5 -5
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css",
"version": "1.3.39",
"version": "1.5.9",
"description": "Css for NAV Designsystem components",
"author": "NAV Designsystem team",
"keywords": [
@@ -20,11 +20,11 @@
"watch": "postcss --watch --use postcss-import -o dist/index.css index.css"
},
"devDependencies": {
"@navikt/ds-tokens": "^1.3.39",
"@navikt/ds-tokens": "^1.5.9",
"normalize.css": "^8.0.1",
"postcss": "^8.3.6",
"postcss-cli": "^8.3.1",
"postcss": "^8.4.0",
"postcss-cli": "^9.0.0",
"postcss-combine-duplicated-selectors": "10.0.3",
"postcss-import": "^14.0.2"
"postcss-import": "^14.1.0"
}
}
+93 -14
View File
@@ -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));
}
+131
View File
@@ -1,5 +1,136 @@
# @navikt/ds-react
## 1.5.9
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@1.5.9
## 1.5.8
### Patch Changes
- console.log removed
- Updated dependencies []:
- @navikt/ds-icons@1.5.8
## 1.5.7
### Patch Changes
- defaultMonth/Year prop date-komponent
- Updated dependencies []:
- @navikt/ds-icons@1.5.7
## 1.5.6
### Patch Changes
- Datepicker fungerte ikke med open shadow-dom
- Updated dependencies []:
- @navikt/ds-icons@1.5.6
## 1.5.5
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@1.5.5
## 1.5.4
### Patch Changes
- Updated dependencies [[`77302a30b`](https://github.com/navikt/Designsystemet/commit/77302a30b8eef8dc00b2d2e9c904a3f57da81a11)]:
- @navikt/ds-icons@1.5.4
## 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
- Updated dependencies []:
- @navikt/ds-icons@1.4.2
## 1.4.1
### Patch Changes
- [`3c08651df`](https://github.com/navikt/Designsystemet/commit/3c08651df28c3e19dd8c8a7a1d0032200bec473d) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Date-komponenter følger språkrådets dato-formatering for måneder.
- Updated dependencies []:
- @navikt/ds-icons@1.4.1
## 1.4.0
### Minor Changes
- [`1bdb7e377`](https://github.com/navikt/Designsystemet/commit/1bdb7e3777ece28d153991b78dbdd289366fca57) Thanks [@KenAJoh](https://github.com/KenAJoh)! - [#1702](https://github.com/navikt/Designsystemet/pull/1702) [`20bcc28cb`](https://github.com/navikt/Designsystemet/commit/20bcc28cb0a886aa40d2c1b042fb2706a144c014) Thanks [@andnorda](https://github.com/andnorda)! - Global Provider komponent for håndtering av global config
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@1.4.0
## 1.3.39
### Patch Changes
+12 -10
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react",
"version": "1.3.39",
"version": "1.5.9",
"description": "NAV designsystem react components",
"author": "NAV Designsystem team",
"license": "MIT",
@@ -24,19 +24,20 @@
"/cjs",
"/esm",
"/src",
"_docs.json"
"_docs.json",
"!**/*.tsbuildinfo"
],
"scripts": {
"docgen": "yarn ts-node ../../../scripts/docgen.ts",
"create-package-json-pointers-to-esm": "node ../../../scripts/createPackageJsonsWithESMPointers.js",
"clean": "rimraf cjs esm",
"build": "yarn run clean && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-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.3.39",
"@navikt/ds-icons": "^1.5.9",
"@radix-ui/react-tabs": "1.0.0",
"@radix-ui/react-toggle-group": "1.0.0",
"clsx": "^1.2.1",
@@ -50,21 +51,22 @@
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^14.2.0",
"@types/faker": "5.5.8",
"@types/jest": "^27.0.1",
"@types/jest": "^29.0.0",
"@types/node": "^17.0.35",
"@types/react-modal": "^3.13.1",
"concurrently": "7.2.1",
"copyfiles": "^2.4.1",
"faker": "5.5.3",
"fast-glob": "3.2.11",
"jest": "^27.5.0",
"jest": "^29.0.0",
"jest-environment-jsdom": "^29.0.0",
"react-dom": "^18.0.0",
"react-router-dom": "^6.3.0",
"rimraf": "3.0.2",
"swr": "^1.1.2",
"ts-jest": "^27.1.0",
"ts-node": "10.7.0",
"typescript": "^4.7.2"
"ts-jest": "^29.0.0",
"ts-node": "10.9.0",
"typescript": "^4.8.0"
},
"peerDependencies": {
"@types/react": "^17.0.30 || ^18.0.0",
+45
View File
@@ -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;
+41
View File
@@ -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>
);
};
+1
View File
@@ -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,40 @@ 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>
);
};
export const defaultShownMonth = () => {
const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
fromDate: new Date("Aug 23 2019"),
onDateChange: console.log,
defaultMonth: new Date("Oct 23 2022"),
});
return (
<div style={{ display: "flex", gap: "1rem" }}>
<DatePicker {...datepickerProps}>
<DatePicker.Input {...inputProps} label="Velg dato" />
</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,
@@ -28,6 +28,10 @@ export interface UseDatepickerOptions
* The initially selected Date
*/
defaultSelected?: Date;
/**
* Default shown month
*/
defaultMonth?: Date;
/**
* Make selection of Date required
*/
@@ -36,6 +40,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 +75,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 +109,9 @@ export const useDatepicker = (
disabled,
disableWeekends,
onDateChange,
inputFormat,
onValidate,
defaultMonth,
} = opt;
const locale = getLocaleFromString(_locale);
@@ -85,12 +122,12 @@ export const useDatepicker = (
const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
// Initialize states
const [month, setMonth] = useState(defaultSelected ?? today);
const [month, setMonth] = useState(defaultSelected ?? defaultMonth ?? today);
const [selectedDay, setSelectedDay] = useState(defaultSelected);
const [open, setOpen] = useState(false);
const defaultInputValue = defaultSelected
? formatDateForInput(defaultSelected, locale, "date")
? formatDateForInput(defaultSelected, locale, "date", inputFormat)
: "";
const [inputValue, setInputValue] = useState(defaultInputValue);
@@ -99,16 +136,26 @@ 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) {
/* Workaround for shadow-dom users (open) */
const composed = e.composedPath?.()?.[0];
if (!e?.target || !e?.target?.nodeType || !composed) {
return;
}
![
daypickerRef.current,
inputRef.current,
inputRef.current?.nextSibling,
].some((element) => element?.contains(e.target)) &&
].some(
(element) => element?.contains(e.target) || element?.contains(composed)
) &&
open &&
setOpen(false);
},
@@ -126,30 +173,32 @@ export const useDatepicker = (
const reset = () => {
updateDate(defaultSelected);
setMonth(defaultSelected ?? today);
setMonth(defaultSelected ?? defaultMonth ?? today);
setInputValue(defaultInputValue ?? "");
setDefaultSelected(_defaultSelected);
};
const setSelected = (date: Date | undefined) => {
updateDate(date);
setMonth(date ?? today);
setInputValue(date ? formatDateForInput(date, locale, "date") : "");
setMonth(date ?? defaultMonth ?? today);
setInputValue(
date ? formatDateForInput(date, locale, "date", inputFormat) : ""
);
};
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
!open && setOpen(true);
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 +211,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,23 +229,40 @@ 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);
setMonth(day);
updateValidation();
setMonth(defaultMonth ?? day);
};
const handleClose = useCallback(() => {
@@ -217,13 +287,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,19 @@ export interface UseMonthPickerOptions
* Callback for month-change
*/
onMonthChange?: (date?: Date) => void;
/**
* Input-format
* @default "MMMM yyyy"
*/
inputFormat?: string;
/**
* validation-callback
*/
onValidate?: (val: MonthValidationT) => void;
/**
* Default shown year
*/
defaultYear?: Date;
}
interface UseMonthPickerValue {
@@ -48,6 +61,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 +91,9 @@ export const useMonthpicker = (
disabled,
required,
onMonthChange,
inputFormat,
onValidate,
defaultYear,
} = opt;
const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
@@ -70,12 +105,12 @@ export const useMonthpicker = (
const monthpickerRef = useRef<HTMLDivElement>(null);
// Initialize states
const [year, setYear] = useState(defaultSelected ?? today);
const [year, setYear] = useState(defaultSelected ?? defaultYear ?? today);
const [selectedMonth, setSelectedMonth] = useState(defaultSelected);
const [open, setOpen] = useState(false);
const defaultInputValue = defaultSelected
? formatDateForInput(defaultSelected, locale, "month")
? formatDateForInput(defaultSelected, locale, "month", inputFormat)
: "";
const [inputValue, setInputValue] = useState(defaultInputValue);
@@ -85,16 +120,25 @@ 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) {
/* Workaround for shadow-dom users (open) */
const composed = e.composedPath?.()?.[0];
if (!e?.target || !e?.target?.nodeType || !composed) {
return;
}
![
monthpickerRef.current,
inputRef.current,
inputRef.current?.nextSibling,
].some((element) => element?.contains(e.target)) &&
].some(
(element) => element?.contains(e.target) || element?.contains(composed)
) &&
open &&
setOpen(false);
},
@@ -112,15 +156,17 @@ export const useMonthpicker = (
const reset = () => {
updateMonth(defaultSelected);
setYear(defaultSelected ?? today);
setYear(defaultSelected ?? defaultYear ?? today);
setInputValue(defaultInputValue ?? "");
setDefaultSelected(_defaultSelected);
};
const setSelected = (date: Date | undefined) => {
updateMonth(date);
setYear(date ?? today);
setInputValue(date ? formatDateForInput(date, locale, "month") : "");
setYear(date ?? defaultYear ?? today);
setInputValue(
date ? formatDateForInput(date, locale, "month", inputFormat) : ""
);
};
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
@@ -128,13 +174,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 +193,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 +211,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,9 @@ export const useRangeDatepicker = (
disabled,
disableWeekends,
onRangeChange,
inputFormat,
onValidate,
defaultMonth,
} = opt;
const locale = getLocaleFromString(_locale);
@@ -89,7 +214,7 @@ export const useRangeDatepicker = (
// Initialize states
const [month, setMonth] = useState(
defaultSelected ? defaultSelected?.from : today
defaultSelected ? defaultSelected?.from : defaultMonth ?? today
);
const [selectedRange, setSelectedRange] = useState<DateRange | undefined>(
defaultSelected ?? { from: undefined, to: undefined }
@@ -97,15 +222,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,9 +243,20 @@ 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) {
/* Workaround for shadow-dom users (open) */
const composed = e.composedPath?.()?.[0];
if (!e?.target || !e?.target?.nodeType || !composed) {
return;
}
![
@@ -124,7 +265,9 @@ export const useRangeDatepicker = (
inputRefFrom.current,
inputRefTo.current?.nextSibling,
inputRefFrom.current?.nextSibling,
].some((element) => element?.contains(e.target)) &&
].some(
(element) => element?.contains(e.target) || element?.contains(composed)
) &&
open &&
setOpen(false);
},
@@ -142,15 +285,21 @@ export const useRangeDatepicker = (
const reset = () => {
updateRange(defaultSelected ?? { from: undefined, to: undefined });
setMonth(defaultSelected ? defaultSelected?.from : today);
setMonth(defaultSelected ? defaultSelected?.from : defaultMonth ?? 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 +308,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 +326,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 +339,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 +362,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 +532,8 @@ export const useRangeDatepicker = (
mode: "range" as const,
open,
onOpenToggle: () => setOpen((x) => !x),
disabled,
disableWeekends,
ref: datePickerRef,
};
+3
View File
@@ -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");
};
+2
View File
@@ -1,5 +1,6 @@
export * from "./accordion";
export * from "./alert";
export * from "./provider";
export * from "./button";
export * from "./date";
export * from "./form";
@@ -15,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";
+15 -3
View File
@@ -1,8 +1,8 @@
import React, { forwardRef, useMemo, useRef } from "react";
import React, { forwardRef, useEffect, useMemo, useRef } from "react";
import cl from "clsx";
import ReactModal from "react-modal";
import { Close } from "@navikt/ds-icons";
import { Button, mergeRefs } from "..";
import { Button, mergeRefs, useProvider } from "..";
import ModalContent, { ModalContentType } from "./ModalContent";
export interface ModalProps {
@@ -63,7 +63,7 @@ interface ModalComponent
}
type ModalLifecycle = {
setAppElement?: (element: any) => void;
setAppElement: (element: any) => void;
};
export const Modal = forwardRef<ReactModal, ModalProps>(
@@ -81,6 +81,7 @@ export const Modal = forwardRef<ReactModal, ModalProps>(
"aria-modal": ariaModal,
"aria-label": contentLabel,
style,
parentSelector,
...rest
},
ref
@@ -88,6 +89,12 @@ export const Modal = forwardRef<ReactModal, ModalProps>(
const modalRef = useRef<ReactModal | null>(null);
const mergedRef = useMemo(() => mergeRefs([modalRef, ref]), [ref]);
const buttonRef = useRef<HTMLButtonElement>(null);
const rootElement = useProvider()?.rootElement;
const appElement = useProvider()?.appElement;
useEffect(() => {
appElement && Modal.setAppElement(appElement);
}, [appElement]);
const onModalCloseRequest = (e) => {
if (shouldCloseOnOverlayClick || e.type === "keydown") {
@@ -100,6 +107,11 @@ export const Modal = forwardRef<ReactModal, ModalProps>(
return (
<ReactModal
{...rest}
parentSelector={
parentSelector ?? rootElement !== undefined
? () => rootElement as HTMLElement
: undefined
}
style={style}
isOpen={open}
ref={mergedRef}
@@ -114,7 +114,7 @@ describe("Popover", () => {
expect(fn).toHaveBeenCalledTimes(0);
cleanup();
});
}, 20000);
it("keep open on popover-click", async () => {
const fn = jest.fn();
@@ -0,0 +1,32 @@
import React, { createContext, useContext } from "react";
export interface ProviderContextType {
/**
* Global root-element to attach portals to (Modal, Tooltip)
*/
rootElement?: HTMLElement;
/**
* Global config for appElement (Modal)
*/
appElement?: HTMLElement;
}
export const ProviderContext = createContext<ProviderContextType | undefined>(
undefined
);
export interface ProviderProps {
children?: React.ReactNode;
rootElement?: HTMLElement;
appElement?: HTMLElement;
}
export const useProvider = () => useContext(ProviderContext);
export const Provider = ({ children, ...rest }: ProviderProps) => {
return (
<ProviderContext.Provider value={rest}>{children}</ProviderContext.Provider>
);
};
export default Provider;
+1
View File
@@ -0,0 +1 @@
export { default as Provider, useProvider } from "./Provider";
+20 -8
View File
@@ -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,
+82 -5
View File
@@ -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>
+3 -2
View File
@@ -21,7 +21,7 @@ import React, {
useRef,
useState,
} from "react";
import { Detail } from "..";
import { Detail, useProvider } from "..";
import { mergeRefs, useId } from "../util";
export interface TooltipProps extends HTMLAttributes<HTMLDivElement> {
@@ -96,6 +96,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
) => {
const [open, setOpen] = useState(defaultOpen);
const arrowRef = useRef<HTMLDivElement | null>(null);
const rootElement = useProvider()?.rootElement;
const {
x,
@@ -170,7 +171,7 @@ export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
: children?.props["aria-describedby"],
})
)}
<FloatingPortal>
<FloatingPortal root={rootElement}>
{(userOpen ?? open) && (
<div
{...getFloatingProps({
+30
View File
@@ -1,5 +1,35 @@
# @navikt/ds-tailwind
## 1.5.9
## 1.5.8
## 1.5.7
## 1.5.6
## 1.5.5
## 1.5.4
## 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.4.0
## 1.3.39
### Patch Changes
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tailwind",
"version": "1.3.39",
"version": "1.5.9",
"description": "Auto-generated tailwind config based on @navikt/ds-tokens",
"author": "NAV Designsystem team",
"keywords": [
@@ -22,13 +22,13 @@
"directory": "@navikt/core/tailwind"
},
"devDependencies": {
"@navikt/ds-tokens": "^1.3.39",
"@types/jest": "^27.0.1",
"@navikt/ds-tokens": "^1.5.9",
"@types/jest": "^29.0.0",
"@types/node": "^17.0.35",
"jest": "^27.2.0",
"jest": "^29.0.0",
"lodash": "^4.17.21",
"ts-jest": "^27.0.5",
"ts-node": "^10.3.0",
"typescript": "^4.7.2"
"ts-jest": "^29.0.0",
"ts-node": "10.9.0",
"typescript": "^4.8.0"
}
}
+30
View File
@@ -1,5 +1,35 @@
# @navikt/ds-tokens
## 1.5.9
## 1.5.8
## 1.5.7
## 1.5.6
## 1.5.5
## 1.5.4
## 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.4.0
## 1.3.39
### Patch Changes
+6 -6
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-tokens",
"version": "1.3.39",
"version": "1.5.9",
"description": "Auto-generated design-tokens for NAV design-systems framework",
"author": "NAV Designsystem team",
"keywords": [
@@ -29,18 +29,18 @@
"directory": "@navikt/core/tokens"
},
"devDependencies": {
"@types/jest": "^27.0.1",
"@types/jest": "^29.0.0",
"@types/node": "^17.0.35",
"axios": "^0.21.3",
"color": "4.2.3",
"dotenv": "^10.0.0",
"figma-api": "^1.7.0",
"jest": "^27.2.0",
"jest": "^29.0.0",
"lodash": "^4.17.21",
"nodemon": "^2.0.12",
"style-dictionary": "^3.0.2",
"ts-jest": "^27.0.5",
"ts-node": "^10.3.0",
"typescript": "^4.7.2"
"ts-jest": "^29.0.0",
"ts-node": "10.9.0",
"typescript": "^4.8.0"
}
}
+38
View File
@@ -1,5 +1,43 @@
# @navikt/ds-icons
## 1.5.9
## 1.5.8
## 1.5.7
## 1.5.6
## 1.5.5
### Patch Changes
- Error-ikon hadde avrundede kanter
## 1.5.4
### Patch Changes
- [#1709](https://github.com/navikt/Designsystemet/pull/1709) [`77302a30b`](https://github.com/navikt/Designsystemet/commit/77302a30b8eef8dc00b2d2e9c904a3f57da81a11) Thanks [@KenAJoh](https://github.com/KenAJoh)! - Oppdatert ikoner
## 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.4.0
## 1.3.39
### Patch Changes
+126
View File
@@ -311,6 +311,102 @@
"created_at": "2021-04-28T14:11:08.212Z",
"pageName": "People"
},
{
"name": "ChevronDownCircle",
"description": "",
"created_at": "2022-11-02T08:31:54.965Z",
"pageName": "Arrows"
},
{
"name": "ChevronDownCircleFilled",
"description": "",
"created_at": "2022-11-02T08:31:55.048Z",
"pageName": "Arrows"
},
{
"name": "ChevronDownDouble",
"description": "",
"created_at": "2022-11-02T08:31:54.957Z",
"pageName": "Arrows"
},
{
"name": "ChevronDownDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.949Z",
"pageName": "Arrows"
},
{
"name": "ChevronLeftCircle",
"description": "",
"created_at": "2022-11-02T08:31:54.938Z",
"pageName": "Arrows"
},
{
"name": "ChevronLeftCircleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.930Z",
"pageName": "Arrows"
},
{
"name": "ChevronLeftDouble",
"description": "",
"created_at": "2022-11-02T08:31:55.040Z",
"pageName": "Arrows"
},
{
"name": "ChevronLeftDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.922Z",
"pageName": "Arrows"
},
{
"name": "ChevronRightCircle",
"description": "",
"created_at": "2022-11-02T08:31:54.993Z",
"pageName": "Arrows"
},
{
"name": "ChevronRightCircleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.985Z",
"pageName": "Arrows"
},
{
"name": "ChevronRightDouble",
"description": "",
"created_at": "2022-11-02T08:31:55.003Z",
"pageName": "Arrows"
},
{
"name": "ChevronRightDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:55.013Z",
"pageName": "Arrows"
},
{
"name": "ChevronUpCircle",
"description": "",
"created_at": "2022-11-02T08:31:54.906Z",
"pageName": "Arrows"
},
{
"name": "ChevronUpCircleFilled",
"description": "",
"created_at": "2022-11-02T08:31:55.021Z",
"pageName": "Arrows"
},
{
"name": "ChevronUpDouble",
"description": "",
"created_at": "2022-11-02T08:31:55.031Z",
"pageName": "Arrows"
},
{
"name": "ChevronUpDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.914Z",
"pageName": "Arrows"
},
{
"name": "Child",
"description": "",
@@ -761,6 +857,12 @@
"created_at": "2021-01-11T13:37:55.499Z",
"pageName": "Status"
},
{
"name": "ErrorStroke",
"description": "",
"created_at": "2022-10-27T14:42:57.018Z",
"pageName": "Status"
},
{
"name": "Eu",
"description": "",
@@ -1355,6 +1457,12 @@
"created_at": "2021-01-11T13:37:55.736Z",
"pageName": "Status"
},
{
"name": "InformationStroke",
"description": "",
"created_at": "2022-10-27T14:42:57.034Z",
"pageName": "Status"
},
{
"name": "Laptop",
"description": "",
@@ -1613,6 +1721,18 @@
"created_at": "2020-07-01T10:37:42.664Z",
"pageName": "Arrows"
},
{
"name": "NextDouble",
"description": "",
"created_at": "2022-11-02T08:31:54.896Z",
"pageName": "Arrows"
},
{
"name": "NextDoubleFilled",
"description": "",
"created_at": "2022-11-02T08:31:54.975Z",
"pageName": "Arrows"
},
{
"name": "NextFilled",
"description": "",
@@ -2651,6 +2771,12 @@
"created_at": "2021-01-11T13:37:55.590Z",
"pageName": "Status"
},
{
"name": "WarningStroke",
"description": "",
"created_at": "2022-10-27T14:42:57.027Z",
"pageName": "Status"
},
{
"name": "Washing",
"description": "",
+10 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-icons",
"version": "1.3.39",
"version": "1.5.9",
"description": "Aksel icons",
"repository": {
"type": "git",
@@ -25,13 +25,14 @@
"/esm",
"/src",
"/svg",
"/meta.json"
"/meta.json",
"!**/*.tsbuildinfo"
],
"scripts": {
"create-package-json-pointers-to-esm": "node ../../scripts/createPackageJsonsWithESMPointers.js",
"create-icons": "svgr --out-dir src svg",
"create-icons": "svgr --silent --out-dir src svg",
"clean": "rimraf src cjs esm",
"build": "yarn clean && copyfiles util/* src && yarn create-icons && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
"build": "copyfiles util/* src && yarn create-icons && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
"update": "ts-node figma/index.ts dotenv/config",
"test": "jest"
},
@@ -46,7 +47,7 @@
},
"devDependencies": {
"@svgr/cli": "6.2.1",
"@types/jest": "^27.0.1",
"@types/jest": "^29.0.0",
"@types/lodash.startcase": "^4.4.6",
"@types/node": "^17.0.35",
"@types/rimraf": "3.0.2",
@@ -54,13 +55,13 @@
"concurrently": "7.2.1",
"copyfiles": "^2.4.1",
"dotenv": "^10.0.0",
"jest": "^27.5.0",
"jest": "^29.0.0",
"lodash.kebabcase": "^4.1.1",
"lodash.startcase": "4.4.0",
"react": "^18.0.0",
"rimraf": "3.0.2",
"ts-jest": "^27.1.0",
"ts-node": "^10.4.0",
"typescript": "^4.7.2"
"ts-jest": "^29.0.0",
"ts-node": "10.9.0",
"typescript": "^4.8.0"
}
}
+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12ZM12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 15.5607L7.46967 11.0303L8.53033 9.96967L12 13.4393L15.4697 9.96967L16.5303 11.0303L12 15.5607Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 640 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25ZM12 15.5607L16.5303 11.0303L15.4697 9.96967L12 13.4393L8.53033 9.96967L7.46967 11.0303L12 15.5607Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 420 B

+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12ZM12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25Z" fill="#262626"/>
<path d="M12 13.5607L16.5303 9.03033L15.4697 7.96967L12 11.4393L8.53033 7.96967L7.46967 9.03033L12 13.5607Z" fill="#262626"/>
<path d="M12 17.0607L16.5303 12.5303L15.4697 11.4697L12 14.9393L8.53033 11.4697L7.46967 12.5303L12 17.0607Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 726 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12ZM11.9984 13.4579L6.94365 8.40316L8.27389 7.07292L11.9984 10.7974L15.7228 7.07292L17.0531 8.40316L11.9984 13.4579ZM6.94365 13.241L11.9984 18.2957L17.0531 13.241L15.7228 11.9108L11.9984 15.6352L8.27389 11.9108L6.94365 13.241Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 546 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25ZM22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.43934 12L12.9697 7.46967L14.0303 8.53033L10.5607 12L14.0303 15.4697L12.9697 16.5303L8.43934 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 641 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12ZM8.43934 12L12.9697 16.5303L14.0303 15.4697L10.5607 12L14.0303 8.53033L12.9697 7.46967L8.43934 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 421 B

+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25ZM22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12Z" fill="#262626"/>
<path d="M10.4393 12L14.9697 16.5303L16.0303 15.4697L12.5607 12L16.0303 8.53033L14.9697 7.46967L10.4393 12Z" fill="#262626"/>
<path d="M6.93934 12L11.4697 16.5303L12.5303 15.4697L9.06066 12L12.5303 8.53033L11.4697 7.46967L6.93934 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 727 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75ZM10.5421 11.9984L15.5968 6.94365L16.9271 8.27389L13.2026 11.9984L16.9271 15.7228L15.5968 17.0531L10.5421 11.9984ZM10.759 6.94365L5.70428 11.9984L10.759 17.0531L12.0892 15.7228L8.36477 11.9984L12.0892 8.27389L10.759 6.94365Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 546 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75ZM1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.5607 12L11.0303 16.5303L9.96967 15.4697L13.4393 12L9.96967 8.53033L11.0303 7.46967L15.5607 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 639 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12ZM15.5607 12L11.0303 7.46967L9.96967 8.53033L13.4393 12L9.96967 15.4697L11.0303 16.5303L15.5607 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 420 B

+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75ZM1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12Z" fill="#262626"/>
<path d="M13.5607 12L9.03033 7.46967L7.96967 8.53033L11.4393 12L7.96967 15.4697L9.03033 16.5303L13.5607 12Z" fill="#262626"/>
<path d="M17.0607 12L12.5303 7.46967L11.4697 8.53033L14.9393 12L11.4697 15.4697L12.5303 16.5303L17.0607 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 725 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25ZM13.4579 12.0016L8.40316 17.0564L7.07292 15.7261L10.7974 12.0016L7.07292 8.27718L8.40316 6.94694L13.4579 12.0016ZM13.241 17.0564L18.2957 12.0016L13.241 6.94694L11.9108 8.27718L15.6352 12.0016L11.9108 15.7261L13.241 17.0564Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 545 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12ZM12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 8.43934L16.5303 12.9697L15.4697 14.0303L12 10.5607L8.53033 14.0303L7.46967 12.9697L12 8.43934Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 640 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75ZM12 8.43934L7.46967 12.9697L8.53033 14.0303L12 10.5607L15.4697 14.0303L16.5303 12.9697L12 8.43934Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 421 B

+5
View File
@@ -0,0 +1,5 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75C6.89137 2.75 2.75 6.89137 2.75 12ZM12 22.75C6.06294 22.75 1.25 17.9371 1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75Z" fill="#262626"/>
<path d="M12 10.4393L7.46967 14.9697L8.53033 16.0303L12 12.5607L15.4697 16.0303L16.5303 14.9697L12 10.4393Z" fill="#262626"/>
<path d="M12 6.93934L7.46967 11.4697L8.53033 12.5303L12 9.06066L15.4697 12.5303L16.5303 11.4697L12 6.93934Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 726 B

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12ZM12.0016 10.5421L17.0564 15.5968L15.7261 16.9271L12.0016 13.2026L8.27718 16.9271L6.94694 15.5968L12.0016 10.5421ZM17.0564 10.759L12.0016 5.70428L6.94694 10.759L8.27718 12.0892L12.0016 8.36477L15.7261 12.0892L17.0564 10.759Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 545 B

+1 -1
View File
@@ -1,4 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.999 0C5.39479 0 0.0125453 5.37181 2.35603e-05 11.976C-0.00623729 15.1815 1.2355 18.1972 3.49775 20.4688C5.76001 22.7394 8.77148 23.9937 11.977 23.9999H12C18.6031 23.9999 23.9864 18.6271 24 12.0219C24.0125 5.40625 18.6396 0.0125217 11.999 0Z" fill="#BA3A26"/>
<path d="M12 10.6512L15.3719 7.27932C15.7443 6.90687 16.3482 6.90687 16.7206 7.27932C17.0931 7.65177 17.0931 8.25563 16.7206 8.62808L13.3487 12L16.7206 15.3719C17.0931 15.7443 17.0931 16.3482 16.7206 16.7206C16.3482 17.0931 15.7443 17.0931 15.3719 16.7206L12 13.3487L8.62808 16.7206C8.25563 17.0931 7.65177 17.0931 7.27932 16.7206C6.90687 16.3482 6.90687 15.7443 7.27932 15.3719L10.6512 12L7.27932 8.62808C6.90687 8.25563 6.90687 7.65177 7.27932 7.27932C7.65177 6.90687 8.25563 6.90687 8.62808 7.27932L12 10.6512Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.5714 6.99998L17 8.42855L13.428 12L17 15.5714L15.5714 17L12 13.428L8.42855 17L6.99998 15.5714L10.572 12L6.99998 8.42855L8.42855 6.99998L12 10.572L15.5714 6.99998Z" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 606 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17 5L19 7L13.9992 12L19 17L17 19L12 13.9992L7 19L5 17L10.0008 12L5 7L7 5L12 10.0008L17 5Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 261 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.57141 20V17.7143H10.8571V12H8.57141V9.71429H13.1428V17.7143H15.4286V20H8.57141ZM12 4C12.9467 4 13.7142 4.76751 13.7142 5.71429C13.7142 6.66106 12.9467 7.42857 12 7.42857C11.0532 7.42857 10.2857 6.66106 10.2857 5.71429C10.2857 4.76751 11.0532 4 12 4Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 423 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.1213 12L6.41421 19.7071L5 18.2929L11.2929 12L5 5.70711L6.41421 4.29289L14.1213 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.62 12L11.9129 19.7071L10.4987 18.2929L16.7916 12L10.4987 5.70711L11.9129 4.29289L19.62 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 419 B

+4
View File
@@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M14.182 12L6.12132 20.0607L4 17.9393L9.93934 12L4 6.06067L6.12132 3.93935L14.182 12Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M21.2426 12L13.182 20.0607L11.0607 17.9393L17 12L11.0607 6.06067L13.182 3.93935L21.2426 12Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 414 B

+1 -1
View File
@@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.0465 7.67114L18.4456 9.10034L9.71768 17.4992L6 14.0182L7.39516 12.5852L9.71359 14.7034L17.0465 7.67114Z" fill="#262626"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2014 6L20 7.89047L8.77943 19L4 14.3955L5.79361 12.5L8.77418 15.3019L18.2014 6Z" fill="#262626"/>
</svg>

Before

Width:  |  Height:  |  Size: 278 B

After

Width:  |  Height:  |  Size: 253 B

+3
View File
@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.6667 4V13.3333H13.3333V4H10.6667ZM12 20C13.1046 20 14 19.1046 14 18C14 16.8954 13.1046 16 12 16C10.8954 16 10 16.8954 10 18C10 19.1046 10.8954 20 12 20Z" fill="#262626"/>
</svg>

After

Width:  |  Height:  |  Size: 327 B

+2 -1
View File
@@ -4,5 +4,6 @@
"outDir": "./cjs",
"module": "commonjs"
},
"exclude": ["./figma", "./util", "./tests", "./scripts", "**/*.stories.*"]
"exclude": ["./figma", "./util", "./tests", "./scripts", "**/*.stories.*"],
"include": ["./src"]
}
+34
View File
@@ -1,5 +1,39 @@
# @navikt/ds-css-internal
## 1.5.9
## 1.5.8
## 1.5.7
## 1.5.6
## 1.5.5
## 1.5.4
## 1.5.3
## 1.5.2
## 1.5.1
## 1.5.0
## 1.4.4
## 1.4.3
## 1.4.2
### Patch Changes
- :bug: Dropdown-link ikke i synk med Figma
## 1.4.1
## 1.4.0
## 1.3.39
### Patch Changes
+3 -2
View File
@@ -3,7 +3,7 @@
--navds-dropdown-menu-color: var(--navds-semantic-color-text);
--navdsi-dropdown-item-color-text: var(--navds-semantic-color-link);
--navdsi-dropdown-item-color-background-hover: var(--navds-semantic-color-interaction-primary-hover-subtle);
--navdsi-dropdown-item-color-background-active: var(--navds-global-color-blue-200);
--navdsi-dropdown-item-color-background-active: var(--navds-global-color-deepblue-500);
--navds-dropdown-item-color-focus: var(--navds-semantic-color-focus);
}
@@ -64,9 +64,10 @@
.navdsi-dropdown__item:active {
background-color: var(--navdsi-dropdown-item-color-background-active);
color: var(--navds-global-color-white);
}
.navdsi-dropdown__item:focus {
.navdsi-dropdown__item:focus-visible {
outline: none;
box-shadow: inset 0 0 0 2px var(--navds-dropdown-item-color-focus);
}
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-css-internal",
"version": "1.3.39",
"version": "1.5.9",
"description": "Css for NAV internal Designsystem components",
"author": "NAV Designsystem team",
"keywords": [
@@ -20,9 +20,9 @@
"watch": "yarn build --watch"
},
"devDependencies": {
"postcss": "^8.3.8",
"postcss": "^8.4.0",
"postcss-cli": "^9.0.0",
"postcss-combine-duplicated-selectors": "10.0.3",
"postcss-import": "^14.0.2"
"postcss-import": "^14.1.0"
}
}
+120
View File
@@ -1,5 +1,125 @@
# @navikt/ds-react-internal
## 1.5.9
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.5.9
- @navikt/ds-icons@1.5.9
## 1.5.8
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.5.8
- @navikt/ds-icons@1.5.8
## 1.5.7
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.5.7
- @navikt/ds-icons@1.5.7
## 1.5.6
### Patch Changes
- Updated dependencies []:
- @navikt/ds-react@1.5.6
- @navikt/ds-icons@1.5.6
## 1.5.5
### Patch Changes
- Updated dependencies []:
- @navikt/ds-icons@1.5.5
- @navikt/ds-react@1.5.5
## 1.5.4
### Patch Changes
- Updated dependencies [[`77302a30b`](https://github.com/navikt/Designsystemet/commit/77302a30b8eef8dc00b2d2e9c904a3f57da81a11)]:
- @navikt/ds-icons@1.5.4
- @navikt/ds-react@1.5.4
## 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
- Updated dependencies []:
- @navikt/ds-react@1.4.2
- @navikt/ds-icons@1.4.2
## 1.4.1
### Patch Changes
- Updated dependencies [[`3c08651df`](https://github.com/navikt/Designsystemet/commit/3c08651df28c3e19dd8c8a7a1d0032200bec473d)]:
- @navikt/ds-react@1.4.1
- @navikt/ds-icons@1.4.1
## 1.4.0
### Patch Changes
- Updated dependencies [[`1bdb7e377`](https://github.com/navikt/Designsystemet/commit/1bdb7e3777ece28d153991b78dbdd289366fca57)]:
- @navikt/ds-react@1.4.0
- @navikt/ds-icons@1.4.0
## 1.3.39
### Patch Changes
+8 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@navikt/ds-react-internal",
"version": "1.3.39",
"version": "1.5.9",
"description": "NAV internal designsystem react components",
"author": "NAV Designsystem team",
"license": "MIT",
@@ -24,18 +24,19 @@
"/cjs",
"/esm",
"/src",
"_docs.json"
"_docs.json",
"!**/*.tsbuildinfo"
],
"scripts": {
"docgen": "yarn ts-node ../../../scripts/docgen.ts",
"create-package-json-pointers-to-esm": "node ../../../scripts/createPackageJsonsWithESMPointers.js",
"clean": "rimraf cjs esm",
"build": "yarn run clean && concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
"build": "concurrently \"tsc\" \"tsc -p tsconfig.esm.json\" && yarn create-package-json-pointers-to-esm",
"watch": "tsc --watch -p tsconfig.esm.json"
},
"dependencies": {
"@navikt/ds-icons": "^1.3.39",
"@navikt/ds-react": "^1.3.39",
"@navikt/ds-icons": "^1.5.9",
"@navikt/ds-react": "^1.5.9",
"clsx": "^1.1.1",
"copy-to-clipboard": "^3.3.1"
},
@@ -43,8 +44,8 @@
"@types/node": "^17.0.35",
"concurrently": "7.2.1",
"rimraf": "^3.0.2",
"ts-node": "10.7.0",
"typescript": "^4.7.2"
"ts-node": "10.9.0",
"typescript": "^4.8.0"
},
"peerDependencies": {
"@types/react": "^17.0.30 || ^18.0.0",
+2 -1
View File
@@ -3,5 +3,6 @@
"compilerOptions": {
"outDir": "./cjs",
"module": "commonjs"
}
},
"include": ["./src"]
}
+2 -8
View File
@@ -1,16 +1,10 @@
Font License
The Source Sans Pro font files in packages/node_modules/nav-frontend-typografi-style/assets are a subset of Source Sans Pro, licensed under the SIL Open Font License, and copyright Adobe Systems Incorporated, with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
Icon License
This project uses Streamline Icons. If you use nav-frontend-moduler in your project please adhere to the Streamline Icons license agreement found here: https://streamlineicons.com/ux/extended-license.html
The rest of the codebase (excluding 3rd party dependencies):
SIL Open Font License (OFL)
# The MIT License
Copyright 2019 NAV (Arbeids- og velferdsdirektoratet) - The Norwegian Labour and Welfare Administration
Copyright 2022 NAV (Arbeids- og velferdsdirektoratet) - The Norwegian Labour and Welfare Administration
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the "Software"),
+4 -6
View File
@@ -36,6 +36,10 @@
├── internal/css # @navikt/ds-css-internal, css interne flater
├── icons # @navikt/ds-icons, ikonpakke
└── codemod # @navikt/ds-codemod, migrerings-scripts
aksel.nav.no/
├── /website # NEXT.JS app (v12)
└── /sanity # Sanity CMS-app (v2)
```
## Commands
@@ -54,12 +58,6 @@ yarn && yarn boot
| `yarn clean` | Fjerner genererte filer |
| `yarn docgen` | Generer ts-docs |
## Dokumentasjon
[Dokumentasjon forvaltes i navikt/aksel-website](https://github.com/navikt/aksel-website)
[Migreringer](https://aksel.nav.no/designsystem/side/migrering#beta-til-v1)
## Bidra
Vi tar gjerne i mot PR-er [CONTRIBUTING.md](https://github.com/navikt/Designsystemet/blob/master/CONTRIBUTING.md)
+17
View File
@@ -0,0 +1,17 @@
FROM node:16.4-alpine3.14
RUN apk add --no-cache libc6-compat
ENV NODE_ENV production
WORKDIR /app
COPY aksel.nav.no/website/package.json .
COPY aksel.nav.no/website/.next/ .next/
COPY aksel.nav.no/website/public/ public
COPY aksel.nav.no/website/.env .
COPY aksel.nav.no/website/redirects.json .
COPY aksel.nav.no/website/next.config.js .
COPY node_modules/ node_modules/
COPY @navikt/ @navikt/
EXPOSE 3000
CMD yarn start
+92
View File
@@ -0,0 +1,92 @@
CMS og nettside for [aksel.nav.no](https://aksel.nav.no/)
```sh
├── /website # NEXT.JS app (v12)
└── /sanity # Sanity CMS-app (v2)
```
### /website
[Nextjs](https://nextjs.org/) applikasjon som henter data fra et [sanity-datasett](https://www.sanity.io/).
Siden leverer to løsninger:
- Innhold på toppnivå i Aksel: artikler, prinsipper og blogger
- Designsystem-dokumentasjon under https://aksel.nav.no/designsystem
### /sanity
Det publiserte studioet finner man på [aksel.nav.no/studio](https://aksel.nav.no/studio)(krever NAV SSO eller invite).
`production`-datasettet er privat, så man må ha riktige tilganger for å kunne lese/jobbe med dataen der.
## Kom i gang
### Bidrag
Branch `master` blir pusher rett til prod -> aksel.nav.no. For å utvikle nye features brukes branch `next` som ved push publiseres til devmiljø aksel.dev.nav.no (krever naisdevice).
### Nettside (localhost:3000)
```
yarn install
yarn workspace aksel.nav.no dev
```
**Rettigheter**
Sanity-datasettet er privat, noe som betyr du må ha tilgang til sanity applikasjonen + følgende token for å få data lokalt:
```
SANITY_PREVIEW_TOKEN
SANITY_PRIVATE_NO_DRAFTS
```
### Sanity (localhost:3333)
> !! Må være developer i https://verktoykasse.sanity.studio, Ta kontakt med team Aksel om du trenger tilgang !!
Husk at alle endringer i datasettet lokalt også gjøres i prod. Bytt derfor til `development`-dataset hvis man vil teste destruktive handlinger. Dette kan endres i `/sanity/schema.json`
```
yarn install
yarn workspace aksel.nav.no sanity
```
**Deploy av ny sanity-oppdatering**
```
yarn workspace aksel.nav.no sanity:deploy
```
### .env
Blir brukt flere keys i .env under `./website`, men kun `SANITY_PRIVATE_NO_DRAFTS` trengs for å teste lokalt
- SANITY_WRITE_KEY:
For å sende dokumenter til sanity, brukt til å oppdatere sandboxes/examples/farger. Trengs bare hvis kode skal synkes fra lokal branch
- ALGOLIA_ADMIN:
For å oppdatere records i søkemotoren. Trengs bare hvis man oppdaterer søkeindexen lokalt.
- ALGOLIA_ID:
Søkemotor index-id for å redigere riktig Index. Trengs bare for at søk skal fungere lokalt
- TRELLO_TOKEN: Sender feedback til et egent trello-board. Ikke nødvendig lokalt hvis man ikke vil teste feedback-modulen.
- SANITY_PREVIEW_TOKEN: Gir appen tilgang til å lese draft innhold fra sanity i "preview"-mode. Trengs for å teste preview-sider
- SANITY_PRIVATE_NO_DRAFTS: Gir appen tilgang til å lese innhold fra Sanity da datasettet er privat
### Søk
Søk-index blir generert av [algolia-scraper](https://github.com/algolia/docsearch-scraper). Kjøres daglig i en github-action, men kan kjøres lokalt også med docker.
```
docker run -it --env-file=.env -e "CONFIG=$(cat crawler.json | jq -r tostring)" algolia/docsearch-scraper
```
## Backups
Kjøres backups hver 3 dag til GCP-bucket under `designsystem-prod`
## Henvendelser
Spørsmål og kontakt kan rettes til team Aksel
Aksel har også en egen slack-kanal #aksel
+48
View File
@@ -0,0 +1,48 @@
{
"index_name": "aksel_docsearch",
"start_urls": [
"https://aksel.nav.no/",
{
"url": "https://aksel.nav.no/designsystem",
"tags": ["designsystem", "docs"]
},
{
"url": "https://aksel.nav.no/artikkel/",
"tags": ["aksel"],
"selectors_key": "aksel"
},
{
"url": "https://aksel.nav.no/blogg/",
"tags": ["aksel"],
"selectors_key": "aksel"
}
],
"selectors": {
"default": {
"lvl0": {
"selector": "h1.algolia-index-lvl1",
"global": true
},
"lvl1": ".algolia-index-tabs--active",
"lvl2": "h2.algolia-index-lvl2",
"lvl3": "h3.algolia-index-lvl3",
"text": "p.algolia-index-body, p.algolia-index-ingress"
},
"aksel": {
"lvl0": {
"selector": "h1.algolia-index-lvl1",
"global": true
},
"lvl1": "h2.algolia-index-lvl2",
"lvl2": "h3.algolia-index-lvl3",
"text": "p.algolia-index-body, p.algolia-index-ingress"
}
},
"selectors_exclude": [".algolia-ignore-index"],
"stop_urls": [
"https://aksel.nav.no/preview",
"https://old-design-nav.vercel.app"
],
"sitemap_urls": ["https://aksel.nav.no/api/sitemap"],
"js_render": true
}
+6
View File
@@ -0,0 +1,6 @@
AZURE_APP_CLIENT_ID=notfound
AZURE_OPENID_CONFIG_TOKEN_ENDPOINT=https://fakedings.dev-gcp.nais.io/fake/aad?NAVIdent=A123456&aud=testbruker-aksel" >> website/.env
AZURE_APP_CLIENT_SECRET=secret
AZURE_OPENID_CONFIG_ISSUER=https://fakedings.dev-gcp.nais.io/fake
AZURE_OPENID_CONFIG_JWKS_URI=https://fakedings.dev-gcp.nais.io/fake/jwks
AZURE_APP_JWK=https://fakedings.dev-gcp.nais.io/fake/jwk
+49
View File
@@ -0,0 +1,49 @@
apiVersion: "nais.io/v1alpha1"
kind: "Application"
metadata:
name: verktoykasse
namespace: designsystem
labels:
team: designsystem
spec:
image: {{ image }}
port: 3000
ingresses:
- "https://aksel.dev.nav.no"
liveness:
path: /api/isAlive
initialDelay: 20
timeout: 1
periodSeconds: 5
failureThreshold: 10
readiness:
path: /api/isAlive
initialDelay: 20
timeout: 1
replicas:
min: 1
max: 1
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
accessPolicy:
outbound:
external:
- host: api.sanity.io
- host: hnbe3yhs.api.sanity.io
- host: apicdn.sanity.io
- host: hnbe3yhs.apicdn.sanity.io
- host: cdn.sanity.io
rules: []
env:
azure:
application:
enabled: true
allowAllUsers: true
tenant: nav.no
sidecar:
enabled: true
+55
View File
@@ -0,0 +1,55 @@
apiVersion: "nais.io/v1alpha1"
kind: "Application"
metadata:
name: verktoykasse
namespace: designsystem
labels:
team: designsystem
spec:
image: {{ image }}
port: 3000
ingresses:
- "https://aksel.nav.no"
- "https://design.nav.no"
liveness:
path: /api/isAlive
initialDelay: 20
timeout: 1
periodSeconds: 5
failureThreshold: 10
readiness:
path: /api/isAlive
initialDelay: 20
timeout: 1
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
accessPolicy:
outbound:
external:
- host: api.sanity.io
- host: hnbe3yhs.api.sanity.io
- host: apicdn.sanity.io
- host: hnbe3yhs.apicdn.sanity.io
- host: cdn.sanity.io
rules: []
env:
azure:
application:
enabled: true
allowAllUsers: true
tenant: nav.no
sidecar:
enabled: true
gcp:
buckets:
- name: aksel-website-prod
retentionPeriodDays: 30
lifecycleCondition:
age: 7
numNewerVersions: 3
withState: ANY
+33
View File
@@ -0,0 +1,33 @@
{
"name": "aksel.nav.no",
"version": "1.0.0",
"private": true,
"description": "Nettside for Aksel",
"scripts": {
"dev": "yarn workspace website dev",
"build:next": "yarn workspace website build",
"serve:next": "yarn workspace website start",
"sanity": "yarn workspace sanity start",
"sanity:deploy": "yarn workspace sanity deploy",
"sanity:backup": "yarn workspace sanity backup",
"sanity:update": "yarn workspace website update:sanity",
"test": "yarn workspace website test"
},
"workspaces": [
"sanity",
"website"
],
"dependencies": {
"@navikt/ds-codemod": "^1.5.9",
"@navikt/ds-css": "^1.5.9",
"@navikt/ds-css-internal": "^1.5.9",
"@navikt/ds-icons": "^1.5.9",
"@navikt/ds-react": "^1.5.9",
"@navikt/ds-react-internal": "^1.5.9",
"@navikt/ds-tailwind": "^1.5.9",
"@navikt/ds-tokens": "^1.5.9"
},
"devDependencies": {
"prettier-plugin-tailwindcss": "^0.1.13"
}
}
@@ -0,0 +1,46 @@
// https://www.sanity.io/schemas/make-a-field-read-only-after-publishing-once-d87bf5f6
import { useState, useEffect } from "react";
import { useDocumentOperation, useValidationStatus } from "@sanity/react-hooks";
import PublishIcon from "part:@sanity/base/publish-icon";
export default function SetAndPublishAction(props) {
const { patch, publish }: any = useDocumentOperation(props.id, props.type);
const { isValidating, markers }: any = useValidationStatus(
props.id,
props.type
);
const [isPublishing, setIsPublishing] = useState(false);
useEffect(() => {
// if the isPublishing state was set to true and the draft has changed
// to become `null` the document has been published
if (isPublishing && !props.draft) {
setIsPublishing(false);
}
}, [props.draft]);
return {
disabled:
publish.disabled ||
isValidating ||
markers.some((x) => x?.level === "error"),
label: isPublishing ? "Publishing…" : "Publish",
color: "success",
icon: PublishIcon,
onHandle: () => {
// This will update the button text
setIsPublishing(true);
// Set publishedAt to current date and time
!props.published &&
patch.execute([{ set: { publishedAt: new Date().toISOString() } }]);
// Perform the publish
publish.execute();
// Signal that the action is completed
props.onComplete();
},
};
}
@@ -0,0 +1,139 @@
import { EyeScreened } from "@navikt/ds-icons";
import { BodyLong, Button } from "@navikt/ds-react";
import React from "react";
const sanityClient = require("@sanity/client");
const SanityConfig = require("../../sanity.json");
const client = sanityClient({
projectId: SanityConfig.api.projectId,
dataset: SanityConfig.api.dataset,
apiVersion: "2021-08-21",
withCredentials: true,
});
export default function SetPrivateAction(props) {
const [isDialogOpen, setDialogOpen] = React.useState(false);
const isPrivate =
props?.published?.tilgang?.privat ?? props?.draft?.tilgang?.privat;
const handlePatch = async (dir: boolean) => {
props?.published &&
(await client
.patch(props.id)
.set({ tilgang: { privat: dir } })
.commit()
.catch((err) => {
console.error(err.message);
}));
props?.draft &&
(await client
.patch(props.draft._id)
.set({ tilgang: { privat: dir } })
.commit()
.catch((err) => {
console.error(err.message);
}));
props.onComplete();
};
return {
label: isPrivate ? "Åpne side for alle" : "Skjul side bak innlogging",
/* color: "success",
icon: PublishIcon, */
icon: EyeScreened,
onHandle: async () => {
setDialogOpen(true);
},
dialog: isDialogOpen && {
type: "modal",
onClose: props.onComplete,
header: isPrivate
? "Åpne innhold for alle"
: "Gjemme innhold bak innlogging",
content: (
<div>
{isPrivate ? (
<BodyLong spacing>
Innholdet gjøres nå tilgjengelig for alle utenfor NAV! Dette kan
medføre konsekvenser siden innholdet i artikkelen blir
tilgjengelig for alle. Innhold som NAV potensielt ikke ønsker å
dele offentlig kan medføre eks omdømmetap og uønsket oppmerksomhet
utenfra. Dobbelsjekk med temaansvarlig og andre som har skrevet
artikkelen før du velger å åpne innholdet for alle. Er du usikker
er det bare å sende en melding på #aksel eller #aksel-redaktører
på slack.
</BodyLong>
) : (
<>
<BodyLong spacing>
Innholdet gjøres nå bare tilgjengelig for NAV-ansatte. Alt
utenom "innhold" vil fortsatt være tilgjengelig for alle. Dette
inkluderer alle bilder som er lastet opp til sanity også! Husk
at ingen "sikker" data skal skrives i Aksel, og at
innloggings-barrieren er ment for å kunne dele innhold som vi
ikke er helt trygg på å dele med alle.
</BodyLong>
Dette vil fortsatt være åpent for alle
<ul>
<li>Sidetittel</li>
<li>Ingress</li>
<li>Redaktører</li>
<li>Bilder/filer</li>
<li>SEO</li>
</ul>
Dette vil bare være tilgjengelig for NAV-ansatte
<ul>
<li>"Innhold"-blokken</li>
</ul>
</>
)}
<div style={{ display: "flex", gap: "6px", marginTop: 8 }}>
{isPrivate ? (
<>
<Button
onClick={() => {
setDialogOpen(false);
handlePatch(false);
}}
>
Åpne innholdet for alle
</Button>
<Button
variant="secondary"
onClick={() => {
setDialogOpen(false);
props.onComplete();
}}
>
Avbryt
</Button>
</>
) : (
<>
<Button
onClick={() => {
setDialogOpen(false);
handlePatch(true);
}}
>
Skjul innholdet bak innlogging
</Button>
<Button
variant="secondary"
onClick={() => {
setDialogOpen(false);
props.onComplete();
}}
>
Avbryt
</Button>
</>
)}
</div>
</div>
),
},
};
}
@@ -0,0 +1,3 @@
import MediaAssetSource from "part:sanity-plugin-media/asset-source";
import Unsplash from "part:sanity-plugin-asset-source-unsplash/image-asset-source";
export default [MediaAssetSource, Unsplash];
@@ -0,0 +1,52 @@
import { useEffect } from "react";
import config from "config:sanity";
const BUNDLE_CHECK_INTERVAL = 60 * 1000;
const BUNDLE_CHECK_INTERVAL_DECLINED = 60 * 10000;
const CHANGES_AVAILABLE_MESSAGE =
"Studioet er har nye endringer! For å ta i bruk disse vil siden nå oppdateres for den nyeste versjonen.";
async function getCurrentHash() {
const basePath = (config.project && config.project.basePath) || "/";
const html = await window.fetch(basePath).then((res) => res.text());
const [, hash] = html.match(/app\.bundle\.js\?(\w+)/) || [];
return hash;
}
let hash = null;
let interval = null;
const BundleChecker = () => {
useEffect(() => {
getCurrentHash().then((newHash) => {
hash = newHash;
});
interval = createInterval();
return () => clearInterval(interval);
}, []);
// We're a react component, in theory, so return null to not render anything
return null;
};
export default BundleChecker;
const createInterval = (declined?: boolean) =>
setInterval(
async () => {
const newHash = await getCurrentHash();
if (hash && newHash !== hash) {
clearInterval(interval);
if (window.confirm(CHANGES_AVAILABLE_MESSAGE)) {
window.location.reload();
} else {
interval = createInterval(true);
}
}
},
declined ? BUNDLE_CHECK_INTERVAL_DECLINED : BUNDLE_CHECK_INTERVAL
);
@@ -0,0 +1,44 @@
import { allDocumentTypes } from "../config";
export default {
widgets: [
{
name: "document-list",
options: {
title: "Drafts for God Praksis",
query: '*[_type in $types && (_id in path("drafts.**"))]',
queryParams: {
types: allDocumentTypes.filter((x) => x.startsWith("gp")),
},
},
},
{
name: "document-list",
options: {
title: "Drafts for Designsystemet",
query: '*[_type in $types && (_id in path("drafts.**"))]',
queryParams: {
types: allDocumentTypes.filter((x) => x.startsWith("ds")),
},
},
},
{
name: "outdated-documents-widget",
options: {
type: "warning",
},
},
{
name: "outdated-documents-widget",
options: {
type: "error",
},
},
{
name: "project-info",
},
{
name: "project-users",
},
],
};
@@ -0,0 +1,24 @@
import { Picture } from "@navikt/ds-icons";
import S from "@sanity/desk-tool/structure-builder";
import React from "react";
export const adminPanel = async (roles) =>
roles.find((x) => x.name === "administrator") &&
S.listItem()
.title("Admin")
.child(
S.list()
.title("Admin")
.items([
S.documentListItem()
.title(`Forside Aksel`)
.schemaType(`vk_frontpage`)
.icon(() => <Picture />)
.id(`frontpage_vk_praksis`),
S.listItem()
.title("Standalone-sider")
.child(S.documentTypeList("aksel_standalone")),
S.listItem().title("Redirects").child(S.documentTypeList("redirect")),
])
);
Loaded 100 of 577 files, more files were not shown because too many files have changed in this diff. Show more