@mattilsynet/design 3.2.9 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mtds/ai/AGENTS.md +892 -0
- package/mtds/ai/alert.mdx +63 -0
- package/mtds/ai/alert.stories.tsx +128 -0
- package/mtds/ai/analytics.mdx +185 -0
- package/mtds/ai/app.mdx +60 -0
- package/mtds/ai/app.stories.tsx +897 -0
- package/mtds/ai/atlas.mdx +82 -0
- package/mtds/ai/atlas.stories.tsx +424 -0
- package/mtds/ai/avatar.mdx +45 -0
- package/mtds/ai/avatar.stories.tsx +109 -0
- package/mtds/ai/badge.mdx +70 -0
- package/mtds/ai/badge.stories.tsx +122 -0
- package/mtds/ai/breadcrumbs.mdx +36 -0
- package/mtds/ai/breadcrumbs.stories.tsx +158 -0
- package/mtds/ai/button.mdx +179 -0
- package/mtds/ai/button.stories.tsx +440 -0
- package/mtds/ai/card.mdx +51 -0
- package/mtds/ai/card.stories.tsx +469 -0
- package/mtds/ai/chart.mdx +67 -0
- package/mtds/ai/chart.stories.tsx +519 -0
- package/mtds/ai/chip.mdx +71 -0
- package/mtds/ai/chip.stories.tsx +211 -0
- package/mtds/ai/details.mdx +33 -0
- package/mtds/ai/details.stories.tsx +91 -0
- package/mtds/ai/dialog.mdx +38 -0
- package/mtds/ai/dialog.stories.tsx +373 -0
- package/mtds/ai/divider.mdx +19 -0
- package/mtds/ai/divider.stories.tsx +50 -0
- package/mtds/ai/errorsummary.mdx +26 -0
- package/mtds/ai/errorsummary.stories.tsx +137 -0
- package/mtds/ai/field.mdx +86 -0
- package/mtds/ai/field.stories.tsx +863 -0
- package/mtds/ai/fieldset.mdx +126 -0
- package/mtds/ai/fieldset.stories.tsx +298 -0
- package/mtds/ai/fileupload.mdx +16 -0
- package/mtds/ai/fileupload.stories.tsx +126 -0
- package/mtds/ai/helptext.mdx +24 -0
- package/mtds/ai/helptext.stories.tsx +106 -0
- package/mtds/ai/input.mdx +223 -0
- package/mtds/ai/input.stories.tsx +352 -0
- package/mtds/ai/law.mdx +115 -0
- package/mtds/ai/law.stories.tsx +168 -0
- package/mtds/ai/layout.mdx +145 -0
- package/mtds/ai/layout.stories.tsx +443 -0
- package/mtds/ai/link.mdx +45 -0
- package/mtds/ai/link.stories.tsx +44 -0
- package/mtds/ai/logo.mdx +86 -0
- package/mtds/ai/logo.stories.tsx +146 -0
- package/mtds/ai/pagination.mdx +136 -0
- package/mtds/ai/pagination.stories.tsx +404 -0
- package/mtds/ai/popover.mdx +86 -0
- package/mtds/ai/popover.stories.tsx +355 -0
- package/mtds/ai/print.mdx +96 -0
- package/mtds/ai/print.stories.tsx +839 -0
- package/mtds/ai/progress.mdx +41 -0
- package/mtds/ai/progress.stories.tsx +141 -0
- package/mtds/ai/skeleton.mdx +26 -0
- package/mtds/ai/skeleton.stories.tsx +131 -0
- package/mtds/ai/spinner.mdx +26 -0
- package/mtds/ai/spinner.stories.tsx +72 -0
- package/mtds/ai/steps.mdx +37 -0
- package/mtds/ai/steps.stories.tsx +568 -0
- package/mtds/ai/table.mdx +124 -0
- package/mtds/ai/table.stories.tsx +1715 -0
- package/mtds/ai/tabs.mdx +106 -0
- package/mtds/ai/tabs.stories.tsx +159 -0
- package/mtds/ai/tag.mdx +49 -0
- package/mtds/ai/tag.stories.tsx +111 -0
- package/mtds/ai/toast.mdx +67 -0
- package/mtds/ai/toast.stories.tsx +215 -0
- package/mtds/ai/togglegroup.mdx +75 -0
- package/mtds/ai/togglegroup.stories.tsx +96 -0
- package/mtds/ai/tooltip.mdx +32 -0
- package/mtds/ai/tooltip.stories.tsx +34 -0
- package/mtds/ai/typography.mdx +67 -0
- package/mtds/ai/typography.stories.tsx +798 -0
- package/mtds/ai/validation.mdx +19 -0
- package/mtds/ai/validation.stories.tsx +45 -0
- package/mtds/atlas/atlas-element.js +1 -1
- package/mtds/chart/chart-lines.js +19 -19
- package/mtds/chart/chart-lines.js.map +1 -1
- package/mtds/chart/chart.css.js +16 -1
- package/mtds/chart/chart.css.js.map +1 -1
- package/mtds/chart/chart.stories.d.ts +1 -0
- package/mtds/index.iife.js +32 -17
- package/mtds/package.json.js +1 -1
- package/mtds/styles.css +1 -1
- package/mtds/table/table-observer.js +26 -15
- package/mtds/table/table-observer.js.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { JumpTo, CssVariables } from '../../.storybook/blocks';
|
|
3
|
+
import * as stories from './atlas.stories';
|
|
4
|
+
import { Table, Popover } from '../react';
|
|
5
|
+
import atlasCSS from './atlas.css?raw';
|
|
6
|
+
|
|
7
|
+
<Meta of={stories} />
|
|
8
|
+
|
|
9
|
+
# Atlas (Eksperimentell)
|
|
10
|
+
|
|
11
|
+
> Atlas er et standardisert oppsett for presentasjon av kart.
|
|
12
|
+
|
|
13
|
+
<JumpTo />
|
|
14
|
+
<Popover id="pop-jsref" style={{ maxWidth: 500 }}>For eksempel via `document.getElementById` eller via `useRef` i React.</Popover>
|
|
15
|
+
|
|
16
|
+
## Kode
|
|
17
|
+
- Importer `import "@mattilsynet/design/atlas"` og bruk elementene<br />`<mtds-atlas>`, `<mtds-atlas-marker>` og `<mtds-atlas-matgeo>`
|
|
18
|
+
- **React?** Importer `import { Atlas } from "@mattilsynet/design/atlas/react"` og bruk elementene `<Atlas>`, `<Atlas.Marker>` og `<Atlas.Matgeo>`. Husk `"use client"`
|
|
19
|
+
- **Avansert bruk?** Du får tilgang til hele [Leaflet](https://leafletjs.com/) via `import { L } from "@mattilsynet/design/atlas"` eller `import { L } from "@mattilsynet/design/atlas/react"`
|
|
20
|
+
- **Kartlag** leveres av [Kartverket](https://cache.kartverket.no/) for oppnå gjenkjennlige og presise norgeskart
|
|
21
|
+
- **Karttegning** leveres av [Leaflet](https://leafletjs.com/) ([2.0.0@alpha.1](https://leafletjs.com/2025/05/18/leaflet-2.0.0-alpha.html)) i [EPSG:4326 koordinatsystem](https://epsg.io/4326)
|
|
22
|
+
|
|
23
|
+
## Utsnitt
|
|
24
|
+
- Bruk `data-view="lat, lng, zoom"` for å sette eller endre kartutsnitt
|
|
25
|
+
- Bruk `data-view="fit"` for å få et utsnitt som viser alle markører
|
|
26
|
+
- Du kan også hente Atlas elementet via JS (f.eks `document.getElementById` eller `useRef` i React) og kalle `atlasElement.setView([lat, lng, zoom])` eller `atlasElement.setView('fit')` for å endre utsnitt programatisk
|
|
27
|
+
<Canvas of={stories.WithView} />
|
|
28
|
+
|
|
29
|
+
## Kartlag
|
|
30
|
+
- Bruk `data-tiles="gray | color"` for å endre kartlag
|
|
31
|
+
<Canvas of={stories.WithColor} />
|
|
32
|
+
|
|
33
|
+
## Markører
|
|
34
|
+
- Legg elementer i `<mtds-atlas>` eller `<Atlas.Marker>` med `data-marker="lat, lng"`
|
|
35
|
+
- Legg innhold inni for å gi markøren ikon eller tekst
|
|
36
|
+
- Bruk `popovertarget="ID"` for å knytte en popover til markøren
|
|
37
|
+
- Bruk `data-tooltip="TEKST"` for å legge til tooltip
|
|
38
|
+
- Bruk `draggable` for å gjøre markøren flyttbar
|
|
39
|
+
- Bruk `data-color` for å endre farge
|
|
40
|
+
- Du kan style markører via CSS-variabler, enten individuelt eller satt på Atlas-elementet
|
|
41
|
+
<Canvas of={stories.WithMarker} />
|
|
42
|
+
|
|
43
|
+
## Clustering
|
|
44
|
+
- Bruk `data-cluster="number"` for å aktivere clustring fra til et gitt zoom-nivå og utover
|
|
45
|
+
- Bruk `data-cluster="true"` for clustering på alle zoomnivå. Dette er anbefalt dersom du kan ha datapunker på samme posisjon
|
|
46
|
+
<Canvas of={stories.WithClustering} />
|
|
47
|
+
|
|
48
|
+
## Popover
|
|
49
|
+
- Legg et Popover element med `id` inni Atlas med ønsket innhold
|
|
50
|
+
- Bruk `popovertarget="ID"` på markører eller matgeo for å tilknytte
|
|
51
|
+
- Du kan også hente Atlas elementet via JS (f.eks `document.getElementById` eller `useRef` i React) og kalle `atlasElement.map.openPopup("content", [lat, lng])` for å åpne en popover programatisk. Dersom du kaller `atlasElement.map.openPopup("#ID", [lat, lng])`, vil popupen automatisk vise innholdet fra et annet element med gitt `ID`.
|
|
52
|
+
<Canvas of={stories.WithPopover} />
|
|
53
|
+
|
|
54
|
+
## Matgeo
|
|
55
|
+
- Matgeo er Mattilsynets egne stedfestede data fra alle fagområder
|
|
56
|
+
- Du kan vise Matgeo-data i Atlas ved å bruke `<mtds-atlas-matgeo>` eller `<Atlas.Matgeo>`
|
|
57
|
+
- Bruk `data-collection="COLLECTION-ID"` for å velge collection
|
|
58
|
+
- Hvis du ikke setter en gyldig `COLLECTION-ID`, listes mulige collections i konsoll
|
|
59
|
+
- Bruk `data-color` for å endre farge
|
|
60
|
+
- Bruk `popovertarget="ID"` for å knytte en popover til matgeo
|
|
61
|
+
- Lytt til `atlasfeatureclick` (eller `onFeatureClick` i React) for å fange opp klikk på matgeo
|
|
62
|
+
- Bruk `await AtlasMatgeoElement.getCollection()` for å hente collection metadata
|
|
63
|
+
- Bruk `await AtlasElement.getCollections()` for å hente alle collections
|
|
64
|
+
<Canvas of={stories.WithMatgeo} />
|
|
65
|
+
|
|
66
|
+
## WMS
|
|
67
|
+
- WMS (web map service), er en åpen standard for utveksling av kartlag på tvers av kilder
|
|
68
|
+
- Du kan vise WMS-lag fra f.eks [geonorge](https://kartkatalog.geonorge.no/) ved å bruke `<mtds-atlas-wma>` eller `<Atlas.WMS>`
|
|
69
|
+
- Bruk `data-url="MATRIKKEL-URL-MED-PARAMETER"` for å hente karlag
|
|
70
|
+
<Canvas of={stories.WithWMS} />
|
|
71
|
+
|
|
72
|
+
## Klikk-for-markør
|
|
73
|
+
- Bruk `data-cursor="pointer"` på `<mtds-atlas>` for å indikere at kartet er klikkbart
|
|
74
|
+
- Lytt til `click`, og sjekk at `event.currentTarget === event.target` for å sikre at klikket skjedde på kartet og ikke en markør eller matgeo
|
|
75
|
+
- Bruk `event.currentTarget.latLngFromPoint(event.clientX, event.clientY)` for å få lat/lng fra klikkpunktet
|
|
76
|
+
<Canvas of={stories.WithClickToAddMarker} />
|
|
77
|
+
|
|
78
|
+
## Uten scroll-zoom
|
|
79
|
+
- Bruk `data-scroll-zoom="false"` for å deaktivere zooming med scroll-hjul
|
|
80
|
+
<Canvas of={stories.WithoutScrollZoom} />
|
|
81
|
+
|
|
82
|
+
<CssVariables component='atlas' css={atlasCSS} />
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { MagnifyingGlassMinusIcon, StarIcon } from "@phosphor-icons/react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import type { MTDSAtlasCollection, MTDSAtlasElement } from "../atlas";
|
|
5
|
+
import {
|
|
6
|
+
Button,
|
|
7
|
+
Details,
|
|
8
|
+
Field,
|
|
9
|
+
Fieldset,
|
|
10
|
+
Flex,
|
|
11
|
+
Group,
|
|
12
|
+
Heading,
|
|
13
|
+
Popover,
|
|
14
|
+
Prose,
|
|
15
|
+
toast,
|
|
16
|
+
} from "../react";
|
|
17
|
+
import { Atlas, type AtlasMatgeoProps } from "../react-atlas";
|
|
18
|
+
|
|
19
|
+
const meta = {
|
|
20
|
+
title: "Designsystem/Atlas",
|
|
21
|
+
parameters: {
|
|
22
|
+
layout: "padded",
|
|
23
|
+
},
|
|
24
|
+
} satisfies Meta;
|
|
25
|
+
|
|
26
|
+
export default meta;
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
|
|
29
|
+
const LOREM_IPSUM =
|
|
30
|
+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque finibus dui id efficitur lobortis. Aliquam erat volutpat. Pellentesque imperdiet consectetur posuere. Donec ultrices libero eu velit egestas tincidunt. Suspendisse placerat risus non tellus faucibus, eu ultricies augue tempus. Donec vestibulum arcu diam, efficitur auctor lectus placerat vel. Nullam aliquam turpis vel mollis pharetra. Etiam eget pulvinar dui, imperdiet congue nisi. Nullam vel finibus risus. Ut sodales luctus odio quis interdum. Donec ligula quam, viverra vitae finibus a, bibendum quis odio. Quisque sodales erat volutpat condimentum maximus. Sed eget augue sed ligula congue hendrerit id sed turpis. Fusce nec leo fringilla, faucibus turpis a, tristique est. In ac semper libero, nec lacinia tellus.";
|
|
31
|
+
|
|
32
|
+
export const Default: Story = {
|
|
33
|
+
parameters: {
|
|
34
|
+
showInOverview: false,
|
|
35
|
+
},
|
|
36
|
+
render: () => <mtds-atlas />,
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const React: Story = {
|
|
40
|
+
parameters: {
|
|
41
|
+
showInOverview: false,
|
|
42
|
+
},
|
|
43
|
+
render: () => <Atlas />,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const WithView: Story = {
|
|
47
|
+
render: () => <Atlas data-view="63.431958, 10.397461, 12" />,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const WithViewAdvanced: Story = {
|
|
51
|
+
render: function Render() {
|
|
52
|
+
const atlasRef = useRef<MTDSAtlasElement>(null);
|
|
53
|
+
const [open, setOpen] = useState<(typeof markers)[number]>();
|
|
54
|
+
const markers = [
|
|
55
|
+
{
|
|
56
|
+
latlng: "59.910815, 10.754078",
|
|
57
|
+
summary: "Oslo",
|
|
58
|
+
content: "Informasjon om Oslo",
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
latlng: "63.431958, 10.397461",
|
|
62
|
+
summary: "Trondheim",
|
|
63
|
+
content: "Informasjon om Trondheim",
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
latlng: "60.391449, 5.324119",
|
|
67
|
+
summary: "Bergen",
|
|
68
|
+
content: "Informasjon om Bergen",
|
|
69
|
+
},
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Flex data-items="300" data-nowrap>
|
|
74
|
+
<Atlas ref={atlasRef} data-view={open ? `${open.latlng}, 14` : "fit"}>
|
|
75
|
+
{markers.map((marker) => (
|
|
76
|
+
<Atlas.Marker
|
|
77
|
+
key={marker.summary}
|
|
78
|
+
data-tooltip={marker.summary}
|
|
79
|
+
data-latlng={marker.latlng}
|
|
80
|
+
onClick={() => setOpen(marker)}
|
|
81
|
+
/>
|
|
82
|
+
))}
|
|
83
|
+
</Atlas>
|
|
84
|
+
<Group as={Prose} data-items="200" data-fixed>
|
|
85
|
+
{markers.map((marker) => (
|
|
86
|
+
<Details
|
|
87
|
+
key={marker.summary}
|
|
88
|
+
open={open?.summary === marker.summary}
|
|
89
|
+
name="place"
|
|
90
|
+
>
|
|
91
|
+
<Details.Summary onClick={() => setOpen(marker)}>
|
|
92
|
+
{marker.summary}
|
|
93
|
+
</Details.Summary>
|
|
94
|
+
<div>{marker.content}</div>
|
|
95
|
+
</Details>
|
|
96
|
+
))}
|
|
97
|
+
<Button onClick={() => setOpen(undefined)}>
|
|
98
|
+
<MagnifyingGlassMinusIcon /> Zoom ut
|
|
99
|
+
</Button>
|
|
100
|
+
</Group>
|
|
101
|
+
</Flex>
|
|
102
|
+
);
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const WithColor: Story = {
|
|
107
|
+
render: () => (
|
|
108
|
+
<mtds-atlas data-tiles="color" data-view="63.431958, 10.397461, 12" />
|
|
109
|
+
),
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export const WithCustomSize: Story = {
|
|
113
|
+
render: () => (
|
|
114
|
+
<mtds-atlas style={{ width: "100%", height: "calc(100vh - 30px)" }} />
|
|
115
|
+
),
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export const WithMarker: Story = {
|
|
119
|
+
render: () => (
|
|
120
|
+
<Atlas data-view="60.722, 10.989, 16">
|
|
121
|
+
<Atlas.Marker data-latlng="60.7223, 10.9861" aria-label="Min markør" />
|
|
122
|
+
<Atlas.Marker
|
|
123
|
+
data-color="info"
|
|
124
|
+
data-latlng="60.72235, 10.9837"
|
|
125
|
+
aria-label="Min markør med stjerne"
|
|
126
|
+
>
|
|
127
|
+
<StarIcon weight="fill" />
|
|
128
|
+
</Atlas.Marker>
|
|
129
|
+
<Atlas.Marker
|
|
130
|
+
data-latlng="60.7222, 10.988"
|
|
131
|
+
aria-label="Min markør med tekst"
|
|
132
|
+
>
|
|
133
|
+
A
|
|
134
|
+
</Atlas.Marker>
|
|
135
|
+
</Atlas>
|
|
136
|
+
),
|
|
137
|
+
};
|
|
138
|
+
export const WithMarkerStyling: Story = {
|
|
139
|
+
render: () => (
|
|
140
|
+
<Atlas data-view="60.722, 10.989, 16">
|
|
141
|
+
<Atlas.Marker
|
|
142
|
+
data-latlng="60.72235, 10.9837"
|
|
143
|
+
aria-label="Min markør rød"
|
|
144
|
+
data-color="danger"
|
|
145
|
+
/>
|
|
146
|
+
<Atlas.Marker
|
|
147
|
+
data-latlng="60.7223, 10.9861"
|
|
148
|
+
aria-label="Min markør styled"
|
|
149
|
+
style={
|
|
150
|
+
{
|
|
151
|
+
"--mtdsc-atlas-marker-size": "var(--mtds-10)",
|
|
152
|
+
"--mtdsc-atlas-marker-inset": "var(--mtds-2)",
|
|
153
|
+
"--mtdsc-atlas-marker-color": "var(--mtds-color-info-base-default)",
|
|
154
|
+
"--mtdsc-atlas-marker-border": "2px solid",
|
|
155
|
+
"--mtdsc-atlas-marker-background":
|
|
156
|
+
"var(--mtds-color-info-base-contrast-default)",
|
|
157
|
+
"--mtdsc-atlas-marker-background-outer":
|
|
158
|
+
"var(--mtds-color-info-base-default)",
|
|
159
|
+
} as React.CSSProperties
|
|
160
|
+
}
|
|
161
|
+
/>
|
|
162
|
+
</Atlas>
|
|
163
|
+
),
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const getRandomCoordinates = (lat = 60.722, lng = 10.985) =>
|
|
167
|
+
Array.from({ length: 100 }, () => {
|
|
168
|
+
return `${lat + (Math.random() - 0.5) * 0.025}, ${lng + (Math.random() - 0.5) * 0.1}`;
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
export const WithClustering: Story = {
|
|
172
|
+
render: () => (
|
|
173
|
+
<Atlas data-view={"60.722, 10.985, 12"} data-cluster="true">
|
|
174
|
+
{getRandomCoordinates().map((latlng, index) => (
|
|
175
|
+
<Atlas.Marker
|
|
176
|
+
aria-label={`Markør ${index + 1}`}
|
|
177
|
+
key={index.toString()}
|
|
178
|
+
data-latlng={latlng}
|
|
179
|
+
popoverTarget="my-cluster-popover"
|
|
180
|
+
/>
|
|
181
|
+
))}
|
|
182
|
+
<Popover id="my-cluster-popover">Popover</Popover>
|
|
183
|
+
</Atlas>
|
|
184
|
+
),
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export const WithPopover: Story = {
|
|
188
|
+
render: () => (
|
|
189
|
+
<Atlas data-view="60.722, 10.985, 16">
|
|
190
|
+
<Atlas.Marker
|
|
191
|
+
aria-label="Markør 1"
|
|
192
|
+
data-latlng="60.722, 10.985"
|
|
193
|
+
popoverTarget="popover-1"
|
|
194
|
+
/>
|
|
195
|
+
<Atlas.Marker
|
|
196
|
+
aria-label="Markør 2"
|
|
197
|
+
data-latlng="60.721, 10.980"
|
|
198
|
+
popoverTarget="popover-2"
|
|
199
|
+
/>
|
|
200
|
+
<Popover id="popover-1">Popover 1</Popover>
|
|
201
|
+
<Popover id="popover-2">Popover 2</Popover>
|
|
202
|
+
</Atlas>
|
|
203
|
+
),
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
export const WithPopoverDynamic: Story = {
|
|
207
|
+
render: function Render() {
|
|
208
|
+
const [open, setOpen] = useState(-1);
|
|
209
|
+
const markers = [
|
|
210
|
+
{ latlng: "60.722, 10.985", popover: "Min nydelige popover" },
|
|
211
|
+
{
|
|
212
|
+
latlng: "60.721, 10.980",
|
|
213
|
+
popover: (
|
|
214
|
+
<Prose>
|
|
215
|
+
<Heading>Avansert popover</Heading>
|
|
216
|
+
<p>Innhold</p>
|
|
217
|
+
</Prose>
|
|
218
|
+
),
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
return (
|
|
223
|
+
<Atlas data-view="60.722, 10.985, 16">
|
|
224
|
+
{markers.map((marker, index) => (
|
|
225
|
+
<Atlas.Marker
|
|
226
|
+
aria-label={`Markør ${index + 1}`}
|
|
227
|
+
data-latlng={marker.latlng}
|
|
228
|
+
key={index.toString()}
|
|
229
|
+
onClick={() => setOpen(index)}
|
|
230
|
+
popoverTarget="my-popover"
|
|
231
|
+
/>
|
|
232
|
+
))}
|
|
233
|
+
<Popover id="my-popover">{markers[open]?.popover}</Popover>
|
|
234
|
+
</Atlas>
|
|
235
|
+
);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export const WithMatgeo: Story = {
|
|
240
|
+
render: () => {
|
|
241
|
+
const [content, setContent] = useState("");
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<Atlas data-view="60.722, 10.985, 16">
|
|
245
|
+
<Atlas.Matgeo
|
|
246
|
+
data-collection="bygg"
|
|
247
|
+
popoverTarget="my-matgeo-popover"
|
|
248
|
+
onFeatureClick={(event) => {
|
|
249
|
+
setContent(
|
|
250
|
+
JSON.stringify(
|
|
251
|
+
event.detail.targets.map((layer) => layer.feature?.properties),
|
|
252
|
+
null,
|
|
253
|
+
" ",
|
|
254
|
+
),
|
|
255
|
+
);
|
|
256
|
+
}}
|
|
257
|
+
/>
|
|
258
|
+
<Popover as={Prose} id="my-matgeo-popover">
|
|
259
|
+
<pre data-size="sm">{content}</pre>
|
|
260
|
+
</Popover>
|
|
261
|
+
</Atlas>
|
|
262
|
+
);
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
export const WithMatgeoToggle: Story = {
|
|
267
|
+
render: () => {
|
|
268
|
+
const atlasRef = useRef<MTDSAtlasElement>(null);
|
|
269
|
+
const colors = ["info", "success", "warning", "danger"] as const;
|
|
270
|
+
const [content, setContent] = useState("");
|
|
271
|
+
const [collections, setCollections] = useState<
|
|
272
|
+
(MTDSAtlasCollection & { hidden?: boolean })[]
|
|
273
|
+
>([]);
|
|
274
|
+
|
|
275
|
+
const handleFeatureClick: AtlasMatgeoProps["onFeatureClick"] = (event) => {
|
|
276
|
+
const targets = event.detail.targets;
|
|
277
|
+
const props = targets.map((layer) => layer.feature?.properties);
|
|
278
|
+
setContent(JSON.stringify(props, null, " "));
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
useEffect(() => {
|
|
282
|
+
atlasRef.current
|
|
283
|
+
?.getCollections()
|
|
284
|
+
.then((collections) => setCollections(Object.values(collections)));
|
|
285
|
+
}, []);
|
|
286
|
+
|
|
287
|
+
return (
|
|
288
|
+
<Flex data-nowrap data-items="300">
|
|
289
|
+
<Atlas ref={atlasRef} data-view="60.722, 10.985, 16">
|
|
290
|
+
{collections.map((collection, index) => (
|
|
291
|
+
<Atlas.Matgeo
|
|
292
|
+
hidden={collection.hidden}
|
|
293
|
+
key={collection.id}
|
|
294
|
+
data-collection={collection.id}
|
|
295
|
+
data-color={colors[index % colors.length]}
|
|
296
|
+
popoverTarget="my-matgeo-popover"
|
|
297
|
+
onFeatureClick={handleFeatureClick}
|
|
298
|
+
/>
|
|
299
|
+
))}
|
|
300
|
+
<Popover as={Prose} id="my-matgeo-popover">
|
|
301
|
+
<pre data-size="sm">{content}</pre>
|
|
302
|
+
</Popover>
|
|
303
|
+
</Atlas>
|
|
304
|
+
<Group data-fixed>
|
|
305
|
+
<Fieldset aria-label="Lag">
|
|
306
|
+
{collections.map((collection, index) => (
|
|
307
|
+
<Field
|
|
308
|
+
as="input"
|
|
309
|
+
type="checkbox"
|
|
310
|
+
key={collection.id}
|
|
311
|
+
data-color={colors[index % colors.length]}
|
|
312
|
+
checked={!collection.hidden}
|
|
313
|
+
label={collection.title}
|
|
314
|
+
onChange={() => {
|
|
315
|
+
const clone = collections.slice();
|
|
316
|
+
clone[index].hidden = !clone[index].hidden;
|
|
317
|
+
setCollections(clone);
|
|
318
|
+
}}
|
|
319
|
+
/>
|
|
320
|
+
))}
|
|
321
|
+
</Fieldset>
|
|
322
|
+
</Group>
|
|
323
|
+
</Flex>
|
|
324
|
+
);
|
|
325
|
+
},
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
export const WithWMS: Story = {
|
|
329
|
+
render: () => (
|
|
330
|
+
<Atlas data-view="63.431958, 10.397461, 16">
|
|
331
|
+
<Atlas.WMS data-url="https://wms.geonorge.no/skwms1/wms.matrikkel?request=GetMap&version=1.3.0&layers=matrikkel_WMS&format=image/png&transparent=true" />
|
|
332
|
+
</Atlas>
|
|
333
|
+
),
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
export const WithTooltip: Story = {
|
|
337
|
+
render: () => (
|
|
338
|
+
<Atlas data-view="60.722, 10.985, 16">
|
|
339
|
+
<Atlas.Marker data-latlng="60.722, 10.985" data-tooltip="Mitt tooltip" />
|
|
340
|
+
</Atlas>
|
|
341
|
+
),
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
export const WithClickToAddMarker: Story = {
|
|
345
|
+
render: function Render() {
|
|
346
|
+
const atlasRef = useRef<MTDSAtlasElement>(null);
|
|
347
|
+
const [markers, setMarkers] = useState<string[]>([]);
|
|
348
|
+
|
|
349
|
+
return (
|
|
350
|
+
<>
|
|
351
|
+
<Atlas
|
|
352
|
+
role="application"
|
|
353
|
+
ref={atlasRef}
|
|
354
|
+
data-cursor="pointer"
|
|
355
|
+
data-view="60.722, 10.985, 16"
|
|
356
|
+
onClick={({ currentTarget: atlas, clientX, clientY, target }) => {
|
|
357
|
+
if (atlas !== target) return; // Only add if clicking directly on map
|
|
358
|
+
const latlng = atlas.latLngFromPoint(clientX, clientY);
|
|
359
|
+
setMarkers([...markers, `${latlng?.lat}, ${latlng?.lng}`]);
|
|
360
|
+
toast(<code>{`${latlng}`}</code>);
|
|
361
|
+
}}
|
|
362
|
+
>
|
|
363
|
+
{markers.map((latlng, index) => (
|
|
364
|
+
<Atlas.Marker
|
|
365
|
+
key={index.toString()}
|
|
366
|
+
data-latlng={latlng}
|
|
367
|
+
aria-label={`Markør ${index + 1}`}
|
|
368
|
+
draggable
|
|
369
|
+
onClick={() => {
|
|
370
|
+
const clone = [...markers];
|
|
371
|
+
clone.splice(index, 1); // Remove marker
|
|
372
|
+
setMarkers(clone);
|
|
373
|
+
}}
|
|
374
|
+
onDragEnd={(event) => {
|
|
375
|
+
const clone = [...markers];
|
|
376
|
+
clone[index] = event.currentTarget.latlng;
|
|
377
|
+
setMarkers(clone);
|
|
378
|
+
}}
|
|
379
|
+
>
|
|
380
|
+
{index + 1}
|
|
381
|
+
</Atlas.Marker>
|
|
382
|
+
))}
|
|
383
|
+
</Atlas>
|
|
384
|
+
<ol>
|
|
385
|
+
<li>Klikk på kartet for å legge til markør</li>
|
|
386
|
+
<li>Dra markør for å flytte</li>
|
|
387
|
+
<li>Klikk på markør for å fjerne</li>
|
|
388
|
+
</ol>
|
|
389
|
+
</>
|
|
390
|
+
);
|
|
391
|
+
},
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
export const WithoutScrollZoom: Story = {
|
|
395
|
+
render: () => (
|
|
396
|
+
<Prose>
|
|
397
|
+
<p>{LOREM_IPSUM}</p>
|
|
398
|
+
<Atlas data-scrollzoom="false" />
|
|
399
|
+
<p>{LOREM_IPSUM}</p>
|
|
400
|
+
</Prose>
|
|
401
|
+
),
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
// export const WithGeoJSON: Story = {
|
|
405
|
+
// render: () => {
|
|
406
|
+
// const atlasRef = useRef<MTDSAtlasElement>(null);
|
|
407
|
+
|
|
408
|
+
// useEffect(() => {
|
|
409
|
+
// const map = atlasRef.current?.map;
|
|
410
|
+
// const url =
|
|
411
|
+
// "https://mattilsynet.avadaptive.dev/api/core/v1/ogc/features/collections/slammelding_spredeareal/items";
|
|
412
|
+
|
|
413
|
+
// if (!map) return;
|
|
414
|
+
// fetch(url)
|
|
415
|
+
// .then((res) => res.json())
|
|
416
|
+
// .then((data) => {
|
|
417
|
+
// console.log(data);
|
|
418
|
+
// L.geoJSON(data).addTo(map);
|
|
419
|
+
// });
|
|
420
|
+
// }, []);
|
|
421
|
+
|
|
422
|
+
// return <Atlas ref={atlasRef} />;
|
|
423
|
+
// },
|
|
424
|
+
// };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import { Example, CssVariables } from '../../.storybook/blocks';
|
|
3
|
+
import * as stories from './avatar.stories';
|
|
4
|
+
import styles from '../styles.module.css';
|
|
5
|
+
import { EnvelopeIcon, UserIcon, FilePdfIcon } from '@phosphor-icons/react';
|
|
6
|
+
import { Flex } from '../react';
|
|
7
|
+
import avatar from "./avatar.jpg";
|
|
8
|
+
|
|
9
|
+
<Meta of={stories} />
|
|
10
|
+
|
|
11
|
+
# Avatar
|
|
12
|
+
> Avatar er en komponent som viser et bilde, initialer eller ikon for en person, enhet eller profil.
|
|
13
|
+
|
|
14
|
+
## Kode
|
|
15
|
+
- Bruk klassen `avatar` på typisk `<span>` eller `<Avatar>` komponenten i React
|
|
16
|
+
<Canvas of={stories.Default} />
|
|
17
|
+
|
|
18
|
+
## Skikk og bruk
|
|
19
|
+
|
|
20
|
+
<Flex data-items="350">
|
|
21
|
+
{/* Ikoner i Badge: */}
|
|
22
|
+
<Example data-color="success" text="Avatar kan inneholde tekst, bilde eller ikon som representerer en person eller enhet" zoom="100%">
|
|
23
|
+
<div className={styles.flex}>
|
|
24
|
+
<div className={styles.avatar}>MT</div>
|
|
25
|
+
<div className={styles.avatar}>
|
|
26
|
+
<img src={avatar} alt="Navn Navnesen" />
|
|
27
|
+
</div>
|
|
28
|
+
<div className={styles.avatar}>
|
|
29
|
+
<UserIcon aria-label="Navn Navnesen" />
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</Example>
|
|
33
|
+
<Example data-color="danger" text="Ikke bruk avatar til å representere noe annet enn en person eller enhet, for eksempel et dokument." zoom="100%">
|
|
34
|
+
<div className={styles.avatar}>
|
|
35
|
+
<FilePdfIcon aria-label="PDF fil" />
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
</Example>
|
|
39
|
+
|
|
40
|
+
</Flex>
|
|
41
|
+
|
|
42
|
+
## Sizes
|
|
43
|
+
<Canvas of={stories.Sizes} />
|
|
44
|
+
|
|
45
|
+
<CssVariables component="avatar" />
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { UserIcon } from "@phosphor-icons/react";
|
|
2
|
+
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
3
|
+
import { Avatar } from "../react";
|
|
4
|
+
import styles from "../styles.module.css";
|
|
5
|
+
import avatar from "./avatar.jpg";
|
|
6
|
+
|
|
7
|
+
const meta = {
|
|
8
|
+
title: "Designsystem/Avatar",
|
|
9
|
+
decorators: [
|
|
10
|
+
(Story) => (
|
|
11
|
+
<div className={styles.flex} data-align="center">
|
|
12
|
+
<Story />
|
|
13
|
+
</div>
|
|
14
|
+
),
|
|
15
|
+
],
|
|
16
|
+
} satisfies Meta;
|
|
17
|
+
|
|
18
|
+
export default meta;
|
|
19
|
+
type Story = StoryObj<typeof meta>;
|
|
20
|
+
|
|
21
|
+
export const Default: Story = {
|
|
22
|
+
render: () => (
|
|
23
|
+
<>
|
|
24
|
+
<div className={styles.avatar}>MT</div>
|
|
25
|
+
<div className={styles.avatar}>
|
|
26
|
+
<img src={avatar} alt="Navn Navnesen" />
|
|
27
|
+
</div>
|
|
28
|
+
<div className={styles.avatar}>
|
|
29
|
+
<UserIcon aria-label="Navn Navnesen" />
|
|
30
|
+
</div>
|
|
31
|
+
</>
|
|
32
|
+
),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const React: Story = {
|
|
36
|
+
render: () => (
|
|
37
|
+
<>
|
|
38
|
+
<Avatar>MT</Avatar>
|
|
39
|
+
<Avatar>
|
|
40
|
+
<img src={avatar} alt="Navn Navnesen" />
|
|
41
|
+
</Avatar>
|
|
42
|
+
<Avatar href="#">
|
|
43
|
+
<UserIcon aria-label="Navn Navnesen" />
|
|
44
|
+
</Avatar>
|
|
45
|
+
</>
|
|
46
|
+
),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export const Sizes: Story = {
|
|
50
|
+
render: () => (
|
|
51
|
+
<>
|
|
52
|
+
<div className={styles.avatar} data-size="xs">
|
|
53
|
+
XS
|
|
54
|
+
</div>
|
|
55
|
+
<div className={styles.avatar} data-size="sm">
|
|
56
|
+
SM
|
|
57
|
+
</div>
|
|
58
|
+
<div className={styles.avatar} data-size="md">
|
|
59
|
+
MD
|
|
60
|
+
</div>
|
|
61
|
+
<div className={styles.avatar} data-size="lg">
|
|
62
|
+
LG
|
|
63
|
+
</div>
|
|
64
|
+
</>
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export const WithBadge: Story = {
|
|
69
|
+
render: () => (
|
|
70
|
+
<>
|
|
71
|
+
<div className={styles.badge}>
|
|
72
|
+
<div className={styles.avatar} data-size="xs">
|
|
73
|
+
<img src={avatar} alt="Navn Navnesen" />
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
<div className={styles.badge}>
|
|
77
|
+
<div className={styles.avatar} data-size="sm">
|
|
78
|
+
<img src={avatar} alt="Navn Navnesen" />
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
<div className={styles.badge}>
|
|
82
|
+
<a className={styles.avatar} data-size="md" href="#none">
|
|
83
|
+
<img src={avatar} alt="Navn Navnesen" />
|
|
84
|
+
</a>
|
|
85
|
+
</div>
|
|
86
|
+
<div className={styles.badge}>
|
|
87
|
+
<button type="button" className={styles.avatar} data-size="lg">
|
|
88
|
+
<img src={avatar} alt="Navn Navnesen" />
|
|
89
|
+
</button>
|
|
90
|
+
</div>
|
|
91
|
+
</>
|
|
92
|
+
),
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export const InButton: Story = {
|
|
96
|
+
render: () => (
|
|
97
|
+
<>
|
|
98
|
+
<button type="button" className={styles.button}>
|
|
99
|
+
<div className={styles.avatar} data-size="xs">
|
|
100
|
+
NN
|
|
101
|
+
</div>
|
|
102
|
+
Navn Navnesen
|
|
103
|
+
</button>
|
|
104
|
+
<button type="button" className={styles.button}>
|
|
105
|
+
More buttons
|
|
106
|
+
</button>
|
|
107
|
+
</>
|
|
108
|
+
),
|
|
109
|
+
};
|