Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ede1f5858a | ||
|
|
ad9e7165bb | ||
|
|
77302a30b8 | ||
|
|
0ef12ef601 | ||
|
|
4174f9a7b4 | ||
|
|
608f158d70 | ||
|
|
34d41ecc78 | ||
|
|
7e62365a60 | ||
|
|
8565f410a1 | ||
|
|
46d70820df | ||
|
|
67e66ffe02 | ||
|
|
e19bf67b33 | ||
|
|
97c5f60e91 | ||
|
|
ea5293c28d | ||
|
|
6a58efa9a9 | ||
|
|
c95f33679e | ||
|
|
b52a5e02a0 | ||
|
|
ab3ef0d34b | ||
|
|
69798f6ee2 | ||
|
|
ee14586beb | ||
|
|
82470ba669 | ||
|
|
6286f0e8e6 | ||
|
|
3c08651df2 | ||
|
|
e6d55fdcd6 | ||
|
|
8c445f020c | ||
|
|
78a76bac5d | ||
|
|
75b334af61 | ||
|
|
5d98c50b80 |
No files matched your search
@@ -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"
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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 }}
|
||||
@@ -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"
|
||||
@@ -4,11 +4,10 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "next"
|
||||
paths:
|
||||
- "@navikt/**"
|
||||
pull_request:
|
||||
branches: [master]
|
||||
branches: [master, next]
|
||||
paths:
|
||||
- "@navikt/**"
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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 }}
|
||||
@@ -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/
|
||||
@@ -0,0 +1,2 @@
|
||||
**/nais-dev.yaml
|
||||
**/nais-prod.yaml
|
||||
@@ -15,3 +15,7 @@
|
||||
.rowgap[data-theme="dark"] {
|
||||
background-color: #262626;
|
||||
}
|
||||
|
||||
.rowgap-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@@ -1,5 +1,23 @@
|
||||
# @navikt/ds-codemod
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-codemod",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.4",
|
||||
"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": {
|
||||
|
||||
@@ -1,5 +1,53 @@
|
||||
# @navikt/ds-css
|
||||
|
||||
## 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
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
.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--small .navds-chips__toggle {
|
||||
gap: var(--navds-spacing-1);
|
||||
}
|
||||
|
||||
.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;
|
||||
}
|
||||
@@ -7,6 +7,7 @@
|
||||
@import "button.css";
|
||||
@import "content-container.css";
|
||||
@import "chat.css";
|
||||
@import "chips.css";
|
||||
@import "guide-panel.css";
|
||||
@import "form/index.css";
|
||||
@import "help-text.css";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.4",
|
||||
"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.4.0",
|
||||
"@navikt/ds-tokens": "^1.5.4",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -14,38 +14,117 @@
|
||||
|
||||
.navds-tag {
|
||||
border: 1px solid;
|
||||
border-color: var(--navds-tag-color-border);
|
||||
border-radius: var(--navds-border-radius-medium);
|
||||
background-color: var(--navds-tag-color-background);
|
||||
border-radius: var(--navds-border-radius-small);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0.125rem var(--navds-spacing-3);
|
||||
padding: 0.125rem var(--navds-spacing-2);
|
||||
min-height: 32px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.navds-tag--small {
|
||||
min-height: 24px;
|
||||
padding-right: var(--navds-spacing-1);
|
||||
padding-left: var(--navds-spacing-1);
|
||||
padding: 0 0.375rem;
|
||||
}
|
||||
|
||||
.navds-tag--xsmall {
|
||||
min-height: 20px;
|
||||
padding: 0 var(--navds-spacing-1);
|
||||
}
|
||||
|
||||
.navds-tag--error {
|
||||
background-color: var(--navds-tag-color-error-background);
|
||||
border-color: var(--navds-tag-color-error-border);
|
||||
border-color: var(--ac-tag-error-border, var(--navds-global-color-red-500));
|
||||
background-color: var(--ac-tag-error-bg, var(--navds-global-color-red-50));
|
||||
color: var(--ac-tag-error-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--error-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-error-filled-bg, var(--navds-global-color-red-500));
|
||||
color: var(--ac-tag-error-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-tag--success {
|
||||
background-color: var(--navds-tag-color-success-background);
|
||||
border-color: var(--navds-tag-color-success-border);
|
||||
border-color: var(--ac-tag-success-border, var(--navds-global-color-green-500));
|
||||
background-color: var(--ac-tag-success-bg, var(--navds-global-color-green-50));
|
||||
color: var(--ac-tag-success-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--success-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-success-filled-bg, var(--navds-global-color-green-500));
|
||||
color: var(--ac-tag-success-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-tag--warning {
|
||||
background-color: var(--navds-tag-color-warning-background);
|
||||
border-color: var(--navds-tag-color-warning-border);
|
||||
border-color: var(--ac-tag-warning-border, var(--navds-global-color-orange-600));
|
||||
background-color: var(--ac-tag-warning-bg, var(--navds-global-color-orange-50));
|
||||
color: var(--ac-tag-warning-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--warning-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-warning-filled-bg, var(--navds-global-color-orange-500));
|
||||
color: var(--ac-tag-warning-filled-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--info {
|
||||
background-color: var(--navds-tag-color-info-background);
|
||||
border-color: var(--navds-tag-color-info-border);
|
||||
border-color: var(--ac-tag-info-border, var(--navds-global-color-lightblue-700));
|
||||
background-color: var(--ac-tag-info-bg, var(--navds-global-color-lightblue-50));
|
||||
color: var(--ac-tag-info-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--info-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-info-filled-bg, var(--navds-global-color-lightblue-500));
|
||||
color: var(--ac-tag-info-filled-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--neutral {
|
||||
border-color: var(--ac-tag-neutral-border, var(--navds-global-color-gray-500));
|
||||
background-color: var(--ac-tag-neutral-bg, var(--navds-global-color-gray-100));
|
||||
color: var(--ac-tag-neutral-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--neutral-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-neutral-filled-bg, var(--navds-global-color-gray-800));
|
||||
color: var(--ac-tag-neutral-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-tag--alt1 {
|
||||
border-color: var(--ac-tag-alt1-border, var(--navds-global-color-purple-400));
|
||||
background-color: var(--ac-tag-alt1-bg, var(--navds-global-color-purple-100));
|
||||
color: var(--ac-tag-alt1-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--alt1-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-alt1-filled-bg, var(--navds-global-color-purple-400));
|
||||
color: var(--ac-tag-alt1-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
|
||||
.navds-tag--alt2 {
|
||||
border-color: var(--ac-tag-alt2-border, var(--navds-global-color-limegreen-500));
|
||||
background-color: var(--ac-tag-alt2-bg, var(--navds-global-color-limegreen-100));
|
||||
color: var(--ac-tag-alt2-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--alt2-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-alt2-filled-bg, var(--navds-global-color-limegreen-400));
|
||||
color: var(--ac-tag-alt2-filled-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--alt3 {
|
||||
border-color: var(--ac-tag-alt3-border, var(--navds-global-color-deepblue-400));
|
||||
background-color: var(--ac-tag-alt3-bg, var(--navds-global-color-deepblue-100));
|
||||
color: var(--ac-tag-alt3-text, var(--navds-global-color-gray-900));
|
||||
}
|
||||
|
||||
.navds-tag--alt3-filled {
|
||||
border-color: transparent;
|
||||
background-color: var(--ac-tag-alt3-filled-bg, var(--navds-global-color-deepblue-500));
|
||||
color: var(--ac-tag-alt3-filled-text, var(--navds-global-color-white));
|
||||
}
|
||||
@@ -1,5 +1,84 @@
|
||||
# @navikt/ds-react
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.4",
|
||||
"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.4.0",
|
||||
"@navikt/ds-icons": "^1.5.4",
|
||||
"@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",
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef, HTMLAttributes } from "react";
|
||||
import ToggleChips, { ToggleChipsType } from "./Toggle";
|
||||
import RemovableChips, { RemovableChipsType } from "./Removable";
|
||||
|
||||
export interface ChipsProps extends HTMLAttributes<HTMLUListElement> {
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes padding and font-sizes
|
||||
* @default "medium"
|
||||
*/
|
||||
size?: "medium" | "small";
|
||||
}
|
||||
|
||||
interface ChipsComponent
|
||||
extends React.ForwardRefExoticComponent<
|
||||
ChipsProps & React.RefAttributes<HTMLUListElement>
|
||||
> {
|
||||
Toggle: ToggleChipsType;
|
||||
Removable: RemovableChipsType;
|
||||
}
|
||||
|
||||
export const Chips: ChipsComponent = forwardRef<HTMLUListElement, ChipsProps>(
|
||||
({ className, size = "medium", children, ...rest }, ref) => {
|
||||
return (
|
||||
<ul
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl("navds-chips", className, `navds-chips--${size}`, {
|
||||
"navds-body-short navds-body-short--small": size === "medium",
|
||||
"navds-detail navds-detail--small": size === "small",
|
||||
})}
|
||||
>
|
||||
{React.Children.map(children, (chip, index) => {
|
||||
return <li key={index + (chip?.toString() ?? "")}>{chip}</li>;
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
) as ChipsComponent;
|
||||
|
||||
Chips.Toggle = ToggleChips;
|
||||
Chips.Removable = RemovableChips;
|
||||
|
||||
export default Chips;
|
||||
@@ -0,0 +1,68 @@
|
||||
import { Close } from "@navikt/ds-icons";
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef } from "react";
|
||||
import { OverridableComponent } from "..";
|
||||
|
||||
export interface RemovableChipsProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
children: string;
|
||||
/**
|
||||
* Chip-variants
|
||||
* @default "action"
|
||||
*/
|
||||
variant?: "action" | "neutral";
|
||||
/**
|
||||
* Replaces label read for screen-readers
|
||||
* @default "slett filter"
|
||||
*/
|
||||
removeLabel?: string;
|
||||
/**
|
||||
* Click callback
|
||||
*/
|
||||
onDelete?: () => void;
|
||||
}
|
||||
|
||||
export interface RemovableChipsType
|
||||
extends OverridableComponent<RemovableChipsProps, HTMLButtonElement> {}
|
||||
|
||||
export const RemovableChips: OverridableComponent<
|
||||
RemovableChipsProps,
|
||||
HTMLButtonElement
|
||||
> = forwardRef(
|
||||
(
|
||||
{
|
||||
className,
|
||||
children,
|
||||
variant = "action",
|
||||
as: Component = "button",
|
||||
removeLabel = "slett",
|
||||
onDelete,
|
||||
...rest
|
||||
},
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<Component
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl(
|
||||
"navds-chips__chip navds-chips__removable navds-chips--icon-right",
|
||||
className,
|
||||
`navds-chips__removable--${variant}`
|
||||
)}
|
||||
aria-label={`${children} ${removeLabel}`}
|
||||
onClick={(e) => {
|
||||
onDelete?.();
|
||||
rest?.onClick?.(e);
|
||||
}}
|
||||
>
|
||||
<span className="navds-chips__chip-text">{children}</span>
|
||||
<span className="navds-chips__removable-icon">
|
||||
<Close aria-hidden />
|
||||
</span>
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
) as RemovableChipsType;
|
||||
|
||||
export default RemovableChips;
|
||||
@@ -0,0 +1,41 @@
|
||||
import { SuccessStroke } from "@navikt/ds-icons";
|
||||
import cl from "clsx";
|
||||
import React, { forwardRef } from "react";
|
||||
import { OverridableComponent } from "..";
|
||||
|
||||
export interface ToggleChipsProps
|
||||
extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
children: string;
|
||||
/**
|
||||
* Toggles aria-pressed and visual-changes
|
||||
*/
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
export interface ToggleChipsType
|
||||
extends OverridableComponent<ToggleChipsProps, HTMLButtonElement> {}
|
||||
|
||||
export const ToggleChips: ToggleChipsType = forwardRef(
|
||||
(
|
||||
{ className, children, selected, as: Component = "button", ...rest },
|
||||
ref
|
||||
) => {
|
||||
return (
|
||||
<Component
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={cl("navds-chips__chip navds-chips__toggle", className, {
|
||||
"navds-chips--icon-left": selected,
|
||||
})}
|
||||
aria-pressed={selected}
|
||||
>
|
||||
{selected && (
|
||||
<SuccessStroke aria-hidden className="navds-chips__toggle-icon" />
|
||||
)}
|
||||
<span className="navds-chips__chip-text">{children}</span>
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ToggleChips;
|
||||
@@ -0,0 +1,165 @@
|
||||
import React, { useState } from "react";
|
||||
import { Chips } from ".";
|
||||
|
||||
export default {
|
||||
title: "ds-react/Chips",
|
||||
component: Chips,
|
||||
argTypes: {
|
||||
type: {
|
||||
control: {
|
||||
type: "radio",
|
||||
options: ["toggle", "removable"],
|
||||
},
|
||||
},
|
||||
size: {
|
||||
control: {
|
||||
type: "radio",
|
||||
options: ["medium", "small"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const options = ["Norsk", "Dansk", "Svensk", "Tysk", "Spansk"];
|
||||
|
||||
export const Default = (props) => {
|
||||
const [selected, setSelected] = useState(["Dansk", "Svensk"]);
|
||||
const [filter, setFilter] = useState(options);
|
||||
|
||||
if (props.type === "toggle") {
|
||||
return (
|
||||
<Chips size={props.size ?? "medium"}>
|
||||
{options.map((c) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(c)}
|
||||
key={c}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(c)
|
||||
? selected.filter((x) => x !== c)
|
||||
: [...selected, c]
|
||||
)
|
||||
}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Chips size={props.size ?? "medium"}>
|
||||
{filter.map((c) => (
|
||||
<Chips.Removable
|
||||
key={c}
|
||||
onClick={() => setFilter((x) => x.filter((y) => y !== c))}
|
||||
>
|
||||
{c}
|
||||
</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
);
|
||||
};
|
||||
|
||||
export const Toggle = () => {
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
return (
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(y)}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(y)
|
||||
? selected.filter((x) => x !== y)
|
||||
: [...selected, y]
|
||||
)
|
||||
}
|
||||
key={y}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
);
|
||||
};
|
||||
|
||||
export const Removable = () => {
|
||||
return (
|
||||
<div className="colgap">
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Removable key={y}>{c}</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Removable variant="neutral" key={y}>
|
||||
{c}
|
||||
</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Regular = () => {
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
return (
|
||||
<div className="colgap">
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Removable key={y}>{c}</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
<Chips>
|
||||
{options.map((c, y) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(y)}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(y)
|
||||
? selected.filter((x) => x !== y)
|
||||
: [...selected, y]
|
||||
)
|
||||
}
|
||||
key={y}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Small = () => {
|
||||
const [selected, setSelected] = useState<number[]>([]);
|
||||
return (
|
||||
<div className="colgap">
|
||||
<Chips size="small">
|
||||
{options.map((c, y) => (
|
||||
<Chips.Removable key={y}>{c}</Chips.Removable>
|
||||
))}
|
||||
</Chips>
|
||||
<Chips size="small">
|
||||
{options.map((c, y) => (
|
||||
<Chips.Toggle
|
||||
selected={selected.includes(y)}
|
||||
onClick={() =>
|
||||
setSelected(
|
||||
selected.includes(y)
|
||||
? selected.filter((x) => x !== y)
|
||||
: [...selected, y]
|
||||
)
|
||||
}
|
||||
key={y}
|
||||
>
|
||||
{c}
|
||||
</Chips.Toggle>
|
||||
))}
|
||||
</Chips>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { default as Chips, ChipsProps } from "./Chips";
|
||||
@@ -1,4 +1,3 @@
|
||||
import isSaturday from "date-fns/isSaturday";
|
||||
import React, { useId, useState } from "react";
|
||||
import { UNSAFE_useDatepicker, UNSAFE_useRangeDatepicker } from "..";
|
||||
import { Button } from "../..";
|
||||
@@ -221,8 +220,13 @@ export const UserControlled = () => {
|
||||
};
|
||||
|
||||
export const Validering = () => {
|
||||
const { datepickerProps, selectedDay, inputProps } = UNSAFE_useDatepicker({
|
||||
fromDate: new Date("Aug 23 2019"),
|
||||
const [error, setError] = useState(false);
|
||||
const { datepickerProps, inputProps } = UNSAFE_useDatepicker({
|
||||
fromDate: new Date("Aug 2 2019"),
|
||||
onValidate: (val) => setError(val.isWeekend),
|
||||
defaultSelected: new Date("Nov 26 2022"),
|
||||
disableWeekends: true,
|
||||
onDateChange: console.log,
|
||||
});
|
||||
|
||||
return (
|
||||
@@ -230,8 +234,8 @@ export const Validering = () => {
|
||||
<DatePicker {...datepickerProps}>
|
||||
<DatePicker.Input
|
||||
error={
|
||||
selectedDay && isSaturday(selectedDay)
|
||||
? "NAV-kontoret er ikke åpent på lørdager. Velg en annen dag."
|
||||
error
|
||||
? "NAV-kontoret er ikke åpent i helger. Velg en annen dag."
|
||||
: undefined
|
||||
}
|
||||
{...inputProps}
|
||||
@@ -261,3 +265,24 @@ export const ErrorInput = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const UseRangedDatepickerValidation = () => {
|
||||
const { datepickerProps, fromInputProps, toInputProps } =
|
||||
UNSAFE_useRangeDatepicker({
|
||||
fromDate: new Date("Aug 23 2019"),
|
||||
disableWeekends: true,
|
||||
disabled: [new Date("Oct 10 2022")],
|
||||
onValidate: console.table,
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", gap: "1rem" }}>
|
||||
<DatePicker {...datepickerProps}>
|
||||
<div style={{ display: "flex", gap: "1rem" }}>
|
||||
<DatePicker.Input {...fromInputProps} label="Fra" />
|
||||
<DatePicker.Input {...toInputProps} label="Til" />
|
||||
</div>
|
||||
</DatePicker>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,9 @@
|
||||
export { useDatepicker as UNSAFE_useDatepicker } from "./useDatepicker";
|
||||
export type { DateValidationT } from "./useDatepicker";
|
||||
export { useRangeDatepicker as UNSAFE_useRangeDatepicker } from "./useRangeDatepicker";
|
||||
export type { RangeValidationT } from "./useRangeDatepicker";
|
||||
export { useMonthpicker as UNSAFE_useMonthpicker } from "./useMonthPicker";
|
||||
export type { MonthValidationT } from "./useMonthPicker";
|
||||
export { useDateInputContext, DateContext } from "./useDateInputContext";
|
||||
export {
|
||||
useSharedMonthContext,
|
||||
|
||||
@@ -36,6 +36,15 @@ export interface UseDatepickerOptions
|
||||
* Callback for changed state
|
||||
*/
|
||||
onDateChange?: (val?: Date) => void;
|
||||
/**
|
||||
* Input-format
|
||||
* @default "dd.MM.yyyy"
|
||||
*/
|
||||
inputFormat?: string;
|
||||
/**
|
||||
* validation-callback
|
||||
*/
|
||||
onValidate?: (val: DateValidationT) => void;
|
||||
}
|
||||
|
||||
interface UseDatepickerValue {
|
||||
@@ -62,6 +71,27 @@ interface UseDatepickerValue {
|
||||
setSelected: (date?: Date) => void;
|
||||
}
|
||||
|
||||
export type DateValidationT = {
|
||||
isDisabled: boolean;
|
||||
isWeekend: boolean;
|
||||
isEmpty: boolean;
|
||||
isInvalid: boolean;
|
||||
isValidDate: boolean;
|
||||
isBefore: boolean;
|
||||
isAfter: boolean;
|
||||
};
|
||||
|
||||
const getValidationMessage = (val = {}): DateValidationT => ({
|
||||
isDisabled: false,
|
||||
isWeekend: false,
|
||||
isEmpty: false,
|
||||
isInvalid: false,
|
||||
isBefore: false,
|
||||
isAfter: false,
|
||||
isValidDate: true,
|
||||
...val,
|
||||
});
|
||||
|
||||
export const useDatepicker = (
|
||||
opt: UseDatepickerOptions = {}
|
||||
): UseDatepickerValue => {
|
||||
@@ -75,6 +105,8 @@ export const useDatepicker = (
|
||||
disabled,
|
||||
disableWeekends,
|
||||
onDateChange,
|
||||
inputFormat,
|
||||
onValidate,
|
||||
} = opt;
|
||||
|
||||
const locale = getLocaleFromString(_locale);
|
||||
@@ -90,7 +122,7 @@ export const useDatepicker = (
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const defaultInputValue = defaultSelected
|
||||
? formatDateForInput(defaultSelected, locale, "date")
|
||||
? formatDateForInput(defaultSelected, locale, "date", inputFormat)
|
||||
: "";
|
||||
const [inputValue, setInputValue] = useState(defaultInputValue);
|
||||
|
||||
@@ -99,6 +131,11 @@ export const useDatepicker = (
|
||||
setSelectedDay(date);
|
||||
};
|
||||
|
||||
const updateValidation = (val: Partial<DateValidationT> = {}) => {
|
||||
const msg = getValidationMessage(val);
|
||||
onValidate?.(msg);
|
||||
};
|
||||
|
||||
const handleFocusIn = useCallback(
|
||||
(e) => {
|
||||
if (!e?.target || !e?.target?.nodeType) {
|
||||
@@ -134,7 +171,9 @@ export const useDatepicker = (
|
||||
const setSelected = (date: Date | undefined) => {
|
||||
updateDate(date);
|
||||
setMonth(date ?? today);
|
||||
setInputValue(date ? formatDateForInput(date, locale, "date") : "");
|
||||
setInputValue(
|
||||
date ? formatDateForInput(date, locale, "date", inputFormat) : ""
|
||||
);
|
||||
};
|
||||
|
||||
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
|
||||
@@ -143,13 +182,14 @@ export const useDatepicker = (
|
||||
let day = parseDate(e.target.value, today, locale, "date");
|
||||
if (isValidDate(day)) {
|
||||
setMonth(day);
|
||||
setInputValue(formatDateForInput(day, locale, "date"));
|
||||
setInputValue(formatDateForInput(day, locale, "date", inputFormat));
|
||||
}
|
||||
};
|
||||
|
||||
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
|
||||
let day = parseDate(e.target.value, today, locale, "date");
|
||||
isValidDate(day) && setInputValue(formatDateForInput(day, locale, "date"));
|
||||
isValidDate(day) &&
|
||||
setInputValue(formatDateForInput(day, locale, "date", inputFormat));
|
||||
};
|
||||
|
||||
/* Only allow de-selecting if not required */
|
||||
@@ -162,11 +202,15 @@ export const useDatepicker = (
|
||||
if (!required && selected) {
|
||||
updateDate(undefined);
|
||||
setInputValue("");
|
||||
updateValidation({ isValidDate: false, isEmpty: true });
|
||||
return;
|
||||
}
|
||||
updateDate(day);
|
||||
updateValidation();
|
||||
setMonth(day);
|
||||
setInputValue(day ? formatDateForInput(day, locale, "date") : "");
|
||||
setInputValue(
|
||||
day ? formatDateForInput(day, locale, "date", inputFormat) : ""
|
||||
);
|
||||
};
|
||||
|
||||
// When changing the input field, save its value in state and check if the
|
||||
@@ -176,22 +220,39 @@ export const useDatepicker = (
|
||||
setInputValue(e.target.value);
|
||||
const day = parseDate(e.target.value, today, locale, "date");
|
||||
|
||||
const isBefore =
|
||||
fromDate && day && differenceInCalendarDays(fromDate, day) > 0;
|
||||
const isAfter = toDate && day && differenceInCalendarDays(day, toDate) > 0;
|
||||
|
||||
if (
|
||||
!isValidDate(day) ||
|
||||
(disabled &&
|
||||
((disableWeekends && isWeekend(day)) || isMatch(day, disabled)))
|
||||
(disableWeekends && isWeekend(day)) ||
|
||||
(disabled && isMatch(day, disabled))
|
||||
) {
|
||||
updateDate(undefined);
|
||||
updateValidation({
|
||||
isInvalid: isValidDate(day),
|
||||
isWeekend: disableWeekends && isWeekend(day),
|
||||
isDisabled: disabled && isMatch(day, disabled),
|
||||
isValidDate: false,
|
||||
isEmpty: !e.target.value,
|
||||
isBefore: isBefore ?? false,
|
||||
isAfter: isAfter ?? false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const isBefore = fromDate && differenceInCalendarDays(fromDate, day) > 0;
|
||||
const isAfter = toDate && differenceInCalendarDays(day, toDate) > 0;
|
||||
if (isBefore || isAfter) {
|
||||
updateDate(undefined);
|
||||
updateValidation({
|
||||
isValidDate: false,
|
||||
isBefore: isBefore ?? false,
|
||||
isAfter: isAfter ?? false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
updateDate(day);
|
||||
updateValidation();
|
||||
setMonth(day);
|
||||
};
|
||||
|
||||
@@ -217,13 +278,15 @@ export const useDatepicker = (
|
||||
month,
|
||||
onMonthChange: (month) => setMonth(month),
|
||||
onDayClick: handleDayClick,
|
||||
selected: selectedDay,
|
||||
selected: selectedDay ?? new Date("Invalid date"),
|
||||
locale: _locale,
|
||||
fromDate,
|
||||
toDate,
|
||||
today,
|
||||
open,
|
||||
onOpenToggle: () => setOpen((x) => !x),
|
||||
disabled,
|
||||
disableWeekends,
|
||||
ref: daypickerRef,
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,15 @@ export interface UseMonthPickerOptions
|
||||
* Callback for month-change
|
||||
*/
|
||||
onMonthChange?: (date?: Date) => void;
|
||||
/**
|
||||
* Input-format
|
||||
* @default "MMMM yyyy"
|
||||
*/
|
||||
inputFormat?: string;
|
||||
/**
|
||||
* validation-callback
|
||||
*/
|
||||
onValidate?: (val: MonthValidationT) => void;
|
||||
}
|
||||
|
||||
interface UseMonthPickerValue {
|
||||
@@ -48,6 +57,25 @@ interface UseMonthPickerValue {
|
||||
reset: () => void;
|
||||
}
|
||||
|
||||
export type MonthValidationT = {
|
||||
isDisabled: boolean;
|
||||
isEmpty: boolean;
|
||||
isInvalid: boolean;
|
||||
isValidMonth: boolean;
|
||||
isBefore: boolean;
|
||||
isAfter: boolean;
|
||||
};
|
||||
|
||||
const getValidationMessage = (val = {}): MonthValidationT => ({
|
||||
isDisabled: false,
|
||||
isEmpty: false,
|
||||
isInvalid: false,
|
||||
isBefore: false,
|
||||
isAfter: false,
|
||||
isValidMonth: true,
|
||||
...val,
|
||||
});
|
||||
|
||||
export const useMonthpicker = (
|
||||
opt: UseMonthPickerOptions = {}
|
||||
): UseMonthPickerValue => {
|
||||
@@ -59,6 +87,8 @@ export const useMonthpicker = (
|
||||
disabled,
|
||||
required,
|
||||
onMonthChange,
|
||||
inputFormat,
|
||||
onValidate,
|
||||
} = opt;
|
||||
|
||||
const [defaultSelected, setDefaultSelected] = useState(_defaultSelected);
|
||||
@@ -75,7 +105,7 @@ export const useMonthpicker = (
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const defaultInputValue = defaultSelected
|
||||
? formatDateForInput(defaultSelected, locale, "month")
|
||||
? formatDateForInput(defaultSelected, locale, "month", inputFormat)
|
||||
: "";
|
||||
|
||||
const [inputValue, setInputValue] = useState(defaultInputValue);
|
||||
@@ -85,6 +115,11 @@ export const useMonthpicker = (
|
||||
setSelectedMonth(date);
|
||||
};
|
||||
|
||||
const updateValidation = (val: Partial<MonthValidationT> = {}) => {
|
||||
const msg = getValidationMessage(val);
|
||||
onValidate?.(msg);
|
||||
};
|
||||
|
||||
const handleFocusIn = useCallback(
|
||||
(e) => {
|
||||
if (!e?.target || !e?.target?.nodeType) {
|
||||
@@ -120,7 +155,9 @@ export const useMonthpicker = (
|
||||
const setSelected = (date: Date | undefined) => {
|
||||
updateMonth(date);
|
||||
setYear(date ?? today);
|
||||
setInputValue(date ? formatDateForInput(date, locale, "month") : "");
|
||||
setInputValue(
|
||||
date ? formatDateForInput(date, locale, "month", inputFormat) : ""
|
||||
);
|
||||
};
|
||||
|
||||
const handleFocus: React.FocusEventHandler<HTMLInputElement> = (e) => {
|
||||
@@ -128,13 +165,14 @@ export const useMonthpicker = (
|
||||
let day = parseDate(e.target.value, today, locale, "month");
|
||||
if (isValidDate(day)) {
|
||||
setYear(day);
|
||||
setInputValue(formatDateForInput(day, locale, "month"));
|
||||
setInputValue(formatDateForInput(day, locale, "month", inputFormat));
|
||||
}
|
||||
};
|
||||
|
||||
const handleBlur: React.FocusEventHandler<HTMLInputElement> = (e) => {
|
||||
let day = parseDate(e.target.value, today, locale, "month");
|
||||
isValidDate(day) && setInputValue(formatDateForInput(day, locale, "month"));
|
||||
isValidDate(day) &&
|
||||
setInputValue(formatDateForInput(day, locale, "month", inputFormat));
|
||||
};
|
||||
|
||||
/* Only allow de-selecting if not required */
|
||||
@@ -146,11 +184,15 @@ export const useMonthpicker = (
|
||||
|
||||
if (!required && !month) {
|
||||
updateMonth(undefined);
|
||||
updateValidation({ isValidMonth: false, isEmpty: true });
|
||||
setInputValue("");
|
||||
return;
|
||||
}
|
||||
updateMonth(month);
|
||||
setInputValue(month ? formatDateForInput(month, locale, "month") : "");
|
||||
updateValidation();
|
||||
setInputValue(
|
||||
month ? formatDateForInput(month, locale, "month", inputFormat) : ""
|
||||
);
|
||||
};
|
||||
|
||||
// When changing the input field, save its value in state and check if the
|
||||
@@ -160,32 +202,48 @@ export const useMonthpicker = (
|
||||
setInputValue(e.target.value);
|
||||
const month = parseDate(e.target.value, today, locale, "month");
|
||||
|
||||
if (!isValidDate(month) || (disabled && isMatch(month, disabled))) {
|
||||
updateMonth(undefined);
|
||||
return;
|
||||
}
|
||||
|
||||
const isBefore =
|
||||
fromDate &&
|
||||
month &&
|
||||
(fromDate.getFullYear() > month.getFullYear() ||
|
||||
(fromDate.getFullYear() === month.getFullYear() &&
|
||||
fromDate.getMonth() > month.getMonth()));
|
||||
|
||||
const isAfter =
|
||||
toDate &&
|
||||
month &&
|
||||
(toDate.getFullYear() < month.getFullYear() ||
|
||||
(toDate.getFullYear() === month.getFullYear() &&
|
||||
toDate.getMonth() < month.getMonth()));
|
||||
|
||||
if (!isValidDate(month) || (disabled && isMatch(month, disabled))) {
|
||||
updateMonth(undefined);
|
||||
updateValidation({
|
||||
isInvalid: isValidDate(month),
|
||||
isDisabled: disabled && isMatch(month, disabled),
|
||||
isValidMonth: false,
|
||||
isEmpty: !e.target.value,
|
||||
isBefore: isBefore ?? false,
|
||||
isAfter: isAfter ?? false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
isAfter ||
|
||||
isBefore ||
|
||||
(fromDate && toDate && !isMatch(month, [{ from: fromDate, to: toDate }]))
|
||||
) {
|
||||
updateMonth(undefined);
|
||||
updateValidation({
|
||||
isValidMonth: false,
|
||||
isBefore: isBefore ?? false,
|
||||
isAfter: isAfter ?? false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
updateMonth(month);
|
||||
updateValidation();
|
||||
setYear(month);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* eslint-disable react/jsx-pascal-case */
|
||||
import { act, render } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import React from "react";
|
||||
import { UNSAFE_DatePicker, UNSAFE_useRangeDatepicker } from "..";
|
||||
|
||||
const RangeDemo = () => {
|
||||
const { datepickerProps, fromInputProps, selectedRange, toInputProps } =
|
||||
UNSAFE_useRangeDatepicker({
|
||||
fromDate: new Date("Aug 23 2019"),
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", gap: "1rem" }}>
|
||||
<UNSAFE_DatePicker {...datepickerProps}>
|
||||
<UNSAFE_DatePicker.Input {...fromInputProps} label="Fra" />
|
||||
<UNSAFE_DatePicker.Input {...toInputProps} label="Til" />
|
||||
</UNSAFE_DatePicker>
|
||||
<div title="res">{JSON.stringify(selectedRange)}</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
describe("Writing in input sets correct values", () => {
|
||||
it("useRangeDatepicker same date", async () => {
|
||||
const utils = render(<RangeDemo />);
|
||||
|
||||
const fraInput = utils.getByRole("textbox", { name: "Fra" });
|
||||
const tilInput = utils.getByRole("textbox", { name: "Til" });
|
||||
await act(async () => {
|
||||
await userEvent.type(fraInput, "03.08.2022");
|
||||
await userEvent.type(tilInput, "03.08.2022");
|
||||
});
|
||||
const res = utils.getByTitle("res");
|
||||
expect(res.innerHTML).toEqual(
|
||||
JSON.stringify({
|
||||
from: "2022-08-03T00:00:00.000Z",
|
||||
to: "2022-08-03T00:00:00.000Z",
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("useRangeDatepicker before after to ", async () => {
|
||||
const utils = render(<RangeDemo />);
|
||||
|
||||
const fraInput = utils.getByRole("textbox", { name: "Fra" });
|
||||
const tilInput = utils.getByRole("textbox", { name: "Til" });
|
||||
await act(async () => {
|
||||
await userEvent.type(fraInput, "03.08.2022");
|
||||
await userEvent.type(tilInput, "02.08.2022");
|
||||
});
|
||||
const res = utils.getByTitle("res");
|
||||
expect(res.innerHTML).toEqual(
|
||||
JSON.stringify({
|
||||
from: "2022-08-03T00:00:00.000Z",
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -10,10 +10,42 @@ import {
|
||||
isValidDate,
|
||||
parseDate,
|
||||
} from "../utils";
|
||||
import { UseDatepickerOptions } from "./useDatepicker";
|
||||
import { DateValidationT, UseDatepickerOptions } from "./useDatepicker";
|
||||
|
||||
export type RangeValidationT = {
|
||||
from: DateValidationT;
|
||||
to: DateValidationT & { isBeforeFrom?: boolean };
|
||||
};
|
||||
|
||||
const getValidationMessage = (from = {}, to = {}): RangeValidationT => ({
|
||||
from: {
|
||||
isDisabled: false,
|
||||
isWeekend: false,
|
||||
isEmpty: false,
|
||||
isInvalid: false,
|
||||
isBefore: false,
|
||||
isAfter: false,
|
||||
isValidDate: true,
|
||||
...from,
|
||||
},
|
||||
to: {
|
||||
isDisabled: false,
|
||||
isWeekend: false,
|
||||
isEmpty: false,
|
||||
isInvalid: false,
|
||||
isBefore: false,
|
||||
isAfter: false,
|
||||
isBeforeFrom: false,
|
||||
isValidDate: true,
|
||||
...to,
|
||||
},
|
||||
});
|
||||
|
||||
interface UseRangeDatepickerOptions
|
||||
extends Omit<UseDatepickerOptions, "defaultSelected" | "onDateChange"> {
|
||||
extends Omit<
|
||||
UseDatepickerOptions,
|
||||
"defaultSelected" | "onDateChange" | "onValidate"
|
||||
> {
|
||||
/**
|
||||
* The initially selected DateRange
|
||||
*/
|
||||
@@ -22,6 +54,10 @@ interface UseRangeDatepickerOptions
|
||||
* Callback for changed state
|
||||
*/
|
||||
onRangeChange?: (val?: DateRange) => void;
|
||||
/**
|
||||
* validation-callback
|
||||
*/
|
||||
onValidate?: (val: RangeValidationT) => void;
|
||||
}
|
||||
|
||||
interface UseRangeDatepickerValue {
|
||||
@@ -65,6 +101,92 @@ const RANGE = {
|
||||
|
||||
type RangeT = typeof RANGE[keyof typeof RANGE];
|
||||
|
||||
const fromValidation = (day: Date, opt?: UseRangeDatepickerOptions) => {
|
||||
const isBefore =
|
||||
opt?.fromDate && day && differenceInCalendarDays(opt?.fromDate, day) > 0;
|
||||
const isAfter =
|
||||
opt?.toDate && day && differenceInCalendarDays(day, opt?.toDate) > 0;
|
||||
|
||||
if (
|
||||
isValidDate(day) &&
|
||||
!(opt?.disableWeekends && isWeekend(day)) &&
|
||||
!(opt?.disabled && isMatch(day, opt.disabled))
|
||||
) {
|
||||
return {
|
||||
isValidDate: false,
|
||||
isInvalid: !isValidDate(day),
|
||||
isWeekend: opt?.disableWeekends && isWeekend(day),
|
||||
isDisabled: opt?.disabled && isMatch(day, opt.disabled),
|
||||
isBefore: isBefore,
|
||||
isAfter: isAfter,
|
||||
};
|
||||
}
|
||||
if (isBefore || isAfter) {
|
||||
return {
|
||||
isValidDate: false,
|
||||
isBefore: isBefore,
|
||||
isAfter: isAfter,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const toValidation = (
|
||||
day: Date,
|
||||
from: Date,
|
||||
opt?: UseRangeDatepickerOptions
|
||||
) => {
|
||||
const isBefore =
|
||||
opt?.fromDate && day && differenceInCalendarDays(opt?.fromDate, day) > 0;
|
||||
const isAfter =
|
||||
opt?.toDate && day && differenceInCalendarDays(day, opt?.toDate) > 0;
|
||||
|
||||
const isBeforeFrom =
|
||||
(from && differenceInCalendarDays(from, day) > 0) ?? false;
|
||||
|
||||
if (
|
||||
isValidDate(day) &&
|
||||
!(opt?.disableWeekends && isWeekend(day)) &&
|
||||
!(opt?.disabled && isMatch(day, opt.disabled))
|
||||
) {
|
||||
return {
|
||||
isValidDate: false,
|
||||
isInvalid: !isValidDate(day),
|
||||
isWeekend: opt?.disableWeekends && isWeekend(day),
|
||||
isDisabled: opt?.disabled && isMatch(day, opt.disabled),
|
||||
isBefore,
|
||||
isAfter,
|
||||
isBeforeFrom,
|
||||
};
|
||||
}
|
||||
if (isBefore || isAfter || isBeforeFrom) {
|
||||
return {
|
||||
isValidDate: false,
|
||||
isBefore,
|
||||
isAfter,
|
||||
isBeforeFrom,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const initialValidation = (
|
||||
range?: DateRange,
|
||||
opt?: UseRangeDatepickerOptions
|
||||
): RangeValidationT => {
|
||||
if (!range || !range?.from) {
|
||||
return getValidationMessage(
|
||||
{ isEmpty: true, isValidDate: false },
|
||||
{ isEmpty: true, isValidDate: false }
|
||||
);
|
||||
}
|
||||
|
||||
const fromVal = fromValidation(range.from, opt);
|
||||
const toVal = range.to
|
||||
? toValidation(range.to, range.from, opt)
|
||||
: { isEmpty: true, isValidDate: false };
|
||||
|
||||
return getValidationMessage({ ...fromVal }, { ...toVal });
|
||||
};
|
||||
|
||||
export const useRangeDatepicker = (
|
||||
opt: UseRangeDatepickerOptions = {}
|
||||
): UseRangeDatepickerValue => {
|
||||
@@ -77,6 +199,8 @@ export const useRangeDatepicker = (
|
||||
disabled,
|
||||
disableWeekends,
|
||||
onRangeChange,
|
||||
inputFormat,
|
||||
onValidate,
|
||||
} = opt;
|
||||
|
||||
const locale = getLocaleFromString(_locale);
|
||||
@@ -97,15 +221,20 @@ export const useRangeDatepicker = (
|
||||
|
||||
const [fromInputValue, setFromInputValue] = useState(
|
||||
defaultSelected?.from
|
||||
? formatDateForInput(defaultSelected.from, locale, "date")
|
||||
? formatDateForInput(defaultSelected.from, locale, "date", inputFormat)
|
||||
: ""
|
||||
);
|
||||
|
||||
const [toInputValue, setToInputValue] = useState(
|
||||
defaultSelected?.to
|
||||
? formatDateForInput(defaultSelected.to, locale, "date")
|
||||
? formatDateForInput(defaultSelected.to, locale, "date", inputFormat)
|
||||
: ""
|
||||
);
|
||||
|
||||
const [validation, setValidation] = useState<RangeValidationT>(
|
||||
initialValidation(selectedRange, opt)
|
||||
);
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const updateRange = (range?: DateRange) => {
|
||||
@@ -113,6 +242,15 @@ export const useRangeDatepicker = (
|
||||
setSelectedRange(range);
|
||||
};
|
||||
|
||||
const updateValidation = (
|
||||
from: Partial<RangeValidationT["from"]> = {},
|
||||
to: Partial<RangeValidationT["to"]> = {}
|
||||
) => {
|
||||
const msg = getValidationMessage(from, to);
|
||||
setValidation(msg);
|
||||
onValidate?.(msg);
|
||||
};
|
||||
|
||||
const handleFocusIn = useCallback(
|
||||
(e) => {
|
||||
if (!e?.target || !e?.target?.nodeType) {
|
||||
@@ -143,14 +281,20 @@ export const useRangeDatepicker = (
|
||||
const reset = () => {
|
||||
updateRange(defaultSelected ?? { from: undefined, to: undefined });
|
||||
setMonth(defaultSelected ? defaultSelected?.from : today);
|
||||
setValidation(
|
||||
initialValidation(
|
||||
defaultSelected ?? { from: undefined, to: undefined },
|
||||
opt
|
||||
)
|
||||
);
|
||||
setFromInputValue(
|
||||
defaultSelected?.from
|
||||
? formatDateForInput(defaultSelected.from, locale, "date")
|
||||
? formatDateForInput(defaultSelected.from, locale, "date", inputFormat)
|
||||
: ""
|
||||
);
|
||||
setToInputValue(
|
||||
defaultSelected?.to
|
||||
? formatDateForInput(defaultSelected.to, locale, "date")
|
||||
? formatDateForInput(defaultSelected.to, locale, "date", inputFormat)
|
||||
: ""
|
||||
);
|
||||
setDefaultSelected(_defaultSelected);
|
||||
@@ -159,11 +303,16 @@ export const useRangeDatepicker = (
|
||||
const setSelected = (range?: DateRange) => {
|
||||
updateRange(range);
|
||||
setFromInputValue(
|
||||
range?.from ? formatDateForInput(range.from, locale, "date") : ""
|
||||
range?.from
|
||||
? formatDateForInput(range.from, locale, "date", inputFormat)
|
||||
: ""
|
||||
);
|
||||
setToInputValue(
|
||||
range?.to ? formatDateForInput(range?.to, locale, "date") : ""
|
||||
range?.to
|
||||
? formatDateForInput(range?.to, locale, "date", inputFormat)
|
||||
: ""
|
||||
);
|
||||
setValidation(initialValidation(range, opt));
|
||||
};
|
||||
|
||||
const handleFocus = (e, src: RangeT) => {
|
||||
@@ -172,52 +321,10 @@ export const useRangeDatepicker = (
|
||||
if (isValidDate(day)) {
|
||||
setMonth(day);
|
||||
src === RANGE.FROM
|
||||
? setFromInputValue(formatDateForInput(day, locale, "date"))
|
||||
: setToInputValue(formatDateForInput(day, locale, "date"));
|
||||
}
|
||||
};
|
||||
|
||||
const handleInputs = (day: Date, src: RangeT) => {
|
||||
if (src === RANGE.FROM) {
|
||||
const isAfter =
|
||||
toInputValue &&
|
||||
differenceInCalendarDays(
|
||||
day,
|
||||
parseDate(toInputValue, today, locale, "date")
|
||||
) > 0;
|
||||
|
||||
if (isAfter) {
|
||||
setFromInputValue(
|
||||
formatDateForInput(
|
||||
parseDate(toInputValue, today, locale, "date"),
|
||||
locale,
|
||||
"date"
|
||||
? setFromInputValue(
|
||||
formatDateForInput(day, locale, "date", inputFormat)
|
||||
)
|
||||
);
|
||||
setToInputValue(formatDateForInput(day, locale, "date"));
|
||||
} else {
|
||||
setFromInputValue(formatDateForInput(day, locale, "date"));
|
||||
}
|
||||
} else if (src === RANGE.TO) {
|
||||
const isBefore =
|
||||
fromInputValue &&
|
||||
differenceInCalendarDays(
|
||||
parseDate(fromInputValue, today, locale, "date"),
|
||||
day
|
||||
) > 0;
|
||||
|
||||
if (isBefore) {
|
||||
setToInputValue(
|
||||
formatDateForInput(
|
||||
parseDate(fromInputValue, today, locale, "date"),
|
||||
locale,
|
||||
"date"
|
||||
)
|
||||
);
|
||||
setFromInputValue(formatDateForInput(day, locale, "date"));
|
||||
} else {
|
||||
setToInputValue(formatDateForInput(day, locale, "date"));
|
||||
}
|
||||
: setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -227,7 +334,19 @@ export const useRangeDatepicker = (
|
||||
return;
|
||||
}
|
||||
|
||||
handleInputs(day, src);
|
||||
if (src === RANGE.FROM) {
|
||||
setFromInputValue(formatDateForInput(day, locale, "date", inputFormat));
|
||||
} else if (src === RANGE.TO) {
|
||||
setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
|
||||
}
|
||||
};
|
||||
|
||||
const validateDay = (day: any) => {
|
||||
return (
|
||||
isValidDate(day) &&
|
||||
!(disableWeekends && isWeekend(day)) &&
|
||||
!(disabled && isMatch(day, disabled))
|
||||
);
|
||||
};
|
||||
|
||||
const handleSelect = (range) => {
|
||||
@@ -238,68 +357,140 @@ export const useRangeDatepicker = (
|
||||
!selectedRange?.from && selectedRange?.to ? selectedRange?.to : range?.to;
|
||||
|
||||
range?.from
|
||||
? setFromInputValue(formatDateForInput(range?.from, locale, "date"))
|
||||
? setFromInputValue(
|
||||
formatDateForInput(range?.from, locale, "date", inputFormat)
|
||||
)
|
||||
: setFromInputValue("");
|
||||
prevToRange
|
||||
? setToInputValue(formatDateForInput(prevToRange, locale, "date"))
|
||||
? setToInputValue(
|
||||
formatDateForInput(prevToRange, locale, "date", inputFormat)
|
||||
)
|
||||
: setToInputValue("");
|
||||
updateValidation(
|
||||
{ isValidDate: !!range?.from, isEmpty: !range?.from },
|
||||
{ isValidDate: !!range?.to, isEmpty: !prevToRange }
|
||||
);
|
||||
updateRange({ from: range?.from, to: prevToRange });
|
||||
};
|
||||
|
||||
/* live-update datepicker based on changes in inputfields */
|
||||
const handleChange = (e, src: RangeT) => {
|
||||
src === RANGE.FROM
|
||||
? setFromInputValue(e.target.value)
|
||||
: setToInputValue(e.target.value);
|
||||
const day = parseDate(e.target.value, today, locale, "date");
|
||||
|
||||
if (
|
||||
!isValidDate(day) ||
|
||||
(disabled &&
|
||||
((disableWeekends && isWeekend(day)) || isMatch(day, disabled)))
|
||||
) {
|
||||
updateRange(
|
||||
src === RANGE.FROM
|
||||
? { ...selectedRange, from: undefined }
|
||||
: { from: selectedRange?.from, to: undefined }
|
||||
const fromChange = (
|
||||
val: string = "",
|
||||
day: Date,
|
||||
isBefore = false,
|
||||
isAfter = false
|
||||
) => {
|
||||
setFromInputValue(val);
|
||||
if (!validateDay(day)) {
|
||||
updateRange({ ...selectedRange, from: undefined });
|
||||
updateValidation(
|
||||
{
|
||||
isEmpty: !val,
|
||||
isValidDate: false,
|
||||
isInvalid: !isValidDate(day),
|
||||
isWeekend: disableWeekends && isWeekend(day),
|
||||
isDisabled: disabled && isMatch(day, disabled),
|
||||
isBefore,
|
||||
isAfter,
|
||||
},
|
||||
validation.to
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (isBefore || isAfter) {
|
||||
updateRange({ ...selectedRange, from: undefined });
|
||||
updateValidation(
|
||||
{
|
||||
isValidDate: false,
|
||||
isBefore,
|
||||
isAfter,
|
||||
},
|
||||
validation.to
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
selectedRange?.to &&
|
||||
differenceInCalendarDays(day, selectedRange?.to) > 0
|
||||
) {
|
||||
updateRange({ to: day, from: day });
|
||||
setToInputValue(formatDateForInput(day, locale, "date", inputFormat));
|
||||
setMonth(day);
|
||||
updateValidation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (toInputValue && !selectedRange?.to) {
|
||||
const toDay = parseDate(toInputValue, today, locale, "date");
|
||||
if (validateDay(toDay)) {
|
||||
updateRange({ from: day, to: toDay });
|
||||
setMonth(day);
|
||||
updateValidation();
|
||||
return;
|
||||
}
|
||||
}
|
||||
updateRange({ ...selectedRange, from: day });
|
||||
updateValidation({}, validation.to);
|
||||
setMonth(day);
|
||||
};
|
||||
|
||||
const toChange = (
|
||||
val: string = "",
|
||||
day: Date,
|
||||
isBefore = false,
|
||||
isAfter = false
|
||||
) => {
|
||||
setToInputValue(val);
|
||||
if (!validateDay(day)) {
|
||||
updateRange({ from: selectedRange?.from, to: undefined });
|
||||
updateValidation(validation.from, {
|
||||
isEmpty: !val,
|
||||
isValidDate: false,
|
||||
isInvalid: !isValidDate(day),
|
||||
isWeekend: disableWeekends && isWeekend(day),
|
||||
isDisabled: disabled && isMatch(day, disabled),
|
||||
isBefore,
|
||||
isAfter,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBefore || isAfter) {
|
||||
updateRange({ from: selectedRange?.from, to: undefined });
|
||||
updateValidation(validation.from, {
|
||||
isValidDate: false,
|
||||
isBefore,
|
||||
isAfter,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
/* If to-value < from-value */
|
||||
if (
|
||||
selectedRange?.from &&
|
||||
differenceInCalendarDays(selectedRange?.from, day) > 0
|
||||
) {
|
||||
updateRange({ from: selectedRange?.from, to: undefined });
|
||||
updateValidation(validation.from, {
|
||||
isValidDate: false,
|
||||
isBeforeFrom: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
updateRange({ from: selectedRange?.from, to: day });
|
||||
updateValidation(validation.from, {});
|
||||
setMonth(day);
|
||||
};
|
||||
|
||||
/* live-update datepicker based on changes in inputfields */
|
||||
const handleChange = (e, src: RangeT) => {
|
||||
const day = parseDate(e.target.value, today, locale, "date");
|
||||
const isBefore = fromDate && differenceInCalendarDays(fromDate, day) > 0;
|
||||
const isAfter = toDate && differenceInCalendarDays(day, toDate) > 0;
|
||||
if (isBefore || isAfter) {
|
||||
src === RANGE.FROM
|
||||
? updateRange({ ...selectedRange, from: undefined })
|
||||
: updateRange({ from: selectedRange?.from, to: undefined });
|
||||
return;
|
||||
}
|
||||
|
||||
/* If to-value < from-value, switch places in state */
|
||||
if (
|
||||
src === RANGE.TO &&
|
||||
selectedRange?.from &&
|
||||
differenceInCalendarDays(selectedRange?.from, day) >= 0
|
||||
) {
|
||||
updateRange({ from: day, to: selectedRange?.from });
|
||||
setMonth(day);
|
||||
return;
|
||||
}
|
||||
|
||||
/* If from-value > to-value , switch places in state */
|
||||
if (
|
||||
src === RANGE.FROM &&
|
||||
selectedRange?.to &&
|
||||
differenceInCalendarDays(day, selectedRange?.to) >= 0
|
||||
) {
|
||||
updateRange({ to: day, from: selectedRange?.to });
|
||||
setMonth(day);
|
||||
return;
|
||||
}
|
||||
|
||||
src === RANGE.FROM && updateRange({ ...selectedRange, from: day });
|
||||
src === RANGE.TO && updateRange({ from: selectedRange?.from, to: day });
|
||||
setMonth(day);
|
||||
return src === RANGE.FROM
|
||||
? fromChange(e.target.value, day, isBefore, isAfter)
|
||||
: toChange(e.target.value, day, isBefore, isAfter);
|
||||
};
|
||||
|
||||
const handleClose = useCallback(() => {
|
||||
@@ -336,6 +527,8 @@ export const useRangeDatepicker = (
|
||||
mode: "range" as const,
|
||||
open,
|
||||
onOpenToggle: () => setOpen((x) => !x),
|
||||
disabled,
|
||||
disableWeekends,
|
||||
ref: datePickerRef,
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,9 @@ export {
|
||||
UNSAFE_useDatepicker,
|
||||
UNSAFE_useMonthpicker,
|
||||
UNSAFE_useRangeDatepicker,
|
||||
RangeValidationT,
|
||||
DateValidationT,
|
||||
MonthValidationT,
|
||||
} from "./hooks";
|
||||
export {
|
||||
default as UNSAFE_MonthPicker,
|
||||
|
||||
@@ -90,6 +90,26 @@ export const UseMonthpicker = () => {
|
||||
);
|
||||
};
|
||||
|
||||
export const UseMonthpickerFormat = () => {
|
||||
const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
|
||||
disabled: [new Date("Apr 1 2022")],
|
||||
onMonthChange: console.log,
|
||||
inputFormat: "MM.yyyy",
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={{ height: "20rem" }}>
|
||||
<MonthPicker {...monthpickerProps}>
|
||||
<MonthPicker.Input
|
||||
{...inputProps}
|
||||
label="Velg måned"
|
||||
variant="monthpicker"
|
||||
/>
|
||||
</MonthPicker>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Required = () => {
|
||||
const { inputProps, monthpickerProps } = UNSAFE_useMonthpicker({
|
||||
locale: "nb",
|
||||
|
||||
@@ -6,16 +6,16 @@ const parse = (inp: string) => parseDate(inp, new Date(), nb, "date");
|
||||
|
||||
describe("Format date to correct output", () => {
|
||||
test("formatDateForInput", () => {
|
||||
expect(formatDateForInput(parse("15/05/22"), nb, "date")).toEqual(
|
||||
expect(formatDateForInput(parse("15/05/2022"), nb, "date")).toEqual(
|
||||
"15.05.2022"
|
||||
);
|
||||
expect(formatDateForInput(parse("1/5/22"), nb, "date")).toEqual(
|
||||
expect(formatDateForInput(parse("1/5/2022"), nb, "date")).toEqual(
|
||||
"01.05.2022"
|
||||
);
|
||||
expect(formatDateForInput(parse("1/05/22"), nb, "date")).toEqual(
|
||||
expect(formatDateForInput(parse("1/05/2022"), nb, "date")).toEqual(
|
||||
"01.05.2022"
|
||||
);
|
||||
expect(formatDateForInput(parse("15/5/22"), nb, "date")).toEqual(
|
||||
expect(formatDateForInput(parse("15/5/2022"), nb, "date")).toEqual(
|
||||
"15.05.2022"
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,6 @@ import { parseDate } from "..";
|
||||
import { isValidDate } from "..";
|
||||
import nb from "date-fns/locale/nb";
|
||||
import getMonth from "date-fns/getMonth";
|
||||
import getYear from "date-fns/getYear";
|
||||
|
||||
const check = (inp: string) =>
|
||||
expect(isValidDate(parseDate(inp, new Date(), nb, "date")));
|
||||
@@ -11,71 +10,32 @@ const parse = (inp: string) => parseDate(inp, new Date(), nb, "date");
|
||||
|
||||
describe("Parse date-inputs", () => {
|
||||
test("No spaces", () => {
|
||||
check("150522").toBeTruthy();
|
||||
check("11052022").toBeTruthy();
|
||||
check("15052022").toBeTruthy();
|
||||
});
|
||||
|
||||
test(". divider", () => {
|
||||
check("1.5.22").toBeTruthy();
|
||||
check("1.5.2022").toBeTruthy();
|
||||
check("11.05.22").toBeTruthy();
|
||||
check("11.05.2022").toBeTruthy();
|
||||
});
|
||||
|
||||
test("/ divider", () => {
|
||||
check("1/5/22").toBeTruthy();
|
||||
check("10/5/22").toBeTruthy();
|
||||
check("1/5/2022").toBeTruthy();
|
||||
check("10/5/2022").toBeTruthy();
|
||||
check("1/05/22").toBeTruthy();
|
||||
check("10/05/22").toBeTruthy();
|
||||
check("1/05/2022").toBeTruthy();
|
||||
check("10/05/2022").toBeTruthy();
|
||||
});
|
||||
|
||||
test("- divider", () => {
|
||||
check("1-5-22").toBeTruthy();
|
||||
check("10-5-22").toBeTruthy();
|
||||
check("1-5-2022").toBeTruthy();
|
||||
check("10-5-2022").toBeTruthy();
|
||||
check("1-05-22").toBeTruthy();
|
||||
check("10-05-22").toBeTruthy();
|
||||
check("1-05-2022").toBeTruthy();
|
||||
check("10-05-2022").toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Parse date-inputs to correct year", () => {
|
||||
test("No spaces", () => {
|
||||
expect(getYear(parse("150522"))).toEqual(2022);
|
||||
});
|
||||
|
||||
test(". divider", () => {
|
||||
expect(getYear(parse("1.05.22"))).toEqual(2022);
|
||||
expect(getYear(parse("11.05.22"))).toEqual(2022);
|
||||
expect(getYear(parse("1.5.22"))).toEqual(2022);
|
||||
expect(getYear(parse("11.5.22"))).toEqual(2022);
|
||||
});
|
||||
|
||||
test("/ divider", () => {
|
||||
expect(getYear(parse("1/5/22"))).toEqual(2022);
|
||||
expect(getYear(parse("10/5/22"))).toEqual(2022);
|
||||
expect(getYear(parse("1/05/22"))).toEqual(2022);
|
||||
expect(getYear(parse("10/05/22"))).toEqual(2022);
|
||||
});
|
||||
|
||||
test("- divider", () => {
|
||||
expect(getYear(parse("1-5-22"))).toEqual(2022);
|
||||
expect(getYear(parse("10-5-22"))).toEqual(2022);
|
||||
expect(getYear(parse("1-05-22"))).toEqual(2022);
|
||||
expect(getYear(parse("10-05-22"))).toEqual(2022);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Parse date-inputs to correct month", () => {
|
||||
test("No spaces", () => {
|
||||
expect(getMonth(parse("150522"))).toEqual(4);
|
||||
expect(getMonth(parse("11052022"))).toEqual(4);
|
||||
expect(getMonth(parse("15052022"))).toEqual(4);
|
||||
});
|
||||
|
||||
@@ -7,11 +7,13 @@ import {
|
||||
export const formatDateForInput = (
|
||||
date: Date,
|
||||
locale: Locale,
|
||||
type: "date" | "month"
|
||||
type: "date" | "month",
|
||||
inputFormat?: string
|
||||
) => {
|
||||
const INPUT_DATE_STRING_FORMAT =
|
||||
type === "date"
|
||||
inputFormat ??
|
||||
(type === "date"
|
||||
? INPUT_DATE_STRING_FORMAT_DATE
|
||||
: INPUT_DATE_STRING_FORMAT_MONTH;
|
||||
: INPUT_DATE_STRING_FORMAT_MONTH);
|
||||
return format(date, INPUT_DATE_STRING_FORMAT, { locale });
|
||||
};
|
||||
@@ -6,16 +6,10 @@ export const INPUT_DATE_STRING_FORMAT_DATE = "dd.MM.yyyy";
|
||||
export const INPUT_DATE_STRING_FORMAT_MONTH = "MMMM yyyy";
|
||||
|
||||
const ALLOWED_INPUT_FORMATS_DATE = [
|
||||
"ddMMyy",
|
||||
"d.M.yy",
|
||||
"dd.MM.yy",
|
||||
"dd/MM/yy",
|
||||
"dd-MM-yy",
|
||||
INPUT_DATE_STRING_FORMAT_DATE,
|
||||
"ddMMyyyy",
|
||||
"dd/MM/yyyy",
|
||||
"dd-MM-yyyy",
|
||||
"d.M.yyyy",
|
||||
];
|
||||
|
||||
const ALLOWED_INPUT_FORMATS_MONTH = [
|
||||
@@ -28,20 +22,35 @@ const ALLOWED_INPUT_FORMATS_MONTH = [
|
||||
...ALLOWED_INPUT_FORMATS_DATE,
|
||||
];
|
||||
|
||||
const isTwoDigitYear = (dateString, today, locale, formats) => {
|
||||
let parsed;
|
||||
const newFormat = formats.map((x) => x.replace("yyyy", "yy"));
|
||||
for (const format of newFormat) {
|
||||
parsed = parse(dateString, format, today, { locale });
|
||||
if (isValidDate(parsed)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export const parseDate = (
|
||||
date: string,
|
||||
today: Date,
|
||||
locale: Locale,
|
||||
type: "date" | "month"
|
||||
) => {
|
||||
): Date => {
|
||||
let parsed;
|
||||
const ALLOWED_FORMATS =
|
||||
type === "date" ? ALLOWED_INPUT_FORMATS_DATE : ALLOWED_INPUT_FORMATS_MONTH;
|
||||
for (const format of ALLOWED_FORMATS) {
|
||||
parsed = parse(date, format, today, { locale });
|
||||
if (isValidDate(parsed)) {
|
||||
if (
|
||||
isValidDate(parsed) &&
|
||||
!isTwoDigitYear(date, today, locale, ALLOWED_FORMATS)
|
||||
) {
|
||||
return parsed;
|
||||
}
|
||||
}
|
||||
return parsed;
|
||||
return new Date("Invalid date");
|
||||
};
|
||||
@@ -16,6 +16,7 @@ export * from "./panel";
|
||||
export * from "./popover";
|
||||
export * from "./read-more";
|
||||
export * from "./chat";
|
||||
export * from "./chips";
|
||||
export * from "./stepper";
|
||||
export * from "./tag";
|
||||
export * from "./toggle-group";
|
||||
|
||||
@@ -114,7 +114,7 @@ describe("Popover", () => {
|
||||
expect(fn).toHaveBeenCalledTimes(0);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
}, 20000);
|
||||
|
||||
it("keep open on popover-click", async () => {
|
||||
const fn = jest.fn();
|
||||
|
||||
@@ -3,19 +3,31 @@ import cl from "clsx";
|
||||
import { BodyShort, Detail } from "..";
|
||||
|
||||
export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
|
||||
/**
|
||||
* Tag label
|
||||
*/
|
||||
children: React.ReactNode;
|
||||
/**
|
||||
* Changes background and border color
|
||||
* Changes visual profile of tag
|
||||
*/
|
||||
variant: "warning" | "error" | "info" | "success";
|
||||
variant:
|
||||
| "warning"
|
||||
| "warning-filled"
|
||||
| "error"
|
||||
| "error-filled"
|
||||
| "info"
|
||||
| "info-filled"
|
||||
| "success"
|
||||
| "success-filled"
|
||||
| "neutral"
|
||||
| "neutral-filled"
|
||||
| "alt1"
|
||||
| "alt1-filled"
|
||||
| "alt2"
|
||||
| "alt2-filled"
|
||||
| "alt3"
|
||||
| "alt3-filled";
|
||||
/**
|
||||
* Changes padding and font-sizes
|
||||
* @default "medium"
|
||||
*/
|
||||
size?: "medium" | "small";
|
||||
size?: "medium" | "small" | "xsmall";
|
||||
}
|
||||
|
||||
export const Tag = forwardRef<HTMLSpanElement, TagProps>(
|
||||
@@ -27,7 +39,7 @@ export const Tag = forwardRef<HTMLSpanElement, TagProps>(
|
||||
{...rest}
|
||||
ref={ref}
|
||||
as="span"
|
||||
size={size}
|
||||
size={size === "medium" ? "medium" : "small"}
|
||||
className={cl(
|
||||
"navds-tag",
|
||||
className,
|
||||
|
||||
@@ -9,17 +9,70 @@ export default {
|
||||
defaultValue: "info",
|
||||
control: {
|
||||
type: "radio",
|
||||
options: ["error", "warning", "info", "success"],
|
||||
options: [
|
||||
"warning",
|
||||
"error",
|
||||
"info",
|
||||
"success",
|
||||
"neutral",
|
||||
"alt1",
|
||||
"alt2",
|
||||
"alt3",
|
||||
"warning-filled",
|
||||
"error-filled",
|
||||
"info-filled",
|
||||
"success-filled",
|
||||
"neutral-filled",
|
||||
"alt1-filled",
|
||||
"alt2-filled",
|
||||
"alt3-filled",
|
||||
],
|
||||
},
|
||||
},
|
||||
size: {
|
||||
defaultValue: "medium",
|
||||
control: {
|
||||
type: "radio",
|
||||
options: ["xsmall", "small", "medium"],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const variants: Array<"error" | "warning" | "info" | "success"> = [
|
||||
"error",
|
||||
const variants: Array<
|
||||
| "warning"
|
||||
| "warning-filled"
|
||||
| "error"
|
||||
| "error-filled"
|
||||
| "info"
|
||||
| "info-filled"
|
||||
| "success"
|
||||
| "success-filled"
|
||||
| "neutral"
|
||||
| "neutral-filled"
|
||||
| "alt1"
|
||||
| "alt1-filled"
|
||||
| "alt2"
|
||||
| "alt2-filled"
|
||||
| "alt3"
|
||||
| "alt3-filled"
|
||||
> = [
|
||||
"warning",
|
||||
"error",
|
||||
"info",
|
||||
"success",
|
||||
"neutral",
|
||||
"alt1",
|
||||
"alt2",
|
||||
"alt3",
|
||||
"warning-filled",
|
||||
"error-filled",
|
||||
"info-filled",
|
||||
"success-filled",
|
||||
"neutral-filled",
|
||||
"alt1-filled",
|
||||
"alt2-filled",
|
||||
"alt3-filled",
|
||||
];
|
||||
|
||||
export const Default = (props) => (
|
||||
@@ -34,10 +87,34 @@ Default.args = {
|
||||
|
||||
export const Small = () => {
|
||||
return (
|
||||
<div className="rowgap">
|
||||
<div className="rowgap rowgap-wrap">
|
||||
{variants.map((variant, i) => (
|
||||
<Tag key={variant} variant={variant} size="small">
|
||||
{new Array(i + 1).fill("Id elit esse")}
|
||||
{variant}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const xSmall = () => {
|
||||
return (
|
||||
<div className="rowgap rowgap-wrap">
|
||||
{variants.map((variant, i) => (
|
||||
<Tag key={variant} variant={variant} size="xsmall">
|
||||
{variant}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Variants = () => {
|
||||
return (
|
||||
<div className="rowgap rowgap-wrap">
|
||||
{variants.map((variant, i) => (
|
||||
<Tag key={variant} variant={variant}>
|
||||
{variant}
|
||||
</Tag>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# @navikt/ds-tailwind
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tailwind",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.4",
|
||||
"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.4.0",
|
||||
"@types/jest": "^27.0.1",
|
||||
"@navikt/ds-tokens": "^1.5.4",
|
||||
"@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"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,23 @@
|
||||
# @navikt/ds-tokens
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tokens",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.4",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,27 @@
|
||||
# @navikt/ds-icons
|
||||
|
||||
## 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
|
||||
|
||||
@@ -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": "",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-icons",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.4",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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,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 |
@@ -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 |
@@ -4,5 +4,6 @@
|
||||
"outDir": "./cjs",
|
||||
"module": "commonjs"
|
||||
},
|
||||
"exclude": ["./figma", "./util", "./tests", "./scripts", "**/*.stories.*"]
|
||||
"exclude": ["./figma", "./util", "./tests", "./scripts", "**/*.stories.*"],
|
||||
"include": ["./src"]
|
||||
}
|
||||
@@ -1,5 +1,27 @@
|
||||
# @navikt/ds-css-internal
|
||||
|
||||
## 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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css-internal",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.4",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,77 @@
|
||||
# @navikt/ds-react-internal
|
||||
|
||||
## 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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react-internal",
|
||||
"version": "1.4.0",
|
||||
"version": "1.5.4",
|
||||
"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.4.0",
|
||||
"@navikt/ds-react": "^1.4.0",
|
||||
"@navikt/ds-icons": "^1.5.4",
|
||||
"@navikt/ds-react": "^1.5.4",
|
||||
"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",
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "./cjs",
|
||||
"module": "commonjs"
|
||||
}
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
@@ -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"),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.4",
|
||||
"@navikt/ds-css": "^1.5.4",
|
||||
"@navikt/ds-css-internal": "^1.5.4",
|
||||
"@navikt/ds-icons": "^1.5.4",
|
||||
"@navikt/ds-react": "^1.5.4",
|
||||
"@navikt/ds-react-internal": "^1.5.4",
|
||||
"@navikt/ds-tailwind": "^1.5.4",
|
||||
"@navikt/ds-tokens": "^1.5.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier-plugin-tailwindcss": "^0.1.13"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
// 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]);
|
||||
|
||||
console.log(markers);
|
||||
|
||||
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,23 @@
|
||||
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")),
|
||||
])
|
||||
);
|
||||
@@ -0,0 +1,102 @@
|
||||
import { prinsipper } from "@/lib";
|
||||
import { Facilitet } from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
import documentStore from "part:@sanity/base/datastore/document";
|
||||
import React from "react";
|
||||
import { map } from "rxjs/operators";
|
||||
|
||||
const temaQuery = `*[_type == "aksel_tema" && count(*[references(^._id)]) > 0]`;
|
||||
|
||||
const AkselLogo = () => (
|
||||
<svg
|
||||
width="192px"
|
||||
height="192px"
|
||||
viewBox="0 0 192 192"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
focusable="false"
|
||||
aria-hidden="true"
|
||||
strokeLinecap="round"
|
||||
strokeWidth="10"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path d="m41.63 150.3 47.39-47.38" />
|
||||
<path d="M40.92 80.3 77.7 43.53c4.25-4.24 9.9-4.24 14.15 0l56.56 56.57c4.25 4.25 4.25 9.9 0 14.14l-36.77 36.77" />
|
||||
<path d="m40.92 80.3 38.19-38.18c3.53-3.54 6.72-3.18 13.79-3.18h48.79s0 0 0 0c6.36 0 11.31 4.95 11.31 11.31 0 0 0 0 0 0v48.8c0 7.06.35 10.24-3.18 13.78l-38.19 38.18" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export const akselInnhold = async () => {
|
||||
return S.listItem()
|
||||
.title("Aksel")
|
||||
.icon(() => <AkselLogo />)
|
||||
.child(
|
||||
S.list()
|
||||
.title("Innhold")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Artikler")
|
||||
.child(() =>
|
||||
documentStore.listenQuery(temaQuery).pipe(
|
||||
map((tema: any) => {
|
||||
return S.list()
|
||||
.title("Artikler")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Alle artikler")
|
||||
.child(S.documentTypeList("aksel_artikkel")),
|
||||
S.listItem()
|
||||
.title("Uten tema")
|
||||
.child(
|
||||
S.documentTypeList("aksel_artikkel").filter(
|
||||
`_type == "aksel_artikkel" && !defined(tema)`
|
||||
)
|
||||
),
|
||||
...tema.map((tag) => {
|
||||
return S.listItem()
|
||||
.title(tag.title)
|
||||
.child(
|
||||
S.documentList()
|
||||
.title(tag.title)
|
||||
.filter(
|
||||
`_type == 'aksel_artikkel' && $tag in tema[]->title`
|
||||
)
|
||||
.params({ tag: tag.title })
|
||||
);
|
||||
}),
|
||||
]);
|
||||
})
|
||||
)
|
||||
),
|
||||
S.listItem().title("Blogg").child(S.documentTypeList("aksel_blogg")),
|
||||
S.listItem()
|
||||
.title("Prinsipper")
|
||||
.child(
|
||||
S.list()
|
||||
.title("Prinsipper")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Alle artikler")
|
||||
.child(S.documentTypeList("aksel_prinsipp")),
|
||||
...prinsipper.map(({ value, title }) =>
|
||||
S.listItem()
|
||||
.title(title)
|
||||
.child(
|
||||
S.documentList()
|
||||
.title(title)
|
||||
.filter(
|
||||
`_type == 'aksel_prinsipp' && $value == prinsipp.prinsippvalg`
|
||||
)
|
||||
.params({ value })
|
||||
)
|
||||
),
|
||||
])
|
||||
),
|
||||
S.divider(),
|
||||
S.listItem()
|
||||
.title("Temasider")
|
||||
.icon(() => <Facilitet />)
|
||||
.child(S.documentTypeList("aksel_tema")),
|
||||
])
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,92 @@
|
||||
import { CoApplicant, Facilitet, Information, People } from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
import userStore from "part:@sanity/base/user";
|
||||
import React from "react";
|
||||
import { createSuperPane } from "sanity-super-pane";
|
||||
import { ComponentPageWebPreview } from "../../web-previews/ComponentWebPreview";
|
||||
import { KomponentPreview } from "../../web-previews/KomponentPreview";
|
||||
import { PageWebPreview } from "../../web-previews/PageWebPreview";
|
||||
import { adminPanel } from "./admin";
|
||||
import { akselInnhold } from "./aksel";
|
||||
import { dsPanel } from "./ds";
|
||||
import { profilePanel } from "./profile";
|
||||
|
||||
export const getDefaultDocumentNode = ({ schemaType }) => {
|
||||
switch (schemaType) {
|
||||
case "komponent_artikkel":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(ComponentPageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "ds_artikkel":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "aksel_artikkel":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "aksel_blogg":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "aksel_prinsipp":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
case "aksel_standalone":
|
||||
return S.document().views([
|
||||
S.view.form(),
|
||||
S.view.component(PageWebPreview).title("Preview"),
|
||||
S.view.component(KomponentPreview).title("Preview-dev"),
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
const items = [
|
||||
S.divider(),
|
||||
S.listItem()
|
||||
.title("Redaktører")
|
||||
.icon(() => <People />)
|
||||
.child(createSuperPane("editor")),
|
||||
|
||||
S.divider(),
|
||||
];
|
||||
|
||||
export default () => {
|
||||
return userStore.getCurrentUser().then(async ({ roles, id }) => {
|
||||
const panels = [];
|
||||
const admin = await adminPanel(roles);
|
||||
|
||||
const profile = await profilePanel(id);
|
||||
const ds = await dsPanel(roles);
|
||||
const aksel = await akselInnhold();
|
||||
const intro = [];
|
||||
|
||||
profile && intro.push(profile);
|
||||
profile && intro.push(S.divider());
|
||||
|
||||
let struct = items;
|
||||
|
||||
if (ds) {
|
||||
struct = [ds, ...struct];
|
||||
}
|
||||
struct = [aksel, ...struct];
|
||||
if (admin) {
|
||||
struct = [...struct, admin];
|
||||
}
|
||||
|
||||
return S.list()
|
||||
.title("Aksel")
|
||||
.items([...intro, ...struct, ...panels]);
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,119 @@
|
||||
import {
|
||||
Facilitet,
|
||||
FileContent,
|
||||
Findout,
|
||||
Folder,
|
||||
Picture,
|
||||
Place,
|
||||
Ruler,
|
||||
Task,
|
||||
} from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
import client from "part:@sanity/base/client";
|
||||
import React from "react";
|
||||
import { createSuperPane } from "sanity-super-pane";
|
||||
|
||||
export const dsPanel = async (roles) => {
|
||||
const role = roles.some(({ name }) => "aksel-editor" === name);
|
||||
|
||||
if (role) {
|
||||
return null;
|
||||
} else {
|
||||
return S.listItem()
|
||||
.title("Designsystemet")
|
||||
.icon(() => <Facilitet />)
|
||||
.child(
|
||||
S.list()
|
||||
.title("Designsystem")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Komponentsider")
|
||||
.icon(() => <Facilitet />)
|
||||
.child(createSuperPane("komponent_artikkel")),
|
||||
S.listItem()
|
||||
.title("Artikler")
|
||||
.icon(() => <FileContent />)
|
||||
.child(createSuperPane("ds_artikkel")),
|
||||
S.divider(),
|
||||
S.documentListItem()
|
||||
.title(`Navigasjon`)
|
||||
.schemaType(`ds_navigation`)
|
||||
.icon(() => <Place />)
|
||||
.id(`ds_navigationid`),
|
||||
|
||||
S.listItem()
|
||||
.title("Publiserte sider ikke i navigasjon")
|
||||
.child(async (): Promise<any> => {
|
||||
const doc = await client.fetch(
|
||||
`*[_id == 'ds_navigationid'][0]{
|
||||
headings[]{
|
||||
title,
|
||||
menu
|
||||
}
|
||||
}`
|
||||
);
|
||||
if (!doc.headings) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let allIds = "";
|
||||
try {
|
||||
allIds = doc.headings
|
||||
.map((heading) =>
|
||||
heading.menu
|
||||
.filter((item) => item._type === "item")
|
||||
.map((item) => item.link._ref)
|
||||
.map((x) => `"${x}"`)
|
||||
.join(",")
|
||||
)
|
||||
.join(",");
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
return S.documentList()
|
||||
.title("Sider ikke i navigasjon")
|
||||
.filter(
|
||||
`!(_id in [${allIds}]) && !(_id in path('drafts.**')) && _type in ["komponent_artikkel", "ds_artikkel"]`
|
||||
);
|
||||
}),
|
||||
S.documentListItem()
|
||||
.title(`Forside`)
|
||||
.schemaType(`ds_frontpage`)
|
||||
.icon(() => <Picture />)
|
||||
.id(`frontpage_designsystem`),
|
||||
S.divider(),
|
||||
S.listItem()
|
||||
.title("Autogenerert data")
|
||||
.child(
|
||||
S.list()
|
||||
.title("Autogenerert data")
|
||||
.items([
|
||||
S.listItem()
|
||||
.title("Eksempler")
|
||||
.icon(() => <span>{`EX`}</span>)
|
||||
.child(S.documentTypeList("kode_eksempler_fil")),
|
||||
S.listItem()
|
||||
.title("Fargekategorier")
|
||||
.icon(() => <Folder />)
|
||||
.child(S.documentTypeList("ds_color_categories")),
|
||||
S.listItem()
|
||||
.title("Props")
|
||||
.icon(() => <Folder />)
|
||||
.child(S.documentTypeList("ds_props")),
|
||||
S.listItem()
|
||||
.title("Tokens")
|
||||
.icon(() => <Folder />)
|
||||
.child(S.documentTypeList("ds_tokens")),
|
||||
])
|
||||
),
|
||||
S.divider(),
|
||||
S.documentListItem()
|
||||
.title(`Komponent-template`)
|
||||
.schemaType(`ds_component_template`)
|
||||
.icon(() => <Task />)
|
||||
.id(`ds_component_templateid`),
|
||||
])
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Picture } from "@navikt/ds-icons";
|
||||
import S from "@sanity/desk-tool/structure-builder";
|
||||
import userStore from "part:@sanity/base/user";
|
||||
import client from "part:@sanity/base/client";
|
||||
|
||||
import React from "react";
|
||||
|
||||
export const profilePanel = async (id) => {
|
||||
const ids = await client.withConfig({ apiVersion: "2021-05-31" })
|
||||
.fetch(`*[_type == "editor"]{
|
||||
_id,
|
||||
user_id
|
||||
}`);
|
||||
|
||||
const editor = ids.find(({ user_id }) => user_id?.current === id);
|
||||
|
||||
if (editor) {
|
||||
return S.documentListItem()
|
||||
.title(`Profil`)
|
||||
.schemaType(`editor`)
|
||||
.icon(() => <Picture />)
|
||||
.id(editor._id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
import React from "react";
|
||||
import { People } from "@navikt/ds-icons";
|
||||
import T from "@sanity/base/initial-value-template-builder";
|
||||
import userStore from "part:@sanity/base/user";
|
||||
|
||||
const sanityClient = require("@sanity/client");
|
||||
const sanityToken = process.env.SANITY_TOKEN;
|
||||
const SanityConfig = require("../sanity.json");
|
||||
|
||||
const client = sanityClient({
|
||||
projectId: SanityConfig.api.projectId,
|
||||
dataset: SanityConfig.api.dataset,
|
||||
apiVersion: "2020-06-19",
|
||||
/* Token er safe og har bare tillatelse til å lese template doc */
|
||||
token:
|
||||
"skt6kqEcXmRxUTGDzdEcw11g7HJi9DaHX2fyn8Z0Dearr1k67ykW2N64KTP9GxAPNN6P8TlzPjUdkfGsvbJkfmwfq0UNudKfMYOfyz9OeA666y15pPLRr6D7xnrJGEEBYwSvG6baLLiJI478YowWpjqp1Mz2U1PbAPnIMW4W5btTpdQbwPSD",
|
||||
useCdn: false,
|
||||
});
|
||||
|
||||
export default [
|
||||
...T.defaults().filter((x) => !["komponent_artikkel"].includes(x.spec.id)),
|
||||
|
||||
T.template({
|
||||
id: "komponent_artikkel_template",
|
||||
title: "Mal for Komponentsider",
|
||||
schemaType: "komponent_artikkel",
|
||||
value: async () => {
|
||||
const doc = await client.fetch(`*[_type == "ds_component_template"][0]`);
|
||||
return doc
|
||||
? Object.entries(doc).reduce((old, [key, val]) => {
|
||||
return key.startsWith("_") ? { ...old } : { ...old, [key]: val };
|
||||
}, {})
|
||||
: {};
|
||||
},
|
||||
}),
|
||||
T.template({
|
||||
id: "newEditor",
|
||||
title: "Editor",
|
||||
schemaType: "editor",
|
||||
icon: () => <People />,
|
||||
value: async () => {
|
||||
const { id, displayName } = await userStore.getUser("me");
|
||||
|
||||
return {
|
||||
title: displayName,
|
||||
user_id: {
|
||||
current: id,
|
||||
},
|
||||
_type: "editor",
|
||||
};
|
||||
},
|
||||
}),
|
||||
];
|
||||