mirror of
https://github.com/navikt/aksel.git
synced 2026-10-17 03:02:03 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5fec1f24f4 | ||
|
|
c27c1cfe26 | ||
|
|
5a649d2282 | ||
|
|
baac9cc251 | ||
|
|
d924d523e4 | ||
|
|
fc5a77081d | ||
|
|
1f3477a3e9 | ||
|
|
925450cb73 |
No files matched your search
@@ -0,0 +1,22 @@
|
||||
name: Eksempel på bruk
|
||||
description: Send et eksempel på ting fra Aksel som er brukt i det fri (tokens, komponenter, maler, etc)
|
||||
title: "[Eksempel på bruk]: "
|
||||
labels: ["dokumentasjon 📖"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Takk for at du bidrar til Aksel!
|
||||
- type: input
|
||||
id: title
|
||||
attributes:
|
||||
label: Lenke til side
|
||||
description: Lenke til siden hvor eksemplet er
|
||||
placeholder:
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: examples
|
||||
attributes:
|
||||
label: Forklaring
|
||||
description: Forklar om det er noe man må gjøre for å se eksemplet, eller hvor på siden det ligger
|
||||
@@ -1,5 +1,9 @@
|
||||
# @navikt/aksel-icons
|
||||
|
||||
## 5.9.2
|
||||
|
||||
## 5.9.1
|
||||
|
||||
## 5.9.0
|
||||
|
||||
## 5.8.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/aksel-icons",
|
||||
"version": "5.9.0",
|
||||
"version": "5.9.2",
|
||||
"author": "Aksel | NAV",
|
||||
"homepage": "https://aksel.nav.no/ikoner",
|
||||
"repository": {
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# @navikt/aksel-stylelint
|
||||
|
||||
## 5.9.2
|
||||
|
||||
## 5.9.1
|
||||
|
||||
## 5.9.0
|
||||
|
||||
## 5.8.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/aksel-stylelint",
|
||||
"version": "5.9.0",
|
||||
"version": "5.9.2",
|
||||
"author": "Aksel | NAV",
|
||||
"homepage": "https://aksel.nav.no/grunnleggende/kode/stylelint",
|
||||
"repository": {
|
||||
@@ -35,8 +35,8 @@
|
||||
"dev": "yarn watch:lint"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-css": "^5.9.0",
|
||||
"@navikt/ds-tokens": "^5.9.0",
|
||||
"@navikt/ds-css": "^5.9.2",
|
||||
"@navikt/ds-tokens": "^5.9.2",
|
||||
"@types/jest": "^29.0.0",
|
||||
"concurrently": "7.2.1",
|
||||
"copyfiles": "2.4.1",
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# @navikt/aksel
|
||||
|
||||
## 5.9.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-css@5.9.2
|
||||
|
||||
## 5.9.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`925450cb7`](https://github.com/navikt/aksel/commit/925450cb73cd792cd3b6ad3ebf9f38ba022ee4df)]:
|
||||
- @navikt/ds-css@5.9.1
|
||||
|
||||
## 5.9.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/aksel",
|
||||
"version": "5.9.0",
|
||||
"version": "5.9.2",
|
||||
"description": "Aksel command line interface. Handles css-imports, codemods and more",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"license": "MIT",
|
||||
@@ -29,7 +29,7 @@
|
||||
},
|
||||
"homepage": "https://aksel.nav.no/grunnleggende/kode/kommandolinje",
|
||||
"dependencies": {
|
||||
"@navikt/ds-css": "5.9.0",
|
||||
"@navikt/ds-css": "5.9.2",
|
||||
"axios": "1.3.6",
|
||||
"chalk": "4.1.0",
|
||||
"clipboardy": "^2.3.0",
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# @navikt/ds-css
|
||||
|
||||
## 5.9.2
|
||||
|
||||
## 5.9.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- :lipstick: Modal: Bedre håndtering av mobiler i landskapsmodus ([#2444](https://github.com/navikt/aksel/pull/2444))
|
||||
|
||||
## 5.9.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -59,12 +59,17 @@
|
||||
|
||||
@media (min-width: 480px) {
|
||||
.navds-modal {
|
||||
max-width: calc((100% - 6px) - 2em);
|
||||
max-height: calc((100% - 6px) - 2em);
|
||||
max-width: calc(100% - 6px - 2em);
|
||||
}
|
||||
|
||||
.navds-modal--autowidth {
|
||||
max-width: min(700px, calc((100% - 6px) - 2em));
|
||||
max-width: min(700px, calc(100% - 6px - 2em));
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-height: 480px) {
|
||||
.navds-modal {
|
||||
max-height: calc(100% - 6px - 2em);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-css",
|
||||
"version": "5.9.0",
|
||||
"version": "5.9.2",
|
||||
"description": "CSS for NAV Designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"keywords": [
|
||||
@@ -27,7 +27,7 @@
|
||||
"css:get-version": "node config/get-version.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^5.9.0",
|
||||
"@navikt/ds-tokens": "^5.9.2",
|
||||
"cssnano": "6.0.0",
|
||||
"fast-glob": "3.2.11",
|
||||
"lodash": "4.17.21",
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# @navikt/ds-react
|
||||
|
||||
## 5.9.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- :bug: Datepicker lukker ikke lenger modalen den er i ([#2451](https://github.com/navikt/aksel/pull/2451))
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.9.2
|
||||
- @navikt/aksel-icons@5.9.2
|
||||
|
||||
## 5.9.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @navikt/ds-tokens@5.9.1
|
||||
- @navikt/aksel-icons@5.9.1
|
||||
|
||||
## 5.9.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-react",
|
||||
"version": "5.9.0",
|
||||
"version": "5.9.2",
|
||||
"description": "Aksel react-components for NAV designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"license": "MIT",
|
||||
@@ -38,8 +38,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/react": "0.25.4",
|
||||
"@navikt/aksel-icons": "^5.9.0",
|
||||
"@navikt/ds-tokens": "^5.9.0",
|
||||
"@navikt/aksel-icons": "^5.9.2",
|
||||
"@navikt/ds-tokens": "^5.9.2",
|
||||
"@radix-ui/react-tabs": "1.0.0",
|
||||
"@radix-ui/react-toggle-group": "1.0.0",
|
||||
"clsx": "^1.2.1",
|
||||
|
||||
@@ -437,28 +437,36 @@ export const ModalDemo = () => {
|
||||
toDate: new Date("Feb 23 2024"),
|
||||
onDateChange: console.log,
|
||||
});
|
||||
const [open, setOpen] = useState(true);
|
||||
|
||||
return (
|
||||
<Modal open header={{ heading: "Modal-demo" }}>
|
||||
<Modal.Body style={{ position: "relative" }}>
|
||||
<BodyLong spacing>
|
||||
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
|
||||
</BodyLong>
|
||||
<>
|
||||
<Button onClick={() => setOpen(!open)}>Open modal</Button>
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
header={{ heading: "Modal-demo" }}
|
||||
>
|
||||
<Modal.Body style={{ position: "relative" }}>
|
||||
<BodyLong spacing>
|
||||
Lorem ipsum dolor sit, amet consectetur adipisicing elit.
|
||||
</BodyLong>
|
||||
|
||||
<DatePicker {...datepickerProps} dropdownCaption>
|
||||
<DatePicker.Input
|
||||
{...inputProps}
|
||||
label="Velg dato"
|
||||
description="Format: dd.mm.yyyy"
|
||||
/>
|
||||
</DatePicker>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button>Neste</Button>
|
||||
<Button variant="secondary">Tilbake</Button>
|
||||
<Button variant="tertiary">Avbryt</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
<DatePicker {...datepickerProps} dropdownCaption>
|
||||
<DatePicker.Input
|
||||
{...inputProps}
|
||||
label="Velg dato"
|
||||
description="Format: dd.mm.yyyy"
|
||||
/>
|
||||
</DatePicker>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button>Neste</Button>
|
||||
<Button variant="secondary">Tilbake</Button>
|
||||
<Button variant="tertiary">Avbryt</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
ModalDemo.parameters = { chromatic: { pauseAnimationAtEnd: true } };
|
||||
@@ -57,7 +57,10 @@ export const DateWrapper = ({
|
||||
<Modal
|
||||
ref={modalRef}
|
||||
open={open}
|
||||
onClose={onClose}
|
||||
onClose={(event) => {
|
||||
event.stopPropagation();
|
||||
onClose();
|
||||
}}
|
||||
aria-label={modalLabel(locale, variant)}
|
||||
className={cl("navds-date__modal", {
|
||||
"navds-date__nested-modal": isInModal,
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
import { FileIcon } from "@navikt/aksel-icons";
|
||||
import { Meta, StoryFn } from "@storybook/react";
|
||||
import React, { useRef, useState } from "react";
|
||||
import { BodyLong, Button, Heading, Tooltip } from "..";
|
||||
import Modal from "./Modal";
|
||||
|
||||
export default {
|
||||
const meta: Meta<typeof Modal> = {
|
||||
title: "ds-react/Modal",
|
||||
component: Modal,
|
||||
parameters: {
|
||||
chromatic: { pauseAnimationAtEnd: true },
|
||||
},
|
||||
};
|
||||
export default meta;
|
||||
|
||||
export const WithUseRef = () => {
|
||||
export const WithUseRef: StoryFn = () => {
|
||||
const ref = useRef<HTMLDialogElement>(null);
|
||||
const ref2 = useRef<HTMLDialogElement>(null);
|
||||
|
||||
@@ -87,7 +89,7 @@ export const WithUseRef = () => {
|
||||
};
|
||||
WithUseRef.storyName = "With useRef";
|
||||
|
||||
export const WithUseState = () => {
|
||||
export const WithUseState: StoryFn = () => {
|
||||
const [open, setOpen] = useState(true);
|
||||
const [open2, setOpen2] = useState(false);
|
||||
|
||||
@@ -140,36 +142,43 @@ export const WithUseState = () => {
|
||||
};
|
||||
WithUseState.storyName = "With useState";
|
||||
|
||||
export const EmptyHeader = () => (
|
||||
<div style={{ minWidth: "800px", minHeight: "600px" } /* For Chromatic */}>
|
||||
<Modal open>
|
||||
<Modal.Header />
|
||||
<Modal.Body>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
|
||||
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
||||
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
|
||||
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
|
||||
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
|
||||
mollit anim id est laborum.
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</div>
|
||||
export const EmptyHeader: StoryFn = () => (
|
||||
<Modal open>
|
||||
<Modal.Header />
|
||||
<Modal.Body>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
|
||||
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
|
||||
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
|
||||
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
|
||||
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat
|
||||
cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id
|
||||
est laborum.
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
export const Small = () => (
|
||||
export const Small: StoryFn = () => (
|
||||
<Modal open width="small" header={{ heading: "Simple header" }}>
|
||||
<Modal.Body>Lorem ipsum dolor sit amet.</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
Small.storyName = "Size = Small";
|
||||
|
||||
export const MediumWithPortal = () => (
|
||||
export const MediumWithPortal: StoryFn = () => (
|
||||
<Modal open portal width="medium" header={{ heading: "Simple header" }}>
|
||||
<Modal.Body>Lorem ipsum dolor sit amet.</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
MediumWithPortal.storyName = "Size = Medium (with portal)";
|
||||
|
||||
export const WithTooltip = () => {
|
||||
export const Large800: StoryFn = () => (
|
||||
<Modal open width={800} header={{ heading: "Simple header" }}>
|
||||
<Modal.Body>Lorem ipsum dolor sit amet.</Modal.Body>
|
||||
</Modal>
|
||||
);
|
||||
Large800.storyName = "Size = 800px";
|
||||
|
||||
export const WithTooltip: StoryFn = () => {
|
||||
const ref = useRef<HTMLDialogElement>(null);
|
||||
|
||||
return (
|
||||
@@ -193,3 +202,66 @@ export const WithTooltip = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ChromaticViewportTesting: StoryFn = () => (
|
||||
<div id="modal-story-wrapper" style={{ width: "100vw", height: "100vh" }}>
|
||||
<style>{`#storybook-root { padding: 0 !important }`}</style>
|
||||
<Modal
|
||||
open
|
||||
header={{ heading: "Chromatic Viewports Testing", label: "Test" }}
|
||||
>
|
||||
<Modal.Body>
|
||||
<BodyLong spacing>
|
||||
This story is tailored for testing the breakpoints with Chromatic.
|
||||
</BodyLong>
|
||||
<BodyLong spacing>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
|
||||
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
|
||||
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
||||
aliquip ex ea commodo consequat.
|
||||
</BodyLong>
|
||||
<BodyLong spacing>
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
||||
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt mollit anim id est
|
||||
laborum.
|
||||
</BodyLong>
|
||||
<BodyLong>
|
||||
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
|
||||
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae
|
||||
ab illo inventore veritatis et quasi architecto beatae vitae dicta
|
||||
sunt explicabo.
|
||||
</BodyLong>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button>Primary</Button>
|
||||
<Button variant="secondary">Secondary</Button>
|
||||
<Button variant="tertiary">Tertiary</Button>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
ChromaticViewportTesting.parameters = {
|
||||
chromatic: {
|
||||
modes: {
|
||||
mobile_portrait: {
|
||||
viewport: {
|
||||
width: 400,
|
||||
height: 850,
|
||||
},
|
||||
},
|
||||
mobile_landscape: {
|
||||
viewport: {
|
||||
width: 850,
|
||||
height: 400,
|
||||
},
|
||||
},
|
||||
desktop: {
|
||||
viewport: {
|
||||
width: 1280,
|
||||
height: 960,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,5 +1,9 @@
|
||||
# @navikt/ds-tailwind
|
||||
|
||||
## 5.9.2
|
||||
|
||||
## 5.9.1
|
||||
|
||||
## 5.9.0
|
||||
|
||||
## 5.8.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tailwind",
|
||||
"version": "5.9.0",
|
||||
"version": "5.9.2",
|
||||
"description": "Tailwind config based on @navikt/ds-tokens",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"keywords": [
|
||||
@@ -22,7 +22,7 @@
|
||||
"directory": "@navikt/core/tailwind"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@navikt/ds-tokens": "^5.9.0",
|
||||
"@navikt/ds-tokens": "^5.9.2",
|
||||
"@types/jest": "^29.0.0",
|
||||
"color": "4.2.3",
|
||||
"jest": "^29.0.0",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
# @navikt/ds-tokens
|
||||
|
||||
## 5.9.2
|
||||
|
||||
## 5.9.1
|
||||
|
||||
## 5.9.0
|
||||
|
||||
## 5.8.0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@navikt/ds-tokens",
|
||||
"version": "5.9.0",
|
||||
"version": "5.9.2",
|
||||
"description": "Design-tokens for NAV designsystem",
|
||||
"author": "Aksel | NAV designsystem team",
|
||||
"keywords": [
|
||||
|
||||
+268
-256
File diff suppressed because it is too large.
Load diff
@@ -15,11 +15,11 @@
|
||||
"website"
|
||||
],
|
||||
"dependencies": {
|
||||
"@navikt/aksel-icons": "^5.9.0",
|
||||
"@navikt/ds-css": "^5.9.0",
|
||||
"@navikt/ds-react": "^5.9.0",
|
||||
"@navikt/ds-tailwind": "^5.9.0",
|
||||
"@navikt/ds-tokens": "^5.9.0"
|
||||
"@navikt/aksel-icons": "^5.9.2",
|
||||
"@navikt/ds-css": "^5.9.2",
|
||||
"@navikt/ds-react": "^5.9.2",
|
||||
"@navikt/ds-tailwind": "^5.9.2",
|
||||
"@navikt/ds-tokens": "^5.9.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"prettier-plugin-tailwindcss": "^0.2.3"
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { StorybookConfig } from "@storybook/nextjs";
|
||||
|
||||
import { readFileSync } from "fs";
|
||||
import { join, dirname } from "path";
|
||||
import { loadCsf } from "@storybook/csf-tools";
|
||||
import type { StorybookConfig } from "@storybook/nextjs";
|
||||
import { readFileSync } from "fs";
|
||||
import { dirname, join } from "path";
|
||||
|
||||
/**
|
||||
* This function is used to resolve the absolute path of a package.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { WithSidebar } from "./WithSidebar";
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
import { getBlocks } from "@/sb-util";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { WithSidebar } from "./WithSidebar";
|
||||
|
||||
const meta = {
|
||||
title: "Layout/WithSidebar",
|
||||
@@ -28,8 +28,10 @@ export const KomponenterLanding: Story = {
|
||||
args: {
|
||||
children,
|
||||
pageType: {
|
||||
type: "Komponenter",
|
||||
type: "komponenter",
|
||||
title: "Heading",
|
||||
rootUrl: "/komponenter",
|
||||
rootTitle: "Komponenter",
|
||||
},
|
||||
pageProps: { content: "1" },
|
||||
variant: "landingPage",
|
||||
@@ -65,8 +67,10 @@ export const Komponenter: Story = {
|
||||
args: {
|
||||
children,
|
||||
pageType: {
|
||||
type: "Komponenter",
|
||||
type: "komponenter",
|
||||
title: "Heading",
|
||||
rootUrl: "/komponenter",
|
||||
rootTitle: "Komponenter",
|
||||
},
|
||||
pageProps: { content: "1" },
|
||||
variant: "page",
|
||||
|
||||
@@ -20,8 +20,10 @@ export const WithSidebar = ({
|
||||
children: React.ReactNode;
|
||||
sidebar: AkselSidebarT;
|
||||
pageType: {
|
||||
type: "Komponenter" | "Grunnleggende";
|
||||
type: "komponenter" | "grunnleggende" | "templates";
|
||||
title: string;
|
||||
rootUrl: string;
|
||||
rootTitle: string;
|
||||
};
|
||||
pageProps: any;
|
||||
intro?: React.ReactNode;
|
||||
@@ -29,7 +31,11 @@ export const WithSidebar = ({
|
||||
variant?: "page" | "landingPage";
|
||||
}) => {
|
||||
return (
|
||||
<Box background="bg-default" paddingBlock="6 24">
|
||||
<Box
|
||||
background="bg-default"
|
||||
paddingBlock="6 24"
|
||||
className="min-h-screen-header"
|
||||
>
|
||||
<div className="mx-auto flex w-full max-w-screen-2xl gap-6">
|
||||
<Sidebar kategori={pageType.type} links={sidebar} />
|
||||
<main
|
||||
@@ -52,13 +58,9 @@ export const WithSidebar = ({
|
||||
<div className="z-[1]">
|
||||
{variant === "page" && pageProps?.kategori && (
|
||||
<Detail as="div" className="mb-2">
|
||||
<NextLink
|
||||
href={`/${pageType.type.toLowerCase()}`}
|
||||
passHref
|
||||
legacyBehavior
|
||||
>
|
||||
<NextLink href={pageType.rootUrl} passHref legacyBehavior>
|
||||
<Link className="text-text-default">
|
||||
{capitalize(pageType.type)}
|
||||
{pageType.rootTitle}
|
||||
</Link>
|
||||
</NextLink>{" "}
|
||||
/ {capitalize(pageProps.kategori)}
|
||||
|
||||
@@ -95,6 +95,7 @@ describe("createSearchResult", () => {
|
||||
aksel_blogg: 1,
|
||||
aksel_prinsipp: 1,
|
||||
aksel_standalone: 1,
|
||||
templates_artikkel: 0,
|
||||
};
|
||||
const actual: SearchResultsT = createSearchResult(result, rawResults);
|
||||
expect(actual.hits).toEqual(expected);
|
||||
|
||||
@@ -29,6 +29,9 @@ export function createSearchResult(
|
||||
.length,
|
||||
aksel_blogg: rawResults.filter((x: any) => x.item._type === "aksel_blogg")
|
||||
.length,
|
||||
templates_artikkel: rawResults.filter(
|
||||
(x: any) => x.item._type === "templates_artikkel"
|
||||
).length,
|
||||
aksel_prinsipp: rawResults.filter(
|
||||
(x: any) => x.item._type === "aksel_prinsipp"
|
||||
).length,
|
||||
|
||||
@@ -114,7 +114,7 @@ export const Sidebar = ({
|
||||
kategori,
|
||||
links,
|
||||
}: {
|
||||
kategori: "Komponenter" | "Grunnleggende";
|
||||
kategori: "komponenter" | "grunnleggende" | "templates";
|
||||
links: AkselSidebarT;
|
||||
}) => {
|
||||
const sections = useSection({ kategori, links });
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
import { AkselSidebarT } from "@/types";
|
||||
import { useMemo } from "react";
|
||||
import {
|
||||
grunnleggendeKategorier,
|
||||
komponentKategorier,
|
||||
} from "../../../sanity/config";
|
||||
import { sanityCategoryLookup } from "../../../sanity/config";
|
||||
|
||||
export const useSection = ({
|
||||
kategori,
|
||||
links,
|
||||
}: {
|
||||
kategori: "Komponenter" | "Grunnleggende";
|
||||
kategori: "komponenter" | "grunnleggende" | "templates";
|
||||
links: AkselSidebarT;
|
||||
}) => {
|
||||
const sections = useMemo(
|
||||
() =>
|
||||
(kategori === "Komponenter"
|
||||
? komponentKategorier
|
||||
: grunnleggendeKategorier
|
||||
)
|
||||
sanityCategoryLookup(kategori)
|
||||
.map((x) => ({
|
||||
...x,
|
||||
pages: links
|
||||
|
||||
@@ -15,8 +15,10 @@ export const Designsystem: Story = {
|
||||
args: {
|
||||
node: {
|
||||
title: "button",
|
||||
|
||||
dir: {
|
||||
title: "button",
|
||||
variant: "templates",
|
||||
filer: [
|
||||
{
|
||||
_key: getKey(),
|
||||
@@ -24,6 +26,7 @@ export const Designsystem: Story = {
|
||||
innhold:
|
||||
'import { Button } from "@navikt/ds-react";\n\nconst Example = () => {\n return (\n <div className="flex flex-wrap gap-2">\n <Button variant="primary">Primary</Button>\n <Button variant="secondary">Secondary</Button>\n <Button variant="tertiary">Tertiary</Button>\n <Button variant="danger">Danger</Button>\n </div>\n );\n};',
|
||||
navn: "default",
|
||||
index: 1,
|
||||
},
|
||||
{
|
||||
_key: getKey(),
|
||||
@@ -31,6 +34,7 @@ export const Designsystem: Story = {
|
||||
innhold:
|
||||
'import { Button } from "@navikt/ds-react";\n\nconst Example = () => {\n return (\n <div className="flex flex-wrap gap-2">\n <Button variant="primary-neutral">Primary</Button>\n <Button variant="secondary-neutral">Secondary</Button>\n <Button variant="tertiary-neutral">Tertiary</Button>\n </div>\n );\n};',
|
||||
navn: "neutral",
|
||||
index: 1,
|
||||
},
|
||||
{
|
||||
_key: getKey(),
|
||||
@@ -38,6 +42,7 @@ export const Designsystem: Story = {
|
||||
innhold:
|
||||
'import { PencilIcon } from "@navikt/aksel-icons";\nimport { Button } from "@navikt/ds-react";\n\nconst Example = () => {\n return (\n <div className="flex flex-wrap gap-2">\n <Button size="small" variant="primary" icon={<PencilIcon aria-hidden />}>\n Primary\n </Button>\n <Button size="small" variant="secondary">\n Secondary\n </Button>\n <Button size="small" variant="tertiary">\n Tertiary\n </Button>\n <Button size="small" variant="danger">\n Danger\n </Button>\n </div>\n );\n};',
|
||||
navn: "small",
|
||||
index: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -75,7 +75,7 @@ const ComponentExamples = ({ node }: CodeExamplesProps) => {
|
||||
const fixName = (str: string) =>
|
||||
capitalize(
|
||||
str
|
||||
.replace(/[^\w]|_/g, " ")
|
||||
.replace(/[^\wæøå]|_/g, " ")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim()
|
||||
) ?? str;
|
||||
|
||||
+1
@@ -43,6 +43,7 @@ const Card = ({ article, visible, index }: CardProps) => {
|
||||
"ds_artikkel",
|
||||
"komponent_artikkel",
|
||||
"aksel_blogg",
|
||||
"templates_artikkel",
|
||||
].includes(article._type);
|
||||
|
||||
return (
|
||||
|
||||
+21
-2
@@ -1,4 +1,4 @@
|
||||
import { Heading, Label, Tag as DsTag } from "@navikt/ds-react";
|
||||
import { Tag as DsTag, Heading, Label } from "@navikt/ds-react";
|
||||
import cl from "clsx";
|
||||
|
||||
export const Tag = ({
|
||||
@@ -65,7 +65,26 @@ export const Tag = ({
|
||||
<Comp className="text-deepblue-600 flex items-center gap-3">
|
||||
Grunnleggende
|
||||
{beta && (
|
||||
<DsTag variant="alt1" size="small">
|
||||
<DsTag
|
||||
variant="alt1"
|
||||
size="small"
|
||||
className="border-violet-300 bg-violet-50"
|
||||
>
|
||||
Beta
|
||||
</DsTag>
|
||||
)}
|
||||
</Comp>
|
||||
);
|
||||
case "templates_artikkel":
|
||||
return (
|
||||
<Comp className="text-deepblue-600 flex items-center gap-3">
|
||||
Mønster og Maler
|
||||
{beta && (
|
||||
<DsTag
|
||||
variant="alt1"
|
||||
size="small"
|
||||
className="border-violet-300 bg-violet-50"
|
||||
>
|
||||
Beta
|
||||
</DsTag>
|
||||
)}
|
||||
|
||||
@@ -29,10 +29,11 @@ const useAmplitudeInit = () => {
|
||||
useEffect(() => {
|
||||
const isProdUrl = () => window.location.host === "aksel.nav.no";
|
||||
const isExample = () => window.location.pathname.includes("eksempler/");
|
||||
const isTemplate = () => window.location.pathname.includes("templates/");
|
||||
const isPreview = () => !!document.getElementById("exit-preview-id");
|
||||
|
||||
const initAmplitude = async () => {
|
||||
if (isExample()) {
|
||||
if (isExample() || isTemplate()) {
|
||||
return;
|
||||
} else if (!isProdUrl()) {
|
||||
mockAmplitude();
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"e2e:ci-full": "ts-node ./e2e/genUrls.ts && FULL_TEST=true yarn start-server-and-test start http://localhost:3000 playwright",
|
||||
"update:props": "ts-node --project tsconfig.tsnode.json ./scripts/update-props",
|
||||
"update:tokens": "ts-node --project tsconfig.tsnode.json ./scripts/update-tokens",
|
||||
"update:eksempler": "ts-node --project tsconfig.tsnode.json ./scripts/examples/update-sanity",
|
||||
"update:eksempler": "ts-node --project tsconfig.tsnode.json ./scripts/update-examples/update-sanity",
|
||||
"update:changelog": "ts-node --project tsconfig.tsnode.json ./scripts/changelog",
|
||||
"update:sanity": "yarn update:tokens && yarn update:props && yarn update:eksempler && yarn update:changelog",
|
||||
"analyze": "cross-env ANALYZE=true yarn build",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
import { createClient } from "next-sanity";
|
||||
import { clientConfig } from "../../sanity/config";
|
||||
import type { NextApiRequest, NextApiResponse } from "next";
|
||||
|
||||
const previewClient = createClient({
|
||||
...clientConfig,
|
||||
@@ -23,6 +23,7 @@ const landingPages = [
|
||||
"god-praksis",
|
||||
"produktbloggen",
|
||||
"prinsipper",
|
||||
"monster-maler",
|
||||
];
|
||||
|
||||
export default async function preview(
|
||||
|
||||
@@ -40,7 +40,7 @@ export const query = `{
|
||||
${destructureBlocks}
|
||||
},
|
||||
},
|
||||
"seo": *[_type == "komponenter_landingsside"][0].seo.image,
|
||||
"seo": *[_type == "grunnleggende_landingsside"][0].seo.image,
|
||||
${sidebarQuery}
|
||||
}`;
|
||||
|
||||
@@ -102,7 +102,12 @@ const Page = ({ page, sidebar, seo, publishDate }: PageProps["props"]) => {
|
||||
<Header />
|
||||
<WithSidebar
|
||||
sidebar={sidebar}
|
||||
pageType={{ type: "Grunnleggende", title: page?.heading }}
|
||||
pageType={{
|
||||
type: "grunnleggende",
|
||||
title: page?.heading,
|
||||
rootUrl: "/grunnleggende",
|
||||
rootTitle: "Grunnleggende",
|
||||
}}
|
||||
intro={
|
||||
<Detail as="div">
|
||||
<div className="mt-2 flex flex-wrap items-center gap-3">
|
||||
|
||||
@@ -62,7 +62,12 @@ const Page = ({ page, sidebar, links }: PageProps["props"]) => {
|
||||
<Header />
|
||||
<WithSidebar
|
||||
sidebar={sidebar}
|
||||
pageType={{ type: "Grunnleggende", title: "Grunnleggende" }}
|
||||
pageType={{
|
||||
type: "grunnleggende",
|
||||
title: "Grunnleggende",
|
||||
rootUrl: "/grunnleggende",
|
||||
rootTitle: "Grunnleggende",
|
||||
}}
|
||||
intro={<Ingress className="text-text-on-action">{page?.intro}</Ingress>}
|
||||
pageProps={page}
|
||||
>
|
||||
|
||||
@@ -97,7 +97,7 @@ export const query = `*[_type == "aksel_forside"][0]{
|
||||
seo,
|
||||
${contributorsAll}
|
||||
},
|
||||
"komponenter": *[_type in ["komponent_artikkel", "ds_artikkel"] && defined(publishedAt) && !(_id in ^.highlights[]._ref)] | order(publishedAt desc)[0...3]{
|
||||
"komponenter": *[_type in ["komponent_artikkel", "ds_artikkel", "templates_artikkel"] && defined(publishedAt) && !(_id in ^.highlights[]._ref)] | order(publishedAt desc)[0...3]{
|
||||
_type,
|
||||
_id,
|
||||
heading,
|
||||
|
||||
@@ -261,7 +261,12 @@ const Page = ({
|
||||
<Header />
|
||||
<WithSidebar
|
||||
sidebar={sidebar}
|
||||
pageType={{ type: "Komponenter", title: page?.heading }}
|
||||
pageType={{
|
||||
type: "komponenter",
|
||||
title: page?.heading,
|
||||
rootUrl: "/komponenter",
|
||||
rootTitle: "Komponenter",
|
||||
}}
|
||||
pageProps={page}
|
||||
variant="page"
|
||||
intro={
|
||||
|
||||
@@ -74,7 +74,12 @@ const Page = ({ page, sidebar, links }: PageProps["props"]) => {
|
||||
<Header />
|
||||
<WithSidebar
|
||||
sidebar={sidebar}
|
||||
pageType={{ type: "Komponenter", title: "Komponenter" }}
|
||||
pageType={{
|
||||
type: "komponenter",
|
||||
title: "Komponenter",
|
||||
rootUrl: "/komponenter",
|
||||
rootTitle: "Komponenter",
|
||||
}}
|
||||
intro={
|
||||
<Ingress className="text-text-on-action">
|
||||
{page?.intro}
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
import { dateStr } from "@/components";
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
import { getClient } from "@/sanity/client.server";
|
||||
import { getDocumentsTmp } from "@/sanity/interface";
|
||||
import { destructureBlocks, sidebarQuery } from "@/sanity/queries";
|
||||
import {
|
||||
AkselSidebarT,
|
||||
AkselTemplatesDocT,
|
||||
ArticleListT,
|
||||
CodeExampleSchemaT,
|
||||
NextPageT,
|
||||
ResolveContributorsT,
|
||||
ResolveSlugT,
|
||||
} from "@/types";
|
||||
import { Detail, Heading } from "@navikt/ds-react";
|
||||
import { WithSidebar } from "components/layout/WithSidebar";
|
||||
import Footer from "components/layout/footer/Footer";
|
||||
import { Header } from "components/layout/header/Header";
|
||||
import IntroSeksjon from "components/sanity-modules/intro-seksjon/IntroSeksjon";
|
||||
import { StatusTag } from "components/website-modules/StatusTag";
|
||||
import { AkselTable, AkselTableRow } from "components/website-modules/Table";
|
||||
import { SEO } from "components/website-modules/seo/SEO";
|
||||
import { GetStaticPaths, GetStaticProps } from "next/types";
|
||||
import { Suspense, lazy } from "react";
|
||||
import NotFotfund from "../404";
|
||||
|
||||
type PageProps = NextPageT<{
|
||||
page: ResolveContributorsT<ResolveSlugT<AkselTemplatesDocT>>;
|
||||
sidebar: AkselSidebarT;
|
||||
seo: any;
|
||||
refs: ArticleListT;
|
||||
publishDate: string;
|
||||
}>;
|
||||
|
||||
const query = `{
|
||||
"page": *[_type == "templates_artikkel" && slug.current == $slug] | order(_updatedAt desc)[0]
|
||||
{
|
||||
...,
|
||||
"slug": slug.current,
|
||||
content[]{
|
||||
...,
|
||||
${destructureBlocks}
|
||||
},
|
||||
},
|
||||
"seo": *[_type == "templates_landingsside"][0].seo.image,
|
||||
${sidebarQuery}
|
||||
}`;
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
return {
|
||||
paths: await getDocumentsTmp("templates_artikkel").then((paths) =>
|
||||
paths.map((slug) => ({
|
||||
params: {
|
||||
slug: slug.split("/").filter((x) => x !== "monster-maler"),
|
||||
},
|
||||
}))
|
||||
),
|
||||
fallback: "blocking",
|
||||
};
|
||||
};
|
||||
|
||||
export const getStaticProps: GetStaticProps = async ({
|
||||
params: { slug },
|
||||
preview = false,
|
||||
}: {
|
||||
params: { slug: string[] };
|
||||
preview?: boolean;
|
||||
}): Promise<PageProps> => {
|
||||
const { page, sidebar, seo } = await getClient().fetch(query, {
|
||||
slug: `monster-maler/${slug.slice(0, 2).join("/")}`,
|
||||
type: "templates_artikkel",
|
||||
});
|
||||
|
||||
return {
|
||||
props: {
|
||||
page,
|
||||
slug: slug.slice(0, 2).join("/"),
|
||||
seo,
|
||||
sidebar,
|
||||
preview,
|
||||
title: page?.heading ?? "",
|
||||
id: page?._id ?? "",
|
||||
refs: [],
|
||||
publishDate: await dateStr(page?._updatedAt ?? page?._createdAt),
|
||||
},
|
||||
notFound: !page && !preview,
|
||||
revalidate: 60,
|
||||
};
|
||||
};
|
||||
|
||||
const Page = ({ page, sidebar, seo, publishDate }: PageProps["props"]) => {
|
||||
if (!page) {
|
||||
return <NotFotfund />;
|
||||
}
|
||||
|
||||
const metadata: CodeExampleSchemaT["metadata"] = page.content.find(
|
||||
(x) => x._type === "kode_eksempler"
|
||||
)?.dir?.metadata;
|
||||
|
||||
return (
|
||||
<>
|
||||
<SEO
|
||||
title={page?.heading}
|
||||
description={page?.seo?.meta}
|
||||
image={page?.seo?.image ?? seo}
|
||||
/>
|
||||
|
||||
<Header />
|
||||
<WithSidebar
|
||||
sidebar={sidebar}
|
||||
pageType={{
|
||||
type: "templates",
|
||||
title: page?.heading,
|
||||
rootUrl: "/monster-maler",
|
||||
rootTitle: "Mønster og Maler",
|
||||
}}
|
||||
intro={
|
||||
<Detail as="div">
|
||||
<div className="mt-2 flex flex-wrap items-center gap-3">
|
||||
<span>
|
||||
Oppdatert <time>{publishDate}</time>
|
||||
</span>
|
||||
<StatusTag showStable status={page?.status?.tag} />
|
||||
</div>
|
||||
</Detail>
|
||||
}
|
||||
pageProps={page}
|
||||
variant="page"
|
||||
>
|
||||
<IntroSeksjon node={page?.intro} />
|
||||
<SanityBlockContent blocks={page["content"]} />
|
||||
|
||||
{metadata && metadata.changelog && (
|
||||
<>
|
||||
<Heading
|
||||
tabIndex={-1}
|
||||
id="changelog"
|
||||
level="2"
|
||||
size="large"
|
||||
className="max-w-text text-deepblue-800 mb-4 mt-12 scroll-mt-20 focus:outline-none"
|
||||
>
|
||||
Endringer
|
||||
</Heading>
|
||||
<AkselTable
|
||||
th={[
|
||||
{ text: "Dato" },
|
||||
{ text: "Versjon" },
|
||||
{ text: "Endringer" },
|
||||
]}
|
||||
>
|
||||
{metadata.changelog
|
||||
.sort((a, b) => a.version - b.version)
|
||||
.map((log) => (
|
||||
<AkselTableRow
|
||||
key={log.version}
|
||||
tr={[
|
||||
{ text: log.date },
|
||||
{ text: log.version },
|
||||
{ text: log.description },
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
</AkselTable>
|
||||
</>
|
||||
)}
|
||||
</WithSidebar>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const WithPreview = lazy(() => import("../../components/WithPreview"));
|
||||
|
||||
const Wrapper = (props: any) => {
|
||||
if (props?.preview) {
|
||||
return (
|
||||
<Suspense fallback={<Page {...props} />}>
|
||||
<WithPreview
|
||||
comp={Page}
|
||||
query={query}
|
||||
params={{
|
||||
slug: `monster-maler/${props.slug}`,
|
||||
type: "templates_artikkel",
|
||||
}}
|
||||
props={props}
|
||||
/>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
return <Page {...props} />;
|
||||
};
|
||||
|
||||
export default Wrapper;
|
||||
@@ -0,0 +1,138 @@
|
||||
import { SanityBlockContent } from "@/sanity-block";
|
||||
import { getClient } from "@/sanity/client.server";
|
||||
import { landingPageQuery, sidebarQuery } from "@/sanity/queries";
|
||||
import {
|
||||
AkselLandingPageDocT,
|
||||
AkselSidebarT,
|
||||
ArticleListT,
|
||||
NextPageT,
|
||||
} from "@/types";
|
||||
import { BodyLong, Heading } from "@navikt/ds-react";
|
||||
import cl from "clsx";
|
||||
import { WithSidebar } from "components/layout/WithSidebar";
|
||||
import Footer from "components/layout/footer/Footer";
|
||||
import { Header } from "components/layout/header/Header";
|
||||
import ComponentOverview from "components/sanity-modules/component-overview/ComponentOverview";
|
||||
import { SEO } from "components/website-modules/seo/SEO";
|
||||
import { GetStaticProps } from "next/types";
|
||||
import { Suspense, lazy } from "react";
|
||||
import { templatesKategorier } from "../../sanity/config";
|
||||
|
||||
type PageProps = NextPageT<{
|
||||
page: AkselLandingPageDocT;
|
||||
sidebar: AkselSidebarT;
|
||||
links: ArticleListT;
|
||||
}>;
|
||||
|
||||
export const query = `{${sidebarQuery}, ${landingPageQuery(
|
||||
"templates"
|
||||
)}, "links": *[_type == "templates_artikkel" && defined(kategori)]{_id,heading,"slug": slug,status,kategori,"sidebarindex": sidebarindex}}`;
|
||||
|
||||
export const getStaticProps: GetStaticProps = async ({
|
||||
preview = false,
|
||||
}): Promise<PageProps> => {
|
||||
const { sidebar, page, links } = await getClient().fetch(query, {
|
||||
type: "templates_artikkel",
|
||||
});
|
||||
|
||||
return {
|
||||
props: {
|
||||
page,
|
||||
sidebar,
|
||||
links,
|
||||
slug: "/monster-maler",
|
||||
preview,
|
||||
title: "Forside Mønster og Maler",
|
||||
id: page?._id ?? "",
|
||||
},
|
||||
revalidate: 60,
|
||||
notFound: false,
|
||||
};
|
||||
};
|
||||
|
||||
const Page = ({ page, sidebar, links }: PageProps["props"]) => {
|
||||
return (
|
||||
<>
|
||||
<SEO
|
||||
title="Mønster og Maler"
|
||||
description={page?.seo?.meta}
|
||||
image={page?.seo?.image}
|
||||
/>
|
||||
|
||||
<Header />
|
||||
<WithSidebar
|
||||
sidebar={sidebar}
|
||||
pageType={{
|
||||
type: "templates",
|
||||
title: "Mønster og Maler",
|
||||
rootUrl: "/monster-maler",
|
||||
rootTitle: "Mønster og Maler",
|
||||
}}
|
||||
intro={
|
||||
<BodyLong size="large" className="text-text-on-action">
|
||||
{page?.intro}
|
||||
</BodyLong>
|
||||
}
|
||||
pageProps={page}
|
||||
>
|
||||
{templatesKategorier
|
||||
.filter(
|
||||
(kat) => links?.filter((x) => x.kategori === kat.value).length > 0
|
||||
)
|
||||
.map((kat, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={cl({ "pb-8": i + 1 < templatesKategorier.length })}
|
||||
>
|
||||
<Heading
|
||||
level="2"
|
||||
size="large"
|
||||
spacing
|
||||
className="text-deepblue-800 scoll-mt-20"
|
||||
id={kat.value}
|
||||
>
|
||||
{kat.title}
|
||||
</Heading>
|
||||
<div>
|
||||
{page?.[`ingress_${kat.value}`] && (
|
||||
<BodyLong size="large" className="mb-4 only:mb-7">
|
||||
{page[`ingress_${kat.value}`]}
|
||||
</BodyLong>
|
||||
)}
|
||||
{page?.[`intro_${kat.value}`] && (
|
||||
<SanityBlockContent blocks={page[`intro_${kat.value}`]} />
|
||||
)}
|
||||
</div>
|
||||
<ComponentOverview
|
||||
node={links.filter((x) => x.kategori === kat.value)}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</WithSidebar>
|
||||
<Footer />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const WithPreview = lazy(() => import("../../components/WithPreview"));
|
||||
|
||||
const Wrapper = (props: any) => {
|
||||
if (props?.preview) {
|
||||
return (
|
||||
<Suspense fallback={<Page {...props} />}>
|
||||
<WithPreview
|
||||
comp={Page}
|
||||
query={query}
|
||||
props={props}
|
||||
params={{
|
||||
type: "templates_artikkel",
|
||||
}}
|
||||
/>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
return <Page {...props} />;
|
||||
};
|
||||
|
||||
export default Wrapper;
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": 1,
|
||||
"changelog": [
|
||||
{
|
||||
"description": "Oppdaterte X Y og Z",
|
||||
"date": "31.10.2023",
|
||||
"version": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { VStack } from "@navikt/ds-react";
|
||||
|
||||
export default function Example() {
|
||||
const lorem =
|
||||
"Hvis du ikke bor sammen med begge foreldrene dine, kan du ha rett til barnebidrag fra en eller begge foreldre mens du fullfører videregående skole eller tilsvarende.";
|
||||
|
||||
return <VStack gap="4">{lorem}</VStack>;
|
||||
}
|
||||
|
||||
export const args = {
|
||||
index: 1,
|
||||
title: "Med søk",
|
||||
desc: "abc",
|
||||
};
|
||||
@@ -12,6 +12,7 @@ export const allArticleDocuments = [
|
||||
"aksel_blogg",
|
||||
"aksel_prinsipp",
|
||||
"aksel_standalone",
|
||||
"templates_artikkel",
|
||||
] as const;
|
||||
|
||||
export const previews = [
|
||||
@@ -21,12 +22,14 @@ export const previews = [
|
||||
"aksel_blogg",
|
||||
"aksel_prinsipp",
|
||||
"aksel_standalone",
|
||||
"templates_artikkel",
|
||||
];
|
||||
|
||||
export const landingsider = [
|
||||
{ name: "godpraksis_landingsside", url: "god-praksis" },
|
||||
{ name: "blogg_landingsside", url: "produktbloggen" },
|
||||
{ name: "grunnleggende_landingsside", url: "grunnleggende" },
|
||||
{ name: "templates_landingsside", url: "monster-maler" },
|
||||
{ name: "komponenter_landingsside", url: "komponenter" },
|
||||
{ name: "prinsipper_landingsside", url: "prinsipper" },
|
||||
];
|
||||
@@ -46,7 +49,10 @@ export const grunnleggendeKategorier = [
|
||||
{ title: "Kode", value: "kode" },
|
||||
];
|
||||
|
||||
export const monsterKategorier = [];
|
||||
export const templatesKategorier = [
|
||||
{ title: "Mønster", value: "monster" },
|
||||
{ title: "Maler", value: "maler" },
|
||||
];
|
||||
|
||||
export const bloggKategorier = [
|
||||
{ title: "Nytt fra teamene", value: "nytt-fra-teamene" },
|
||||
@@ -58,19 +64,19 @@ export const prinsippKategorier = [
|
||||
{ title: "Brukeropplevelse", value: "brukeropplevelse" },
|
||||
];
|
||||
|
||||
const allDocumentTypes = [
|
||||
"aksel_artikkel",
|
||||
"aksel_blogg",
|
||||
"aksel_prinsipp",
|
||||
"aksel_standalone",
|
||||
"blogg_landingsside",
|
||||
"ds_artikkel",
|
||||
"godpraksis_landingsside",
|
||||
"grunnleggende_landingsside",
|
||||
"komponent_artikkel",
|
||||
"komponenter_landingsside",
|
||||
"prinsipper_landingsside",
|
||||
"aksel_forside",
|
||||
];
|
||||
export const sanityCategoryLookup = (
|
||||
category: "komponenter" | "grunnleggende" | "templates"
|
||||
) => {
|
||||
const _category = category.toLowerCase();
|
||||
|
||||
export const allDocsRef = allDocumentTypes.map((x) => ({ type: x }));
|
||||
switch (_category) {
|
||||
case "komponenter":
|
||||
return komponentKategorier;
|
||||
case "grunnleggende":
|
||||
return grunnleggendeKategorier;
|
||||
case "templates":
|
||||
return templatesKategorier;
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
};
|
||||
@@ -25,6 +25,7 @@ export async function sitemapPages(
|
||||
"godpraksis": *[_type == "godpraksis_landingsside"][0]._updatedAt,
|
||||
"grunnleggende": *[_type == "grunnleggende_landingsside"][0]._updatedAt,
|
||||
"komponenter": *[_type == "komponenter_landingsside"][0]._updatedAt,
|
||||
"templates": *[_type == "templates_landingsside"][0]._updatedAt,
|
||||
"blogg": *[_type == "blogg_landingsside"][0]._updatedAt,
|
||||
}`
|
||||
);
|
||||
@@ -35,6 +36,7 @@ export async function sitemapPages(
|
||||
{ path: "ikoner", lastmod: undefined },
|
||||
{ path: "grunnleggende", lastmod: pages.grunnleggende },
|
||||
{ path: "komponenter", lastmod: pages.komponenter },
|
||||
{ path: "monster-maler", lastmod: pages.templates },
|
||||
{ path: "produktbloggen", lastmod: pages.blogg },
|
||||
...temaer.map((x) => ({
|
||||
path: `god-praksis/${x.path}`,
|
||||
@@ -61,7 +63,7 @@ export const getAkselDocuments = async (
|
||||
};
|
||||
|
||||
export const getDocumentsTmp = async (
|
||||
source: "komponent_artikkel" | "ds_artikkel",
|
||||
source: "komponent_artikkel" | "ds_artikkel" | "templates_artikkel",
|
||||
token?: string
|
||||
): Promise<string[]> => {
|
||||
const docs = await getDocuments(source, token);
|
||||
@@ -91,6 +93,7 @@ async function getDocuments(
|
||||
| "aksel_blogg"
|
||||
| "aksel_prinsipp"
|
||||
| "aksel_standalone"
|
||||
| "templates_artikkel"
|
||||
| "all",
|
||||
token?: string
|
||||
): Promise<{ slug: string; lastmod: string }[]> {
|
||||
@@ -107,6 +110,7 @@ async function getDocuments(
|
||||
"aksel_blogg",
|
||||
"aksel_prinsipp",
|
||||
"aksel_standalone",
|
||||
"templates_artikkel",
|
||||
]
|
||||
: [source],
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { grunnleggendeKategorier, komponentKategorier } from "../config";
|
||||
import { sanityCategoryLookup } from "../config";
|
||||
|
||||
const markDef = `
|
||||
markDefs[]{
|
||||
@@ -95,7 +95,6 @@ const defaultBlock = `
|
||||
_type == "kode_eksempler" =>{
|
||||
...,
|
||||
dir->,
|
||||
filnavn->,
|
||||
},
|
||||
_type == "kode_ref" => @->,
|
||||
${tips},
|
||||
@@ -185,12 +184,7 @@ export const sidebarQuery = `"sidebar": *[_type == $type && defined(kategori)] {
|
||||
}`;
|
||||
|
||||
export const landingPageQuery = (t) => {
|
||||
const kat =
|
||||
t === "komponenter"
|
||||
? komponentKategorier
|
||||
: t === "grunnleggende"
|
||||
? grunnleggendeKategorier
|
||||
: [];
|
||||
const kat = sanityCategoryLookup(t);
|
||||
|
||||
return `"page": *[_type == "${t}_landingsside"][0]{
|
||||
...,
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
landingsider,
|
||||
previews,
|
||||
prinsippKategorier,
|
||||
templatesKategorier,
|
||||
} from "../../config";
|
||||
import { Iframe } from "./IFrame";
|
||||
|
||||
@@ -18,6 +19,7 @@ import {
|
||||
LightBulbIcon,
|
||||
NewspaperIcon,
|
||||
PencilBoardIcon,
|
||||
RectangleSectionsIcon,
|
||||
TokenIcon,
|
||||
} from "@navikt/aksel-icons";
|
||||
import differenceInMonths from "date-fns/differenceInMonths";
|
||||
@@ -33,6 +35,8 @@ const filtered = [
|
||||
"ds_artikkel",
|
||||
"komponent_artikkel",
|
||||
"grunnleggende_landingsside",
|
||||
"templates_landingsside",
|
||||
"templates_artikkel",
|
||||
"komponenter_landingsside",
|
||||
"media.tag",
|
||||
"editor",
|
||||
@@ -231,6 +235,26 @@ export const structure = async (
|
||||
)),
|
||||
])
|
||||
),
|
||||
S.listItem()
|
||||
.title("Mønster og Maler")
|
||||
.icon(RectangleSectionsIcon)
|
||||
.child(
|
||||
S.list()
|
||||
.title("Mønster og Maler")
|
||||
.items([
|
||||
S.documentListItem()
|
||||
.title(`Landingsside`)
|
||||
.schemaType(`templates_landingsside`)
|
||||
.id(`templates_landingsside_id1`),
|
||||
S.divider(),
|
||||
...(await PanesWithCount(
|
||||
"templates_artikkel",
|
||||
templatesKategorier,
|
||||
getClient,
|
||||
S
|
||||
)),
|
||||
])
|
||||
),
|
||||
S.listItem()
|
||||
.title("Komponenter")
|
||||
.icon(ComponentIcon)
|
||||
@@ -322,7 +346,7 @@ export const structure = async (
|
||||
]) */
|
||||
),
|
||||
S.listItem()
|
||||
.title("Komponent-eksempler Designsystemet")
|
||||
.title("Eksempler/Templates")
|
||||
.child(
|
||||
S.documentList()
|
||||
.title("Eksempler")
|
||||
|
||||
@@ -19,3 +19,5 @@ export * from "./publiseringsflyt";
|
||||
export * from "./redirects";
|
||||
export * from "./skrivehjelp";
|
||||
export * from "./standalone-artikkel";
|
||||
export * from "./templates/artikkel";
|
||||
export * from "./templates/landingsside";
|
||||
@@ -14,13 +14,26 @@ export const KodeEksempelDoc = defineType({
|
||||
validation: (Rule) => Rule.required(),
|
||||
readOnly: true,
|
||||
}),
|
||||
|
||||
defineField({
|
||||
title: "Toggle om eksemplet er et dir eller filnavn",
|
||||
name: "dir",
|
||||
type: "boolean",
|
||||
title: "Variant",
|
||||
name: "variant",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
initialValue: false,
|
||||
readOnly: true,
|
||||
options: {
|
||||
list: [
|
||||
{
|
||||
title: "Eksempler",
|
||||
value: "eksempler",
|
||||
},
|
||||
{
|
||||
title: "Templates",
|
||||
value: "templates",
|
||||
},
|
||||
],
|
||||
layout: "radio",
|
||||
},
|
||||
}),
|
||||
defineField({
|
||||
title: "Filer",
|
||||
@@ -36,21 +49,52 @@ export const KodeEksempelDoc = defineType({
|
||||
{ title: "Filnavn", name: "navn", type: "string" },
|
||||
{ title: "Innhold", name: "innhold", type: "string" },
|
||||
{ title: "Beskrivelse", name: "description", type: "text" },
|
||||
{ title: "Index", name: "index", type: "number" },
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
defineField({
|
||||
title: "Metadata",
|
||||
name: "metadata",
|
||||
type: "object",
|
||||
readOnly: true,
|
||||
fields: [
|
||||
defineField({
|
||||
title: "Version",
|
||||
name: "version",
|
||||
type: "number",
|
||||
}),
|
||||
defineField({
|
||||
title: "Changelog",
|
||||
name: "changelog",
|
||||
type: "array",
|
||||
of: [
|
||||
{
|
||||
title: "Changelog-entry",
|
||||
name: "entry",
|
||||
type: "object",
|
||||
fields: [
|
||||
{ title: "Description", name: "description", type: "string" },
|
||||
{ title: "Version", name: "version", type: "number" },
|
||||
{ title: "Date", name: "date", type: "string" },
|
||||
],
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
title: "title",
|
||||
dir: "dir",
|
||||
variant: "variant",
|
||||
},
|
||||
prepare(selection) {
|
||||
const { title, dir } = selection;
|
||||
const { title, variant } = selection;
|
||||
return {
|
||||
title,
|
||||
subtitle: dir ? "Alle kode-eksempler" : "Spesifikt kode-eksempel",
|
||||
subtitle: variant,
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
import { defineField, defineType } from "sanity";
|
||||
import { templatesKategorier } from "../../../config";
|
||||
import { artikkelPreview } from "../presets/artikkel-preview";
|
||||
import { editorField } from "../presets/editors";
|
||||
import { groups } from "../presets/groups";
|
||||
import { hiddenFields } from "../presets/hidden-fields";
|
||||
import { oppdateringsvarsel } from "../presets/oppdateringsvarsel";
|
||||
import { SEOFields } from "../presets/seo";
|
||||
import { kategoriSlug } from "../presets/slug";
|
||||
import { titleField } from "../presets/title-field";
|
||||
|
||||
const prefix = "monster-maler/";
|
||||
|
||||
export const TemplatesArtikkel = defineType({
|
||||
title: "Mønster/Maler artikkel",
|
||||
name: "templates_artikkel",
|
||||
type: "document",
|
||||
groups,
|
||||
...artikkelPreview("Mønster/Maler"),
|
||||
fields: [
|
||||
oppdateringsvarsel,
|
||||
...hiddenFields,
|
||||
titleField,
|
||||
editorField,
|
||||
defineField({
|
||||
title: "Kategori",
|
||||
name: "kategori",
|
||||
type: "string",
|
||||
validation: (Rule) => Rule.required(),
|
||||
options: {
|
||||
list: templatesKategorier.map((x) => ({
|
||||
title: x.title,
|
||||
value: x.value,
|
||||
})),
|
||||
layout: "radio",
|
||||
},
|
||||
}),
|
||||
kategoriSlug(prefix),
|
||||
defineField({
|
||||
title: "Metadata",
|
||||
name: "status",
|
||||
group: "innhold",
|
||||
type: "object",
|
||||
fields: [
|
||||
{
|
||||
title: "Status",
|
||||
name: "tag",
|
||||
type: "string",
|
||||
initialValue: "new",
|
||||
options: {
|
||||
list: [
|
||||
{ title: "Beta", value: "beta" },
|
||||
{ title: "New", value: "new" },
|
||||
{ title: "Stable", value: "ready" },
|
||||
{ title: "Deprecated", value: "deprecated" },
|
||||
],
|
||||
layout: "radio",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bilde",
|
||||
title: "Thumbnail",
|
||||
type: "image",
|
||||
},
|
||||
],
|
||||
options: {
|
||||
collapsible: true,
|
||||
collapsed: false,
|
||||
},
|
||||
}),
|
||||
defineField({
|
||||
title: "Sidebar index",
|
||||
description:
|
||||
"Overstyrer sortering av artikler i sidebar. Hvis feltet er tomt, sorteres den alfabetisk.",
|
||||
name: "sidebarindex",
|
||||
type: "number",
|
||||
group: "settings",
|
||||
}),
|
||||
defineField({
|
||||
title: "Innhold",
|
||||
description:
|
||||
"Innholdet i artikkelen er riktekst. Tips: klikk på ikon i høyre hjørne for å skrive i fullskjerm.",
|
||||
name: "content",
|
||||
type: "riktekst_templates",
|
||||
group: "innhold",
|
||||
}),
|
||||
SEOFields,
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
import { HouseIcon } from "@navikt/aksel-icons";
|
||||
import { defineField, defineType } from "sanity";
|
||||
import { templatesKategorier } from "../../../config";
|
||||
import { groups } from "../presets/groups";
|
||||
import { SEOFields } from "../presets/seo";
|
||||
|
||||
const views = () => {
|
||||
const list = [];
|
||||
templatesKategorier.forEach((kat) => {
|
||||
list.push(
|
||||
defineField({
|
||||
title: `Ingress ${kat.title}`,
|
||||
name: `ingress_${kat.value}`,
|
||||
type: "text",
|
||||
rows: 2,
|
||||
})
|
||||
);
|
||||
list.push(
|
||||
defineField({
|
||||
title: `Intro ${kat.title}`,
|
||||
name: `intro_${kat.value}`,
|
||||
type: "riktekst_standard",
|
||||
})
|
||||
);
|
||||
});
|
||||
return list;
|
||||
};
|
||||
|
||||
export const TemplatesLandingSide = defineType({
|
||||
title: "Landingsside Mønster og Maler",
|
||||
name: "templates_landingsside",
|
||||
type: "document",
|
||||
groups,
|
||||
fields: [
|
||||
defineField({
|
||||
title: "Intro",
|
||||
name: "intro",
|
||||
type: "text",
|
||||
}),
|
||||
...views(),
|
||||
SEOFields,
|
||||
],
|
||||
preview: {
|
||||
prepare: () => ({
|
||||
title: "Landingsside Mønster og Maler",
|
||||
media: HouseIcon,
|
||||
}),
|
||||
},
|
||||
});
|
||||
@@ -23,6 +23,10 @@ export const schema: SchemaPluginOptions = {
|
||||
document.GrunnleggendeLandingSide,
|
||||
document.GrunnleggendeArtikkel,
|
||||
|
||||
/* Møster og Maler */
|
||||
document.TemplatesLandingSide,
|
||||
document.TemplatesArtikkel,
|
||||
|
||||
/* God-praksis */
|
||||
document.Tema,
|
||||
document.GodPraksisArtikkel,
|
||||
@@ -58,6 +62,7 @@ export const schema: SchemaPluginOptions = {
|
||||
object.RiktekstKomponent,
|
||||
object.RiktekstEnkel,
|
||||
object.RiktekstGrunnleggende,
|
||||
object.RiktekstTemplates,
|
||||
object.RiktekstStandard,
|
||||
object.RiktekstPrinsipp,
|
||||
object.RiktekstStandalone,
|
||||
|
||||
@@ -20,19 +20,17 @@ export const KodeEksempler = defineType({
|
||||
name: "dir",
|
||||
type: "reference",
|
||||
to: [{ type: "kode_eksempler_fil" }],
|
||||
options: {
|
||||
filter: "dir == true",
|
||||
},
|
||||
}),
|
||||
],
|
||||
preview: {
|
||||
select: {
|
||||
dir: "dir.title",
|
||||
variant: "dir.variant",
|
||||
},
|
||||
prepare({ dir }) {
|
||||
prepare({ dir, variant }) {
|
||||
return {
|
||||
title: "Komponent-demo",
|
||||
subtitle: dir ?? "",
|
||||
subtitle: `${variant} | ${dir}`,
|
||||
media: ComponentIcon,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -131,6 +131,7 @@ const Riktekst = (
|
||||
type:
|
||||
| "god-praksis"
|
||||
| "grunnleggende"
|
||||
| "templates"
|
||||
| "komponent"
|
||||
| "prinsipp"
|
||||
| "standard"
|
||||
@@ -169,6 +170,8 @@ const Riktekst = (
|
||||
"token_ref",
|
||||
];
|
||||
|
||||
const templates = ["kode_eksempler"];
|
||||
|
||||
const grunnleggende = ["spesial_seksjon"];
|
||||
|
||||
fields.push(...standard);
|
||||
@@ -186,6 +189,9 @@ const Riktekst = (
|
||||
case "accordion":
|
||||
fields = [...accordion];
|
||||
break;
|
||||
case "templates":
|
||||
fields.push(...templates);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -256,3 +262,11 @@ export const RiktekstStandalone = {
|
||||
of: Riktekst("standalone"),
|
||||
icon: FileTextIcon,
|
||||
};
|
||||
|
||||
export const RiktekstTemplates = {
|
||||
title: "Riktekst",
|
||||
name: "riktekst_templates",
|
||||
type: "array",
|
||||
of: Riktekst("templates"),
|
||||
icon: FileTextIcon,
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
import { getExampleFiles } from "../get-example-files";
|
||||
|
||||
describe("Reading code-examples files", () => {
|
||||
test("getExampleFiles", () => {
|
||||
const files = getExampleFiles();
|
||||
|
||||
expect(files.length).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
export {};
|
||||
@@ -1,89 +0,0 @@
|
||||
import { getExampleFiles } from "../get-example-files";
|
||||
import {
|
||||
filterCode,
|
||||
getDesc,
|
||||
getIndex,
|
||||
readExampleFile,
|
||||
readExampleFiles,
|
||||
} from "../read-example-files";
|
||||
|
||||
const d = `import { Button } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return <Button>Primary</Button>;
|
||||
};`;
|
||||
|
||||
const testStr1 = `${d}
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
index: 0,
|
||||
desc: "description-text"
|
||||
};`;
|
||||
|
||||
const testStr2 = `${d}
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
export const args = {
|
||||
};`;
|
||||
|
||||
const testStr3 = `${d}
|
||||
|
||||
export default withDsExample(Example);
|
||||
`;
|
||||
|
||||
const testStr4 = `${d}
|
||||
|
||||
export default withDsExample(Example, {
|
||||
variant: "full",
|
||||
showBreakpoints: true,
|
||||
});
|
||||
|
||||
export const args = {
|
||||
};`;
|
||||
|
||||
const testStr4Res = `import { Button } from "@navikt/ds-react";
|
||||
|
||||
const Example = () => {
|
||||
return <Button>Primary</Button>;
|
||||
};`;
|
||||
|
||||
const codeRes = `import { Button } from "@navikt/ds-react";
|
||||
|
||||
const Example = () => {
|
||||
return <Button>Primary</Button>;
|
||||
};`;
|
||||
|
||||
describe("Reading code-examples", () => {
|
||||
test("getDesc", () => {
|
||||
expect(getDesc(testStr1)).toEqual("description-text");
|
||||
expect(getDesc(testStr2)).toBeNull();
|
||||
expect(getDesc(testStr3)).toBeNull();
|
||||
});
|
||||
|
||||
test("getIndex", () => {
|
||||
expect(getIndex(testStr1)).toEqual(0);
|
||||
expect(getIndex(testStr2)).toEqual(1);
|
||||
expect(getIndex(testStr3)).toEqual(1);
|
||||
});
|
||||
|
||||
test("filterCode", () => {
|
||||
expect(filterCode(testStr1)).toEqual(codeRes);
|
||||
expect(filterCode(testStr4)).toEqual(testStr4Res);
|
||||
});
|
||||
|
||||
test("readExampleFiles", () => {
|
||||
const files = getExampleFiles();
|
||||
expect(readExampleFiles(files[0].path.split("/")[0])).toBeTruthy();
|
||||
});
|
||||
|
||||
test("readExampleFile", () => {
|
||||
const files = getExampleFiles();
|
||||
expect(readExampleFile(files[0].path)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
export {};
|
||||
@@ -1,26 +0,0 @@
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
/**
|
||||
* @returns array of all paths and if they are a dir or not
|
||||
*/
|
||||
export const getExampleFiles = (): { path: string; dir: boolean }[] => {
|
||||
const examplePath = path.resolve(process.cwd(), `pages/eksempler`);
|
||||
const res = [];
|
||||
|
||||
if (fs.existsSync(examplePath)) {
|
||||
const dirs = fs
|
||||
.readdirSync(examplePath, { withFileTypes: true })
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map((dirent) => dirent.name);
|
||||
|
||||
dirs.map((dir) => {
|
||||
const dirPath = path.resolve(process.cwd(), `pages/eksempler/${dir}`);
|
||||
const files = fs.readdirSync(dirPath);
|
||||
files.forEach((file) => res.push({ path: `${dir}/${file}`, dir: false }));
|
||||
});
|
||||
dirs.forEach((dir) => res.push({ path: `${dir}`, dir: true }));
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export * from "./read-example-files";
|
||||
@@ -1,105 +0,0 @@
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import JSON5 from "json5";
|
||||
|
||||
export const getDesc = (str: string) => {
|
||||
const args = str.match(/export const args = {([^}]+)}/)?.[1];
|
||||
if (args) {
|
||||
const obj = JSON5.parse(`{${args}}`);
|
||||
return obj?.desc ?? null;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const filterCode = (code: string) => {
|
||||
const exampleList = code
|
||||
.substring(0, code.indexOf("export const args ="))
|
||||
.split("\n")
|
||||
.filter((x) => !x.includes("examples/withDsExample"));
|
||||
|
||||
const storyIndex = exampleList.findIndex(
|
||||
(x) => x === "/* Storybook story */"
|
||||
);
|
||||
|
||||
if (storyIndex === -1) {
|
||||
return exampleList
|
||||
.join("\n")
|
||||
.replace(/^\s*export default withDsExample\(Example[\s\S]*?;\s*/gm, "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
return exampleList
|
||||
.filter((_, idx) => idx < storyIndex || idx > storyIndex + 3)
|
||||
.join("\n")
|
||||
.replace(/^\s*export default withDsExample\(Example[\s\S]*?;\s*/gm, "")
|
||||
.trim();
|
||||
};
|
||||
|
||||
export const getIndex = (str: string) => {
|
||||
const args = str.match(/export const args = {([^}]+)}/)?.[1];
|
||||
if (args) {
|
||||
const obj = JSON5.parse(`{${args}}`);
|
||||
return obj?.index ?? 1;
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
|
||||
type FileT = { innhold: string; navn: string; description: string | null }[];
|
||||
|
||||
const sortResult = (res: FileT) => {
|
||||
return res.sort((a, b) => {
|
||||
return getIndex(a.innhold) - getIndex(b.innhold);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param dirName Directory name
|
||||
* @returns File-content for files in dir + filename
|
||||
*/
|
||||
export const readExampleFiles = (dirName: string): FileT => {
|
||||
const examplePath = path.resolve(process.cwd(), `pages/eksempler/${dirName}`);
|
||||
if (fs.existsSync(examplePath)) {
|
||||
const files = fs.readdirSync(examplePath);
|
||||
|
||||
const res = files.map((file) => {
|
||||
let code = "";
|
||||
const filepath = path.resolve(
|
||||
process.cwd(),
|
||||
`pages/eksempler/${dirName}/${file}`
|
||||
);
|
||||
code = fs.readFileSync(filepath, "utf-8");
|
||||
return {
|
||||
innhold: code,
|
||||
navn: file.replace(".tsx", ""),
|
||||
description: getDesc(code),
|
||||
};
|
||||
});
|
||||
return sortResult(res).map((x) => ({
|
||||
...x,
|
||||
innhold: filterCode(x.innhold),
|
||||
}));
|
||||
}
|
||||
return [];
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param fileName example filename including dir: button/primary.tsx
|
||||
* @returns File-content for file + filename
|
||||
*/
|
||||
export const readExampleFile = (
|
||||
fileName: string
|
||||
): { innhold: string; navn: string } => {
|
||||
const examplePath = path.resolve(
|
||||
process.cwd(),
|
||||
`pages/eksempler/${fileName}`
|
||||
);
|
||||
|
||||
let code = "";
|
||||
code = fs.readFileSync(examplePath, "utf-8");
|
||||
return {
|
||||
innhold: filterCode(code),
|
||||
navn: fileName.replace(".tsx", ""),
|
||||
};
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
import dotenv from "dotenv";
|
||||
import { readExampleFile, readExampleFiles } from ".";
|
||||
import { noCdnClient } from "../../sanity/interface/client.server";
|
||||
import { getExampleFiles } from "./get-example-files";
|
||||
dotenv.config();
|
||||
|
||||
const createId = (s: string) =>
|
||||
`kode_eksempelid_${s
|
||||
.match(/\w/g)
|
||||
?.join("")
|
||||
?.match(/\D/g)
|
||||
?.join("")}`.toLowerCase();
|
||||
|
||||
const main = async () => {
|
||||
const token = process.env.SANITY_WRITE_KEY;
|
||||
const transactionClient = noCdnClient(token).transaction();
|
||||
const examples = getExampleFiles();
|
||||
|
||||
const docs = await noCdnClient(token).fetch(
|
||||
`*[_type == "kode_eksempler_fil"]`
|
||||
);
|
||||
|
||||
/* Delete fremoved examples */
|
||||
for (const doc of docs) {
|
||||
if (!examples.some((x) => doc._id === createId(x.path))) {
|
||||
transactionClient.delete(doc._id);
|
||||
}
|
||||
}
|
||||
|
||||
for (const ex of examples) {
|
||||
const data = {
|
||||
_id: createId(ex.path),
|
||||
_type: "kode_eksempler_fil",
|
||||
title: ex.path,
|
||||
dir: ex.dir,
|
||||
filer: ex.dir ? readExampleFiles(ex.path) : [readExampleFile(ex.path)],
|
||||
};
|
||||
|
||||
transactionClient.createOrReplace(data);
|
||||
}
|
||||
|
||||
await transactionClient
|
||||
.commit({ autoGenerateArrayKeys: true })
|
||||
.then(() => console.log(`Oppdaterte kode-eksempler`))
|
||||
.catch((e) => console.error(e.message));
|
||||
};
|
||||
|
||||
main();
|
||||
@@ -0,0 +1,31 @@
|
||||
import { extractArgs } from "../parts/extract-args";
|
||||
|
||||
describe("Testing extractArgs function", () => {
|
||||
test("extractArgs should return null on failed parsing", () => {
|
||||
const code = `export const args {
|
||||
title: "Tittel"
|
||||
desc: "Description",
|
||||
index 2
|
||||
}`;
|
||||
|
||||
const args = extractArgs(code, "filename", "test");
|
||||
|
||||
expect(args).toBeNull();
|
||||
});
|
||||
|
||||
test("extractArgs should parse args from codesnippet", () => {
|
||||
const code = `export const args = {
|
||||
title: "Tittel",
|
||||
desc: "Description",
|
||||
index: 2
|
||||
}`;
|
||||
|
||||
const args = extractArgs(code, "filename", "test");
|
||||
|
||||
expect(args).toEqual({
|
||||
title: "Tittel",
|
||||
desc: "Description",
|
||||
index: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import fs from "fs";
|
||||
import { extractMetadata } from "../parts/extract-metadata";
|
||||
|
||||
jest.mock("fs");
|
||||
|
||||
const sampleObj = {
|
||||
version: 1,
|
||||
changelog: [
|
||||
{
|
||||
description: "Oppdaterte X Y og Z",
|
||||
date: "31.10.2023",
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const sampleString = JSON.stringify(sampleObj, null, 2);
|
||||
|
||||
describe("Testing extractMetadata function", () => {
|
||||
test("extractMetadata should return undefined if directory does not exist", () => {
|
||||
(fs.existsSync as jest.Mock).mockReturnValue(false);
|
||||
const metadata = extractMetadata("nonexistent", "templates");
|
||||
|
||||
expect(metadata).toBeUndefined();
|
||||
});
|
||||
|
||||
test("extractMetadata should read meta.json from /pages/templates directory", () => {
|
||||
(fs.existsSync as jest.Mock).mockReturnValue(true);
|
||||
(fs.readdirSync as jest.Mock).mockReturnValue(["file1.tsx", "meta.json"]);
|
||||
(fs.readFileSync as jest.Mock).mockReturnValue(sampleString);
|
||||
|
||||
const metadata = extractMetadata("eksempler", "templates");
|
||||
|
||||
expect(metadata).toEqual(sampleObj);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
import { filterCode } from "../parts/filter-code";
|
||||
import { codeAfter, codeBefore } from "./mockdata";
|
||||
|
||||
test("filterCode should remove unwanted code", () => {
|
||||
const codeResult = filterCode(codeBefore);
|
||||
|
||||
expect(codeResult).toEqual(codeAfter);
|
||||
});
|
||||
@@ -0,0 +1,15 @@
|
||||
import { getDirectories } from "../parts/get-directories";
|
||||
|
||||
describe("Testing getDirectories function", () => {
|
||||
test("getDirectories should list directories in /pages/eksempler", () => {
|
||||
const folders = getDirectories("eksempler");
|
||||
|
||||
expect(folders.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
test("getDirectories should list directories in /pages/templates", () => {
|
||||
const folders = getDirectories("eksempler");
|
||||
|
||||
expect(folders.length).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
export const codeBefore = `import { Alert } from "@navikt/ds-react";
|
||||
import { withDsExample } from "components/website-modules/examples/withDsExample";
|
||||
|
||||
const Example = () => {
|
||||
return (
|
||||
<Alert variant="error">Noe gikk galt! Prøv igjen om noen minutter.</Alert>
|
||||
);
|
||||
};
|
||||
|
||||
export default withDsExample(Example);
|
||||
|
||||
/* Storybook story */
|
||||
export const Demo = {
|
||||
render: Example,
|
||||
};
|
||||
|
||||
export const args = {
|
||||
index: 0,
|
||||
};
|
||||
`;
|
||||
|
||||
export const codeAfter = `import { Alert } from "@navikt/ds-react";
|
||||
|
||||
const Example = () => {
|
||||
return (
|
||||
<Alert variant="error">Noe gikk galt! Prøv igjen om noen minutter.</Alert>
|
||||
);
|
||||
};`;
|
||||
@@ -0,0 +1,36 @@
|
||||
import fs from "fs";
|
||||
import { parseCodeFiles } from "../parts/parse-code-files";
|
||||
import { codeAfter, codeBefore } from "./mockdata";
|
||||
|
||||
jest.mock("fs");
|
||||
|
||||
describe("Testing parseCodeFiles function", () => {
|
||||
test("parseCodeFiles should return an empty array if directory does not exist", () => {
|
||||
(fs.existsSync as jest.Mock).mockReturnValue(false);
|
||||
const files = parseCodeFiles("nonexistent", "eksempler");
|
||||
|
||||
expect(files).toEqual([]);
|
||||
});
|
||||
|
||||
test("parseCodeFiles should read files from /pages/eksempler directory", () => {
|
||||
(fs.existsSync as jest.Mock).mockReturnValue(true);
|
||||
(fs.readdirSync as jest.Mock).mockReturnValue(["file1.tsx", "file2.tsx"]);
|
||||
(fs.readFileSync as jest.Mock).mockReturnValue(codeBefore);
|
||||
|
||||
const files = parseCodeFiles("eksempler", "eksempler");
|
||||
|
||||
expect(files.length).toBeGreaterThan(0);
|
||||
expect(files[0].innhold).toEqual(codeAfter);
|
||||
});
|
||||
|
||||
test("parseCodeFiles should read files from /pages/templates directory", () => {
|
||||
(fs.existsSync as jest.Mock).mockReturnValue(true);
|
||||
(fs.readdirSync as jest.Mock).mockReturnValue(["file1.tsx", "file2.tsx"]);
|
||||
(fs.readFileSync as jest.Mock).mockReturnValue(codeBefore);
|
||||
|
||||
const files = parseCodeFiles("templates", "templates");
|
||||
|
||||
expect(files.length).toBeGreaterThan(0);
|
||||
expect(files[0].innhold).toEqual(codeAfter);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
import JSON5 from "json5";
|
||||
import { ArgsT } from "../types";
|
||||
|
||||
export function extractArgs(
|
||||
code: string,
|
||||
fileName: string,
|
||||
env?: "test"
|
||||
): ArgsT | null {
|
||||
const args = code.match(/export const args = {([^}]+)}/)?.[1];
|
||||
|
||||
if (!args) {
|
||||
env !== "test" &&
|
||||
console.warn(
|
||||
`Missing args when parsing code for examples/template: ${fileName}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return JSON5.parse(`{${args}}`) ?? null;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import fs from "fs";
|
||||
import JSON5 from "json5";
|
||||
import path from "path";
|
||||
import { CodeExampleSchemaT } from "../../../types";
|
||||
import { RootDirectoriesT } from "../types";
|
||||
|
||||
export function extractMetadata(
|
||||
dirName: string,
|
||||
rootDir: RootDirectoriesT
|
||||
): CodeExampleSchemaT["metadata"] {
|
||||
const codeDirPath = path.resolve(
|
||||
process.cwd(),
|
||||
`pages/${rootDir}/${dirName}`
|
||||
);
|
||||
|
||||
if (
|
||||
!fs.existsSync(codeDirPath) ||
|
||||
!fs.readdirSync(codeDirPath).find((x) => x === "meta.json")
|
||||
) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const metadata = fs.readFileSync(
|
||||
path.resolve(process.cwd(), `pages/${rootDir}/${dirName}/meta.json`),
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
return JSON5.parse(metadata);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
export function filterCode(code: string) {
|
||||
const _code = code
|
||||
.substring(0, code.indexOf("export const args ="))
|
||||
.split("\n")
|
||||
.filter((x) => !x.includes("examples/withDsExample"));
|
||||
|
||||
const storyIndex = _code.findIndex((x) => x === "/* Storybook story */");
|
||||
|
||||
if (storyIndex === -1) {
|
||||
return _code
|
||||
.join("\n")
|
||||
.replace(/^\s*export default withDsExample\(Example[\s\S]*?;\s*/gm, "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
return _code
|
||||
.filter((_, idx) => idx < storyIndex || idx > storyIndex + 3)
|
||||
.join("\n")
|
||||
.replace(/^\s*export default withDsExample\(Example[\s\S]*?;\s*/gm, "")
|
||||
.trim();
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { DirectoryDataT, RootDirectoriesT } from "../types";
|
||||
|
||||
/**
|
||||
* Returns metadata for each 'page' found in directory
|
||||
* @param directory
|
||||
* @returns DirectoryDataT
|
||||
*/
|
||||
export function getDirectories(directory: RootDirectoriesT): DirectoryDataT {
|
||||
const rootPath = path.resolve(process.cwd(), `pages/${directory}`);
|
||||
|
||||
if (!fs.existsSync(rootPath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const folders = fs
|
||||
.readdirSync(rootPath, { withFileTypes: true })
|
||||
.filter((dirent) => dirent.isDirectory())
|
||||
.map((dirent) => dirent.name);
|
||||
|
||||
return folders.map((dir) => ({ path: `${dir}` }));
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { FileArrayT, RootDirectoriesT } from "../types";
|
||||
import { extractArgs } from "./extract-args";
|
||||
import { filterCode } from "./filter-code";
|
||||
import { sortResult } from "./sort";
|
||||
|
||||
export function parseCodeFiles(
|
||||
dirName: string,
|
||||
rootDir: RootDirectoriesT
|
||||
): FileArrayT {
|
||||
const codeDirPath = path.resolve(
|
||||
process.cwd(),
|
||||
`pages/${rootDir}/${dirName}`
|
||||
);
|
||||
|
||||
if (!fs.existsSync(codeDirPath)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const codeFiles = fs
|
||||
.readdirSync(codeDirPath)
|
||||
.filter((x) => !x.includes(".json"));
|
||||
|
||||
const parsedCode: FileArrayT = codeFiles.map((file) => {
|
||||
let code = "";
|
||||
|
||||
code = fs.readFileSync(
|
||||
path.resolve(process.cwd(), `pages/${rootDir}/${dirName}/${file}`),
|
||||
"utf-8"
|
||||
);
|
||||
|
||||
const args = extractArgs(code, `pages/${rootDir}/${dirName}/${file}`);
|
||||
|
||||
return {
|
||||
innhold: code,
|
||||
navn: args?.title ?? file.replace(".tsx", ""),
|
||||
description: args?.desc,
|
||||
index: args?.index ?? 1,
|
||||
};
|
||||
});
|
||||
|
||||
return sortResult(parsedCode).map((x) => ({
|
||||
...x,
|
||||
innhold: filterCode(x.innhold),
|
||||
}));
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { FileArrayT } from "../types";
|
||||
|
||||
export function sortResult(res: FileArrayT) {
|
||||
return res.sort((a, b) => {
|
||||
return a.index - b.index;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
export type FileArrayT = {
|
||||
innhold: string;
|
||||
navn: string;
|
||||
index: number;
|
||||
description?: string;
|
||||
}[];
|
||||
|
||||
export type DirectoryDataT = { path: string }[];
|
||||
|
||||
export type ArgsT = {
|
||||
title?: string;
|
||||
index?: number;
|
||||
desc?: string;
|
||||
};
|
||||
export type RootDirectoriesT = "eksempler" | "templates";
|
||||
@@ -0,0 +1,95 @@
|
||||
import dotenv from "dotenv";
|
||||
import { noCdnClient } from "../../sanity/interface/client.server";
|
||||
import { CodeExampleSchemaT } from "../../types";
|
||||
import { extractMetadata } from "./parts/extract-metadata";
|
||||
import { getDirectories } from "./parts/get-directories";
|
||||
import { parseCodeFiles } from "./parts/parse-code-files";
|
||||
import { RootDirectoriesT } from "./types";
|
||||
dotenv.config();
|
||||
|
||||
const token = process.env.SANITY_WRITE_KEY;
|
||||
|
||||
if (!token) {
|
||||
throw new Error("Missing token 'SANITY_WRITE_KEY' for updating sanity");
|
||||
}
|
||||
|
||||
updateSanity("templates", false);
|
||||
updateSanity("eksempler", false);
|
||||
|
||||
export async function updateSanity(
|
||||
directory: RootDirectoriesT,
|
||||
isDryRun: boolean = false
|
||||
) {
|
||||
const transactionClient = noCdnClient(token).transaction();
|
||||
const folders = getDirectories(directory);
|
||||
|
||||
/* First we add/update examples */
|
||||
for (const folder of folders) {
|
||||
const data: CodeExampleSchemaT = {
|
||||
_id: createId(folder.path),
|
||||
_type: "kode_eksempler_fil",
|
||||
title: folder.path,
|
||||
variant: directory,
|
||||
filer: parseCodeFiles(folder.path, directory),
|
||||
metadata: extractMetadata(folder.path, directory),
|
||||
};
|
||||
|
||||
transactionClient.createOrReplace(data);
|
||||
}
|
||||
|
||||
await transactionClient
|
||||
.commit({ autoGenerateArrayKeys: true, dryRun: isDryRun })
|
||||
.then(() => console.log(`Oppdaterte ${directory}-dokumenter i sanity`))
|
||||
.catch((e) => {
|
||||
throw new Error(e.message);
|
||||
});
|
||||
|
||||
const oldSanityDocuments = await noCdnClient(token).fetch(
|
||||
`*[_type == "kode_eksempler_fil" && variant == "${directory}"]`
|
||||
);
|
||||
|
||||
let deletedIds: string[] = [];
|
||||
/* Delete old examples */
|
||||
for (const document of oldSanityDocuments) {
|
||||
if (!folders.some((folder) => document._id === createId(folder.path))) {
|
||||
transactionClient.delete(document._id);
|
||||
deletedIds.push(document._id);
|
||||
}
|
||||
}
|
||||
|
||||
await transactionClient
|
||||
.commit()
|
||||
.then(() => console.log(`Successfully deleted unused ${directory}`))
|
||||
.catch((e) => {
|
||||
/**
|
||||
* Errormessage includes all ids that failed.
|
||||
*/
|
||||
deletedIds = deletedIds.filter((id) => e.message.includes(id));
|
||||
|
||||
console.log("\n");
|
||||
console.log(
|
||||
`Found ${deletedIds.length} ${directory} documents longer documented locally, but referenced in sanity.
|
||||
How to fix:
|
||||
- Go to links provided under and try to manually delete document.
|
||||
- You will then be prompted to update referenced document before deleting.
|
||||
- After updating reference(s) and deleting document(s) there is no need to run the script again.`
|
||||
);
|
||||
console.log(
|
||||
JSON.stringify(
|
||||
deletedIds.map(
|
||||
(x) =>
|
||||
`https://aksel.nav.no/admin/prod/desk/admin;eksemplerTemplates;${x}`
|
||||
),
|
||||
null,
|
||||
2
|
||||
)
|
||||
);
|
||||
throw new Error(
|
||||
`Failed when deleting old ${directory}-documentation from sanity, see warning above.`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function createId(s: string) {
|
||||
return `kode_eksempelid_${s.match(/\w/g)?.join("")}`.toLowerCase();
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
bloggKategorier,
|
||||
grunnleggendeKategorier,
|
||||
komponentKategorier,
|
||||
templatesKategorier,
|
||||
} from "../sanity/config";
|
||||
|
||||
export type ResolveSlugT<T> = Omit<T, "slug"> & {
|
||||
@@ -138,6 +139,24 @@ export interface AkselGrunnleggendeDocT
|
||||
};
|
||||
}
|
||||
|
||||
export interface AkselTemplatesDocT extends DocumentT<"ds_artikkel">, ArticleT {
|
||||
kategori: (typeof templatesKategorier)[number]["value"];
|
||||
status: {
|
||||
tag?: "beta" | "new" | "ready" | "deprecated";
|
||||
unsafe?: boolean;
|
||||
bilde?: any;
|
||||
};
|
||||
intro: {
|
||||
body?: any[];
|
||||
brukes_til: string[];
|
||||
brukes_ikke_til?: string[];
|
||||
};
|
||||
content: any[];
|
||||
updateInfo?: {
|
||||
lastVerified?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export type AkselSidebarT = Array<{
|
||||
heading: string;
|
||||
slug: string;
|
||||
@@ -282,13 +301,30 @@ export interface RelatertInnholdT {
|
||||
>;
|
||||
}
|
||||
|
||||
export type CodeExampleSchemaT = {
|
||||
_id: string;
|
||||
_type: string;
|
||||
title: string;
|
||||
variant: "eksempler" | "templates";
|
||||
filer: {
|
||||
innhold: string;
|
||||
navn: string;
|
||||
index: number;
|
||||
description?: string;
|
||||
}[];
|
||||
metadata?: {
|
||||
version: number;
|
||||
changelog: { description: string; version: number; date: string }[];
|
||||
};
|
||||
};
|
||||
|
||||
export interface CodeExamplesT {
|
||||
title: string;
|
||||
dir: {
|
||||
title: string;
|
||||
filer: Array<
|
||||
ArrayObjectT<{ navn: string; innhold: string; description?: string }>
|
||||
>;
|
||||
filer: Array<ArrayObjectT<CodeExampleSchemaT["filer"][0]>>;
|
||||
metadata?: CodeExampleSchemaT["metadata"];
|
||||
variant: CodeExampleSchemaT["variant"];
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { allArticleDocuments } from "../sanity/config";
|
||||
import Fuse from "fuse.js";
|
||||
import { allArticleDocuments } from "../sanity/config";
|
||||
|
||||
export const searchOptions: {
|
||||
[K in (typeof allArticleDocuments)[number]]: {
|
||||
@@ -11,7 +11,8 @@ export const searchOptions: {
|
||||
komponent_artikkel: { display: "Komponenter", index: 0 },
|
||||
aksel_artikkel: { display: "God praksis", index: 1 },
|
||||
ds_artikkel: { display: "Grunnleggende", index: 2 },
|
||||
aksel_blogg: { display: "Blogg", index: 3 },
|
||||
templates_artikkel: { display: "Mønster og Maler", index: 3 },
|
||||
aksel_blogg: { display: "Blogg", index: 4 },
|
||||
aksel_prinsipp: { display: "Prinsipper", index: 5 },
|
||||
aksel_standalone: { display: "Unike sider", index: 6, hidden: true },
|
||||
};
|
||||
|
||||
@@ -3415,7 +3415,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@navikt/aksel-icons@^5.8.0, @navikt/aksel-icons@workspace:@navikt/aksel-icons":
|
||||
"@navikt/aksel-icons@^5.9.1, @navikt/aksel-icons@workspace:@navikt/aksel-icons":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@navikt/aksel-icons@workspace:@navikt/aksel-icons"
|
||||
dependencies:
|
||||
@@ -3442,8 +3442,8 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@navikt/aksel-stylelint@workspace:@navikt/aksel-stylelint"
|
||||
dependencies:
|
||||
"@navikt/ds-css": ^5.8.0
|
||||
"@navikt/ds-tokens": ^5.8.0
|
||||
"@navikt/ds-css": ^5.9.1
|
||||
"@navikt/ds-tokens": ^5.9.1
|
||||
"@types/jest": ^29.0.0
|
||||
concurrently: 7.2.1
|
||||
copyfiles: 2.4.1
|
||||
@@ -3461,7 +3461,7 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@navikt/aksel@workspace:@navikt/aksel"
|
||||
dependencies:
|
||||
"@navikt/ds-css": 5.8.0
|
||||
"@navikt/ds-css": 5.9.1
|
||||
"@types/inquirer": ^9.0.3
|
||||
"@types/jest": ^29.0.0
|
||||
axios: 1.3.6
|
||||
@@ -3485,11 +3485,11 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@navikt/ds-css@*, @navikt/ds-css@5.8.0, @navikt/ds-css@^5.8.0, @navikt/ds-css@workspace:@navikt/core/css":
|
||||
"@navikt/ds-css@*, @navikt/ds-css@5.9.1, @navikt/ds-css@^5.9.1, @navikt/ds-css@workspace:@navikt/core/css":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@navikt/ds-css@workspace:@navikt/core/css"
|
||||
dependencies:
|
||||
"@navikt/ds-tokens": ^5.8.0
|
||||
"@navikt/ds-tokens": ^5.9.1
|
||||
cssnano: 6.0.0
|
||||
fast-glob: 3.2.11
|
||||
lodash: 4.17.21
|
||||
@@ -3502,13 +3502,13 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@navikt/ds-react@*, @navikt/ds-react@^5.8.0, @navikt/ds-react@workspace:@navikt/core/react":
|
||||
"@navikt/ds-react@*, @navikt/ds-react@^5.9.1, @navikt/ds-react@workspace:@navikt/core/react":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@navikt/ds-react@workspace:@navikt/core/react"
|
||||
dependencies:
|
||||
"@floating-ui/react": 0.25.4
|
||||
"@navikt/aksel-icons": ^5.8.0
|
||||
"@navikt/ds-tokens": ^5.8.0
|
||||
"@navikt/aksel-icons": ^5.9.1
|
||||
"@navikt/ds-tokens": ^5.9.1
|
||||
"@radix-ui/react-tabs": 1.0.0
|
||||
"@radix-ui/react-toggle-group": 1.0.0
|
||||
"@testing-library/dom": 8.13.0
|
||||
@@ -3542,11 +3542,11 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@navikt/ds-tailwind@^5.8.0, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
|
||||
"@navikt/ds-tailwind@^5.9.1, @navikt/ds-tailwind@workspace:@navikt/core/tailwind":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@navikt/ds-tailwind@workspace:@navikt/core/tailwind"
|
||||
dependencies:
|
||||
"@navikt/ds-tokens": ^5.8.0
|
||||
"@navikt/ds-tokens": ^5.9.1
|
||||
"@types/jest": ^29.0.0
|
||||
color: 4.2.3
|
||||
jest: ^29.0.0
|
||||
@@ -3557,7 +3557,7 @@ __metadata:
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@navikt/ds-tokens@^5.8.0, @navikt/ds-tokens@workspace:@navikt/core/tokens":
|
||||
"@navikt/ds-tokens@^5.9.1, @navikt/ds-tokens@workspace:@navikt/core/tokens":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@navikt/ds-tokens@workspace:@navikt/core/tokens"
|
||||
dependencies:
|
||||
@@ -8438,11 +8438,11 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "aksel.nav.no@workspace:aksel.nav.no"
|
||||
dependencies:
|
||||
"@navikt/aksel-icons": ^5.8.0
|
||||
"@navikt/ds-css": ^5.8.0
|
||||
"@navikt/ds-react": ^5.8.0
|
||||
"@navikt/ds-tailwind": ^5.8.0
|
||||
"@navikt/ds-tokens": ^5.8.0
|
||||
"@navikt/aksel-icons": ^5.9.1
|
||||
"@navikt/ds-css": ^5.9.1
|
||||
"@navikt/ds-react": ^5.9.1
|
||||
"@navikt/ds-tailwind": ^5.9.1
|
||||
"@navikt/ds-tokens": ^5.9.1
|
||||
prettier-plugin-tailwindcss: ^0.2.3
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
Reference in new issue
Block a user