@oslokommune/punkt-react 18.3.0 → 18.3.1
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/CHANGELOG.md +17 -0
- package/dist/components/linkcard/LinkCard.d.ts +4 -8
- package/dist/punkt-react.cjs +1 -1
- package/dist/punkt-react.js +10 -5
- package/dist/shared-strings/nb.d.ts +3 -0
- package/dist/shared-types/index.d.ts +2 -0
- package/dist/shared-types/linkcard.d.ts +24 -0
- package/package.json +3 -3
- package/src/components/linkcard/LinkCard.test.tsx +43 -0
- package/src/components/linkcard/LinkCard.tsx +12 -7
- package/src/components/strings/strings-override.test.tsx +13 -0
package/dist/punkt-react.js
CHANGED
|
@@ -278,6 +278,7 @@ var ce = {
|
|
|
278
278
|
},
|
|
279
279
|
backlink: { label: "Gå tilbake til forrige side" },
|
|
280
280
|
breadcrumbs: { ariaLabel: "brødsmulemeny" },
|
|
281
|
+
linkcard: { openInNewTab: "Åpnes i ny fane" },
|
|
281
282
|
alert: { lastUpdated: "Sist oppdatert: {date}" },
|
|
282
283
|
tag: { remove: "Klikk for å fjerne {label}" },
|
|
283
284
|
header: {
|
|
@@ -7752,12 +7753,12 @@ var Co = i(({ label: e, id: t, children: n, ...r }, i) => /* @__PURE__ */ v("div
|
|
|
7752
7753
|
Co.displayName = "PktInput";
|
|
7753
7754
|
//#endregion
|
|
7754
7755
|
//#region src/components/linkcard/LinkCard.tsx
|
|
7755
|
-
var wo = ({ children: e, skin: t, title: n, href: r, iconName: i, openInNewTab: a, external: o, className: s,
|
|
7756
|
-
let
|
|
7756
|
+
var wo = ({ children: e, skin: t, title: n, href: r, iconName: i, openInNewTab: a, external: o, className: s, strings: c, ...l }) => {
|
|
7757
|
+
let u = _e(["linkcard"], c), d = ["pkt-linkcard", t && `pkt-linkcard--${t}`].filter(Boolean).join(" "), f = ["pkt-linkcard__title", o && "pkt-link pkt-link--external"].filter(Boolean).join(" ");
|
|
7757
7758
|
return /* @__PURE__ */ v("a", {
|
|
7758
|
-
...
|
|
7759
|
+
...l,
|
|
7759
7760
|
href: r,
|
|
7760
|
-
className: (0, M.default)(
|
|
7761
|
+
className: (0, M.default)(d, s),
|
|
7761
7762
|
target: a ? "_blank" : "_self",
|
|
7762
7763
|
rel: a ? "noopener noreferrer" : void 0,
|
|
7763
7764
|
children: [
|
|
@@ -7766,9 +7767,13 @@ var wo = ({ children: e, skin: t, title: n, href: r, iconName: i, openInNewTab:
|
|
|
7766
7767
|
name: i
|
|
7767
7768
|
}),
|
|
7768
7769
|
n && /* @__PURE__ */ _("div", {
|
|
7769
|
-
className: (0, M.default)(
|
|
7770
|
+
className: (0, M.default)(f),
|
|
7770
7771
|
children: n
|
|
7771
7772
|
}),
|
|
7773
|
+
a && u.linkcard.openInNewTab ? /* @__PURE__ */ _("span", {
|
|
7774
|
+
className: "pkt-sr-only",
|
|
7775
|
+
children: u.linkcard.openInNewTab
|
|
7776
|
+
}) : null,
|
|
7772
7777
|
/* @__PURE__ */ _("div", {
|
|
7773
7778
|
className: "pkt-linkcard__text",
|
|
7774
7779
|
children: e
|
|
@@ -15,6 +15,8 @@ export type { TPktInputSize, TSize3, TSize5, TSize7 } from './size';
|
|
|
15
15
|
export { ACCORDION_SKINS } from './accordion';
|
|
16
16
|
export type { TAccordionSkin, IPktAccordionBase, IPktAccordionItemBase, IAccordionSpecProps, IAccordionItemSpecProps, IAccordionVisualProps, } from './accordion';
|
|
17
17
|
export type { IPktBackLinkBase, IBacklinkSpecProps } from './backlink';
|
|
18
|
+
export { LINKCARD_SKINS } from './linkcard';
|
|
19
|
+
export type { TLinkCardSkin, IPktLinkCardBase, ILinkcardSpecProps } from './linkcard';
|
|
18
20
|
export { BREADCRUMBS_NAVIGATION_TYPES } from './breadcrumbs';
|
|
19
21
|
export type { TBreadcrumbsNavigationType, IBreadcrumb, IBreadcrumbItem, IBreadcrumbs, IPktBreadcrumbsBase, IBreadcrumbsSpecProps, } from './breadcrumbs';
|
|
20
22
|
export type { IRenderLink, TRenderLink } from './render-link';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* linkcard.ts
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for pkt-linkcard.
|
|
5
|
+
* Used by React, Elements, and typed component specs.
|
|
6
|
+
*/
|
|
7
|
+
import type { IPktStringsProps } from '../shared-strings';
|
|
8
|
+
/** LinkCard skin variants — shared runtime source for types, specs, and Preview. */
|
|
9
|
+
export declare const LINKCARD_SKINS: readonly ['normal', 'no-padding', 'blue', 'beige', 'green', 'gray', 'beige-outline', 'gray-outline'];
|
|
10
|
+
export type TLinkCardSkin = (typeof LINKCARD_SKINS)[number];
|
|
11
|
+
/** Shared LinkCard props for React, Elements, and typed specs. */
|
|
12
|
+
export type IPktLinkCardBase = IPktStringsProps<'linkcard'> & {
|
|
13
|
+
title?: string;
|
|
14
|
+
href?: string;
|
|
15
|
+
skin?: TLinkCardSkin;
|
|
16
|
+
iconName?: string;
|
|
17
|
+
openInNewTab?: boolean;
|
|
18
|
+
external?: boolean;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Documented LinkCard props (subset of `IPktLinkCardBase`).
|
|
22
|
+
* Used for typed component specs in documentation.
|
|
23
|
+
*/
|
|
24
|
+
export type ILinkcardSpecProps = Pick<IPktLinkCardBase, 'title' | 'href' | 'skin' | 'iconName' | 'openInNewTab' | 'external'>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oslokommune/punkt-react",
|
|
3
|
-
"version": "18.3.
|
|
3
|
+
"version": "18.3.1",
|
|
4
4
|
"description": "React komponentbibliotek til Punkt, et designsystem laget av Oslo Origo",
|
|
5
5
|
"homepage": "https://punkt.oslo.kommune.no",
|
|
6
6
|
"author": "Team Designsystem, Oslo Origo",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@eslint/eslintrc": "^3.3.5",
|
|
46
46
|
"@eslint/js": "^10.0.1",
|
|
47
47
|
"@oslokommune/punkt-assets": "^18.0.0",
|
|
48
|
-
"@oslokommune/punkt-css": "^18.3.
|
|
48
|
+
"@oslokommune/punkt-css": "^18.3.1",
|
|
49
49
|
"@testing-library/jest-dom": "^6.9.1",
|
|
50
50
|
"@testing-library/react": "^16.3.2",
|
|
51
51
|
"@testing-library/user-event": "^14.6.1",
|
|
@@ -102,5 +102,5 @@
|
|
|
102
102
|
"url": "https://github.com/oslokommune/punkt/issues"
|
|
103
103
|
},
|
|
104
104
|
"license": "MIT",
|
|
105
|
-
"gitHead": "
|
|
105
|
+
"gitHead": "076395b7934546d637a3136ac35eef4583d8f8a7"
|
|
106
106
|
}
|
|
@@ -3,6 +3,7 @@ import '@testing-library/jest-dom'
|
|
|
3
3
|
|
|
4
4
|
import { render } from '@testing-library/react'
|
|
5
5
|
import { axe, toHaveNoViolations } from 'jest-axe'
|
|
6
|
+
import { nb } from 'shared-strings'
|
|
6
7
|
|
|
7
8
|
import { PktLinkCard } from './LinkCard'
|
|
8
9
|
|
|
@@ -103,6 +104,48 @@ describe('PktLinkCard', () => {
|
|
|
103
104
|
})
|
|
104
105
|
})
|
|
105
106
|
|
|
107
|
+
describe('openInNewTab strings', () => {
|
|
108
|
+
it('does not announce a new-tab string when openInNewTab is unset', () => {
|
|
109
|
+
const { container, queryByText } = render(<PktLinkCard title="Normal">Content</PktLinkCard>)
|
|
110
|
+
expect(container.querySelector('.pkt-sr-only')).not.toBeInTheDocument()
|
|
111
|
+
expect(queryByText(nb.linkcard.openInNewTab)).not.toBeInTheDocument()
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
it('uses the catalogue default when strings is omitted', () => {
|
|
115
|
+
const { getByText } = render(
|
|
116
|
+
<PktLinkCard title="Normal" openInNewTab>
|
|
117
|
+
Content
|
|
118
|
+
</PktLinkCard>,
|
|
119
|
+
)
|
|
120
|
+
const srOnly = getByText(nb.linkcard.openInNewTab)
|
|
121
|
+
expect(srOnly).toHaveClass('pkt-sr-only')
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('uses a custom override from the strings prop', () => {
|
|
125
|
+
const { getByText, queryByText } = render(
|
|
126
|
+
<PktLinkCard
|
|
127
|
+
title="Normal"
|
|
128
|
+
openInNewTab
|
|
129
|
+
strings={{ linkcard: { openInNewTab: 'Opens in a new tab' } }}
|
|
130
|
+
>
|
|
131
|
+
Content
|
|
132
|
+
</PktLinkCard>,
|
|
133
|
+
)
|
|
134
|
+
expect(getByText('Opens in a new tab')).toHaveClass('pkt-sr-only')
|
|
135
|
+
expect(queryByText(nb.linkcard.openInNewTab)).not.toBeInTheDocument()
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
it('hides the announcement when the override is an empty string', () => {
|
|
139
|
+
const { container, queryByText } = render(
|
|
140
|
+
<PktLinkCard title="Normal" openInNewTab strings={{ linkcard: { openInNewTab: '' } }}>
|
|
141
|
+
Content
|
|
142
|
+
</PktLinkCard>,
|
|
143
|
+
)
|
|
144
|
+
expect(container.querySelector('.pkt-sr-only')).not.toBeInTheDocument()
|
|
145
|
+
expect(queryByText(nb.linkcard.openInNewTab)).not.toBeInTheDocument()
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
|
|
106
149
|
// ACCESSIBILITY TESTS
|
|
107
150
|
|
|
108
151
|
describe('accessibility', () => {
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import { HTMLAttributes, ReactNode } from 'react'
|
|
5
|
+
import type { IPktLinkCardBase, TLinkCardSkin } from 'shared-types'
|
|
5
6
|
|
|
6
7
|
import { PktIcon } from '../icon/Icon'
|
|
8
|
+
import { usePktStrings } from '../../hooks/usePktStrings'
|
|
7
9
|
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
openInNewTab?: boolean
|
|
14
|
-
external?: boolean
|
|
10
|
+
export type { TLinkCardSkin }
|
|
11
|
+
|
|
12
|
+
export interface IPktLinkCard
|
|
13
|
+
extends IPktLinkCardBase,
|
|
14
|
+
Omit<HTMLAttributes<HTMLAnchorElement>, 'title'> {
|
|
15
15
|
children?: ReactNode
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -24,8 +24,10 @@ export const PktLinkCard = ({
|
|
|
24
24
|
openInNewTab,
|
|
25
25
|
external,
|
|
26
26
|
className,
|
|
27
|
+
strings,
|
|
27
28
|
...props
|
|
28
29
|
}: IPktLinkCard) => {
|
|
30
|
+
const s = usePktStrings(['linkcard'], strings)
|
|
29
31
|
const classes = ['pkt-linkcard', skin && `pkt-linkcard--${skin}`].filter(Boolean).join(' ')
|
|
30
32
|
|
|
31
33
|
const titleClasses = ['pkt-linkcard__title', external && 'pkt-link pkt-link--external'].filter(Boolean).join(' ')
|
|
@@ -40,6 +42,9 @@ export const PktLinkCard = ({
|
|
|
40
42
|
>
|
|
41
43
|
{iconName && <PktIcon className="pkt-link__icon" name={iconName} />}
|
|
42
44
|
{title && <div className={classNames(titleClasses)}>{title}</div>}
|
|
45
|
+
{openInNewTab && s.linkcard.openInNewTab ? (
|
|
46
|
+
<span className="pkt-sr-only">{s.linkcard.openInNewTab}</span>
|
|
47
|
+
) : null}
|
|
43
48
|
<div className="pkt-linkcard__text">{children}</div>
|
|
44
49
|
</a>
|
|
45
50
|
)
|
|
@@ -5,6 +5,7 @@ import { resetPktStrings, setPktStrings } from 'shared-strings'
|
|
|
5
5
|
import { PktBackLink } from '../backlink/BackLink'
|
|
6
6
|
import { PktBreadcrumbs } from '../breadcrumbs/Breadcrumbs'
|
|
7
7
|
import { PktFileUpload } from '../fileupload/FileUpload'
|
|
8
|
+
import { PktLinkCard } from '../linkcard/LinkCard'
|
|
8
9
|
import { PktSearchInput } from '../searchinput/SearchInput'
|
|
9
10
|
import { PktTextinput } from '../textinput/Textinput'
|
|
10
11
|
import { PktStringsProvider } from './PktStringsProvider'
|
|
@@ -25,6 +26,18 @@ describe('strings-propen per komponent', () => {
|
|
|
25
26
|
expect(screen.getByLabelText('Tilbake til lista')).toBeInTheDocument()
|
|
26
27
|
})
|
|
27
28
|
|
|
29
|
+
test('linkcard bruker teksten fra propen', () => {
|
|
30
|
+
render(
|
|
31
|
+
<PktLinkCard
|
|
32
|
+
title="Dokument"
|
|
33
|
+
href="/"
|
|
34
|
+
openInNewTab
|
|
35
|
+
strings={{ linkcard: { openInNewTab: 'Opens in a new tab' } }}
|
|
36
|
+
/>,
|
|
37
|
+
)
|
|
38
|
+
expect(screen.getByText('Opens in a new tab')).toBeInTheDocument()
|
|
39
|
+
})
|
|
40
|
+
|
|
28
41
|
test('breadcrumbs bruker teksten fra propen', () => {
|
|
29
42
|
render(
|
|
30
43
|
<PktBreadcrumbs
|