@oslokommune/punkt-elements 12.37.8 → 12.38.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/CHANGELOG.md CHANGED
@@ -5,6 +5,43 @@ og skriver commits ca etter [Conventional Commits](https://conventionalcommits.o
5
5
 
6
6
  ---
7
7
 
8
+ ## [12.38.0](https://github.com/oslokommune/punkt/compare/12.37.8...12.38.0) (2025-05-13)
9
+
10
+ ### ⚠ BREAKING CHANGES
11
+ Ingen
12
+
13
+ ### Features
14
+ * Refaktorering og forbedringer av kort – klikkbart lenkekort, runde bilder, tilgjengelighet, semantikk, fleksibilitet, styling (#2511). Lagt til støtte for:
15
+ - Tilgjenglig, klikkbart lenkekort
16
+ - Variabel tagposisjon
17
+ - Runde bilder
18
+ - Responsivitet
19
+ - Fokus på rammen av kortet
20
+ - Valgfri hover på rammen av kortet
21
+ - Variant uten padding
22
+ - Ny skin: outlined-beige
23
+ - forfatter
24
+ - dato
25
+
26
+ Annet:
27
+ - Bruker ny headingkomponent
28
+ - Støtte for valg av headingnivå
29
+ - Semantisk HTML med article, header, section og footer
30
+ - Fokusert på UU og lagt til aria-label og roller på ulike deler av kortet
31
+ - Kortet går nå fra landskap til portett på små skjermer
32
+ - Mange stylingendringer
33
+ - Håndterer nå at brukere ikke cropper bilder på forhånd slik at de ved ulike størrelser allikevel får uniforme størrelser på bildene i kortene
34
+
35
+
36
+ ### Bug Fixes
37
+ Ingen
38
+
39
+ ### Chores
40
+ Ingen
41
+
42
+ ---
43
+
44
+
8
45
  ## [12.37.8](https://github.com/oslokommune/punkt/compare/12.37.7...12.37.8) (2025-05-13)
9
46
 
10
47
  ### ⚠ BREAKING CHANGES
@@ -0,0 +1,231 @@
1
+ import { e as c } from "./class-map-KyMqi0fa.js";
2
+ import { o as g } from "./if-defined-BErSJCeJ.js";
3
+ import { P as u, E as d, x as t, n as r, a as $ } from "./element-DjjF_tEh.js";
4
+ import { P as m } from "./pkt-slot-controller-DtDaD9q_.js";
5
+ import { e as _, n as y } from "./ref-iIffqQAI.js";
6
+ import "./icon-Beoxup8E.js";
7
+ import "./tag-Cu8afZy8.js";
8
+ const b = {
9
+ skin: {
10
+ default: "outlined"
11
+ },
12
+ direction: {
13
+ default: "portrait"
14
+ },
15
+ padding: {
16
+ default: "standard"
17
+ }
18
+ }, k = {
19
+ props: b
20
+ };
21
+ var f = Object.defineProperty, S = Object.getOwnPropertyDescriptor, i = (a, s, p, o) => {
22
+ for (var n = o > 1 ? void 0 : o ? S(s, p) : s, h = a.length - 1, l; h >= 0; h--)
23
+ (l = a[h]) && (n = (o ? l(s, p, n) : l(n)) || n);
24
+ return o && n && f(s, p, n), n;
25
+ };
26
+ let e = class extends u {
27
+ //Constructor
28
+ constructor() {
29
+ super(), this.defaultSlot = _(), this.ariaLabel = "", this.author = null, this.borderOnHover = !0, this.clickCardLink = null, this.date = null, this.direction = k.props.direction.default, this.heading = "", this.headinglevel = 3, this.image = {
30
+ src: "",
31
+ alt: ""
32
+ }, this.imageShape = "square", this.openLinkInNewTab = !1, this.padding = k.props.padding.default, this.skin = k.props.skin.default, this.subheading = "", this.tagPosition = "top", this.tags = [], this.slotController = new m(this, this.defaultSlot);
33
+ }
34
+ connectedCallback() {
35
+ super.connectedCallback();
36
+ }
37
+ // Render methods
38
+ // Main render method
39
+ // prettier-ignore
40
+ render() {
41
+ var o, n;
42
+ const a = {
43
+ "pkt-card": !0,
44
+ [`pkt-card--${this.skin}`]: this.skin,
45
+ [`pkt-card--${this.direction}`]: this.direction,
46
+ [`pkt-card--padding-${this.padding}`]: this.padding,
47
+ "pkt-card--border-on-hover": this.borderOnHover
48
+ }, s = ((o = this.ariaLabel) == null ? void 0 : o.trim()) || (this.heading ? `${this.heading} lenkekort` : "lenkekort"), p = ((n = this.ariaLabel) == null ? void 0 : n.trim()) || (this.heading ? this.heading : "kort");
49
+ return t`
50
+ <article
51
+ class=${c(a)}
52
+ aria-label=${g(this.clickCardLink ? s : p)}
53
+ >
54
+ ${this.renderImage()}
55
+ <div class="pkt-card__wrapper">
56
+ ${this.tagPosition === "top" ? this.renderTags() : d}
57
+ ${this.renderHeader()}
58
+ ${this.renderSlot()}
59
+ ${this.tagPosition === "bottom" ? this.renderTags() : d}
60
+ ${this.renderCreditline()}
61
+ </div>
62
+ </article>
63
+ `;
64
+ }
65
+ // Render methods for different parts of the card
66
+ renderImage() {
67
+ const a = {
68
+ "pkt-card__image": !0,
69
+ [`pkt-card__image-${this.imageShape}`]: this.imageShape
70
+ };
71
+ return t`
72
+ ${this.image.src && t`
73
+ <div class=${c(a)}>
74
+ <img src=${this.image.src} alt=${this.image.alt || ""} />
75
+ </div>
76
+ `}
77
+ `;
78
+ }
79
+ // Do not render heading if link is present, render link heading instead
80
+ // Combine the rendering for headings into a renderHeader method
81
+ renderHeading() {
82
+ return t`
83
+ ${this.heading && !this.clickCardLink ? t`
84
+ <pkt-heading
85
+ class="pkt-card__heading"
86
+ .level=${this.headinglevel || 3}
87
+ size="medium"
88
+ nospacing
89
+ >
90
+ ${this.heading}
91
+ </pkt-heading>
92
+ ` : d}
93
+ `;
94
+ }
95
+ renderLinkHeading() {
96
+ return t`
97
+ ${this.clickCardLink ? t`
98
+ <pkt-heading
99
+ class="pkt-card__link-heading pkt-card__heading"
100
+ .level=${this.headinglevel || 3}
101
+ size="medium"
102
+ nospacing
103
+ >
104
+ <a
105
+ class="pkt-card__link"
106
+ href=${this.clickCardLink}
107
+ target=${this.openLinkInNewTab ? "_blank" : "_self"}
108
+ >${this.heading}</a
109
+ >
110
+ </pkt-heading>
111
+ ` : d}
112
+ `;
113
+ }
114
+ renderSubheading() {
115
+ return t`
116
+ ${this.subheading ? t` <p class="pkt-card__subheading ">${this.subheading}</p> ` : d}
117
+ `;
118
+ }
119
+ // Render header
120
+ // prettier-ignore
121
+ renderHeader() {
122
+ const a = !!this.heading || !!this.subheading;
123
+ return t`
124
+ ${a ? t`
125
+ <header class="pkt-card__header">
126
+ ${this.renderHeading()}
127
+ ${this.renderLinkHeading()}
128
+ ${this.renderSubheading()}
129
+ </header>
130
+ ` : d}
131
+ `;
132
+ }
133
+ renderTags() {
134
+ const a = {
135
+ "pkt-card__tags": !0,
136
+ [`pkt-card__tags-${this.tagPosition}`]: this.tagPosition
137
+ };
138
+ return t`
139
+ ${this.tags.length > 0 ? t`
140
+ <div
141
+ class=${c(a)}
142
+ role="list"
143
+ aria-label=${this.tags.length > 1 ? "merkelapper" : "merkelapp"}
144
+ >
145
+ ${this.tags.map(
146
+ (s) => t`
147
+ <pkt-tag
148
+ role="listitem"
149
+ textStyle="normal-text"
150
+ size="medium"
151
+ skin=${g(s.skin)}
152
+ iconName=${g(s.iconName)}
153
+ >
154
+ ${s.text}
155
+ </pkt-tag>
156
+ `
157
+ )}
158
+ </div>
159
+ ` : d}
160
+ `;
161
+ }
162
+ renderSlot() {
163
+ return t`
164
+ ${this.defaultSlot && t`<section class="pkt-card__content" ${y(this.defaultSlot)}></section>`}
165
+ `;
166
+ }
167
+ renderCreditline() {
168
+ return t`
169
+ ${this.author || this.date ? t`
170
+ <footer class="pkt-card__creditline">
171
+ ${this.author ? t`<span class="pkt-card__creditline-author">${this.author}</span>` : d}
172
+ ${this.date ? t`<span class="pkt-card__creditline-date">${this.date}</span>` : d}
173
+ </footer>
174
+ ` : d}
175
+ `;
176
+ }
177
+ };
178
+ i([
179
+ r({ type: String })
180
+ ], e.prototype, "ariaLabel", 2);
181
+ i([
182
+ r({ type: String })
183
+ ], e.prototype, "author", 2);
184
+ i([
185
+ r({ type: Boolean })
186
+ ], e.prototype, "borderOnHover", 2);
187
+ i([
188
+ r({ type: String, reflect: !0 })
189
+ ], e.prototype, "clickCardLink", 2);
190
+ i([
191
+ r({ type: String })
192
+ ], e.prototype, "date", 2);
193
+ i([
194
+ r({ type: String })
195
+ ], e.prototype, "direction", 2);
196
+ i([
197
+ r({ type: String })
198
+ ], e.prototype, "heading", 2);
199
+ i([
200
+ r({ type: Number })
201
+ ], e.prototype, "headinglevel", 2);
202
+ i([
203
+ r({ type: Object })
204
+ ], e.prototype, "image", 2);
205
+ i([
206
+ r({ type: String })
207
+ ], e.prototype, "imageShape", 2);
208
+ i([
209
+ r({ type: Boolean })
210
+ ], e.prototype, "openLinkInNewTab", 2);
211
+ i([
212
+ r({ type: String })
213
+ ], e.prototype, "padding", 2);
214
+ i([
215
+ r({ type: String })
216
+ ], e.prototype, "skin", 2);
217
+ i([
218
+ r({ type: String })
219
+ ], e.prototype, "subheading", 2);
220
+ i([
221
+ r({ type: String })
222
+ ], e.prototype, "tagPosition", 2);
223
+ i([
224
+ r({ type: Array })
225
+ ], e.prototype, "tags", 2);
226
+ e = i([
227
+ $("pkt-card")
228
+ ], e);
229
+ export {
230
+ e as P
231
+ };
@@ -0,0 +1,87 @@
1
+ "use strict";const p=require("./class-map-DCyaICmy.cjs"),h=require("./if-defined-a3sotaUr.cjs"),t=require("./element-BSypUpzA.cjs"),g=require("./pkt-slot-controller-Da-RgXfS.cjs"),c=require("./ref-BvbyvXRH.cjs");require("./icon-BnKGwYjj.cjs");require("./tag-B9kFYxHg.cjs");const k={skin:{default:"outlined"},direction:{default:"portrait"},padding:{default:"standard"}},l={props:k};var u=Object.defineProperty,$=Object.getOwnPropertyDescriptor,e=(d,i,a,n)=>{for(var r=n>1?void 0:n?$(i,a):i,s=d.length-1,o;s>=0;s--)(o=d[s])&&(r=(n?o(i,a,r):o(r))||r);return n&&r&&u(i,a,r),r};exports.PktCard=class extends t.PktElement{constructor(){super(),this.defaultSlot=c.e(),this.ariaLabel="",this.author=null,this.borderOnHover=!0,this.clickCardLink=null,this.date=null,this.direction=l.props.direction.default,this.heading="",this.headinglevel=3,this.image={src:"",alt:""},this.imageShape="square",this.openLinkInNewTab=!1,this.padding=l.props.padding.default,this.skin=l.props.skin.default,this.subheading="",this.tagPosition="top",this.tags=[],this.slotController=new g.PktSlotController(this,this.defaultSlot)}connectedCallback(){super.connectedCallback()}render(){var r,s;const i={"pkt-card":!0,[`pkt-card--${this.skin}`]:this.skin,[`pkt-card--${this.direction}`]:this.direction,[`pkt-card--padding-${this.padding}`]:this.padding,"pkt-card--border-on-hover":this.borderOnHover},a=((r=this.ariaLabel)==null?void 0:r.trim())||(this.heading?`${this.heading} lenkekort`:"lenkekort"),n=((s=this.ariaLabel)==null?void 0:s.trim())||(this.heading?this.heading:"kort");return t.x`
2
+ <article
3
+ class=${p.e(i)}
4
+ aria-label=${h.o(this.clickCardLink?a:n)}
5
+ >
6
+ ${this.renderImage()}
7
+ <div class="pkt-card__wrapper">
8
+ ${this.tagPosition==="top"?this.renderTags():t.E}
9
+ ${this.renderHeader()}
10
+ ${this.renderSlot()}
11
+ ${this.tagPosition==="bottom"?this.renderTags():t.E}
12
+ ${this.renderCreditline()}
13
+ </div>
14
+ </article>
15
+ `}renderImage(){const i={"pkt-card__image":!0,[`pkt-card__image-${this.imageShape}`]:this.imageShape};return t.x`
16
+ ${this.image.src&&t.x`
17
+ <div class=${p.e(i)}>
18
+ <img src=${this.image.src} alt=${this.image.alt||""} />
19
+ </div>
20
+ `}
21
+ `}renderHeading(){return t.x`
22
+ ${this.heading&&!this.clickCardLink?t.x`
23
+ <pkt-heading
24
+ class="pkt-card__heading"
25
+ .level=${this.headinglevel||3}
26
+ size="medium"
27
+ nospacing
28
+ >
29
+ ${this.heading}
30
+ </pkt-heading>
31
+ `:t.E}
32
+ `}renderLinkHeading(){return t.x`
33
+ ${this.clickCardLink?t.x`
34
+ <pkt-heading
35
+ class="pkt-card__link-heading pkt-card__heading"
36
+ .level=${this.headinglevel||3}
37
+ size="medium"
38
+ nospacing
39
+ >
40
+ <a
41
+ class="pkt-card__link"
42
+ href=${this.clickCardLink}
43
+ target=${this.openLinkInNewTab?"_blank":"_self"}
44
+ >${this.heading}</a
45
+ >
46
+ </pkt-heading>
47
+ `:t.E}
48
+ `}renderSubheading(){return t.x`
49
+ ${this.subheading?t.x` <p class="pkt-card__subheading ">${this.subheading}</p> `:t.E}
50
+ `}renderHeader(){const i=!!this.heading||!!this.subheading;return t.x`
51
+ ${i?t.x`
52
+ <header class="pkt-card__header">
53
+ ${this.renderHeading()}
54
+ ${this.renderLinkHeading()}
55
+ ${this.renderSubheading()}
56
+ </header>
57
+ `:t.E}
58
+ `}renderTags(){const i={"pkt-card__tags":!0,[`pkt-card__tags-${this.tagPosition}`]:this.tagPosition};return t.x`
59
+ ${this.tags.length>0?t.x`
60
+ <div
61
+ class=${p.e(i)}
62
+ role="list"
63
+ aria-label=${this.tags.length>1?"merkelapper":"merkelapp"}
64
+ >
65
+ ${this.tags.map(a=>t.x`
66
+ <pkt-tag
67
+ role="listitem"
68
+ textStyle="normal-text"
69
+ size="medium"
70
+ skin=${h.o(a.skin)}
71
+ iconName=${h.o(a.iconName)}
72
+ >
73
+ ${a.text}
74
+ </pkt-tag>
75
+ `)}
76
+ </div>
77
+ `:t.E}
78
+ `}renderSlot(){return t.x`
79
+ ${this.defaultSlot&&t.x`<section class="pkt-card__content" ${c.n(this.defaultSlot)}></section>`}
80
+ `}renderCreditline(){return t.x`
81
+ ${this.author||this.date?t.x`
82
+ <footer class="pkt-card__creditline">
83
+ ${this.author?t.x`<span class="pkt-card__creditline-author">${this.author}</span>`:t.E}
84
+ ${this.date?t.x`<span class="pkt-card__creditline-date">${this.date}</span>`:t.E}
85
+ </footer>
86
+ `:t.E}
87
+ `}};e([t.n({type:String})],exports.PktCard.prototype,"ariaLabel",2);e([t.n({type:String})],exports.PktCard.prototype,"author",2);e([t.n({type:Boolean})],exports.PktCard.prototype,"borderOnHover",2);e([t.n({type:String,reflect:!0})],exports.PktCard.prototype,"clickCardLink",2);e([t.n({type:String})],exports.PktCard.prototype,"date",2);e([t.n({type:String})],exports.PktCard.prototype,"direction",2);e([t.n({type:String})],exports.PktCard.prototype,"heading",2);e([t.n({type:Number})],exports.PktCard.prototype,"headinglevel",2);e([t.n({type:Object})],exports.PktCard.prototype,"image",2);e([t.n({type:String})],exports.PktCard.prototype,"imageShape",2);e([t.n({type:Boolean})],exports.PktCard.prototype,"openLinkInNewTab",2);e([t.n({type:String})],exports.PktCard.prototype,"padding",2);e([t.n({type:String})],exports.PktCard.prototype,"skin",2);e([t.n({type:String})],exports.PktCard.prototype,"subheading",2);e([t.n({type:String})],exports.PktCard.prototype,"tagPosition",2);e([t.n({type:Array})],exports.PktCard.prototype,"tags",2);exports.PktCard=e([t.t("pkt-card")],exports.PktCard);
package/dist/index.d.ts CHANGED
@@ -117,6 +117,30 @@ export declare interface IPktButton {
117
117
  disabled?: Booleanish;
118
118
  }
119
119
 
120
+ declare interface IPktCard {
121
+ ariaLabel?: IAriaAttributes['aria-label'];
122
+ author?: string | null;
123
+ date?: string | null;
124
+ direction?: TDirection;
125
+ heading?: string;
126
+ headingLevel?: IPktHeading['level'];
127
+ image?: {
128
+ src: string;
129
+ alt: string;
130
+ };
131
+ imageShape?: TCardImageShape;
132
+ clickCardLink?: string | null;
133
+ openLinkInNewTab?: boolean | null;
134
+ borderOnHover?: boolean | null;
135
+ padding?: TCardPadding;
136
+ skin?: TCardSkin;
137
+ subheading?: string;
138
+ tagPosition?: TCardTagPosition;
139
+ tags?: (Omit<IPktTag, 'closeTag'> & {
140
+ text: string;
141
+ })[];
142
+ }
143
+
120
144
  export declare interface IPktCombobox {
121
145
  allowUserInput?: boolean;
122
146
  typeahead?: boolean;
@@ -425,22 +449,40 @@ export declare class PktCalendar extends PktElement {
425
449
  close(): void;
426
450
  }
427
451
 
428
- export declare class PktCard extends PktElement {
452
+ export declare class PktCard extends PktElement implements IPktCard {
429
453
  defaultSlot: Ref<HTMLElement>;
430
454
  constructor();
431
- skin: TCardSkin;
455
+ ariaLabel: string;
456
+ author: string | null;
457
+ borderOnHover: boolean;
458
+ clickCardLink: IPktCard['clickCardLink'];
459
+ date: string | null;
432
460
  direction: TDirection;
461
+ heading: string;
462
+ headinglevel: IPktHeading['level'];
433
463
  image: {
434
464
  src: string;
435
465
  alt: string;
436
466
  };
437
- heading: string;
467
+ imageShape: TCardImageShape;
468
+ openLinkInNewTab: boolean;
469
+ padding: TCardPadding;
470
+ skin: TCardSkin;
438
471
  subheading: string;
472
+ tagPosition: 'top' | 'bottom';
439
473
  tags: (Omit<IPktTag, 'closeTag'> & {
440
474
  text: string;
441
475
  })[];
442
476
  connectedCallback(): void;
443
477
  render(): TemplateResult<1>;
478
+ renderImage(): TemplateResult<1>;
479
+ renderHeading(): TemplateResult<1>;
480
+ renderLinkHeading(): TemplateResult<1>;
481
+ renderSubheading(): TemplateResult<1>;
482
+ renderHeader(): TemplateResult<1>;
483
+ renderTags(): TemplateResult<1>;
484
+ renderSlot(): TemplateResult<1>;
485
+ renderCreditline(): TemplateResult<1>;
444
486
  }
445
487
 
446
488
  export declare class PktCheckbox extends PktInputElement {
@@ -1115,7 +1157,13 @@ declare type TAriaRelevant = 'additions' | 'removals' | 'text' | 'all';
1115
1157
 
1116
1158
  declare type TAriaSort = 'none' | 'ascending' | 'descending' | 'other';
1117
1159
 
1118
- declare type TCardSkin = 'outlined' | 'gray' | 'beige' | 'green' | 'blue';
1160
+ declare type TCardImageShape = 'square' | 'round';
1161
+
1162
+ declare type TCardPadding = 'none' | 'standard';
1163
+
1164
+ declare type TCardSkin = 'outlined' | 'outlined-beige' | 'gray' | 'beige' | 'green' | 'blue';
1165
+
1166
+ declare type TCardTagPosition = 'top' | 'bottom';
1119
1167
 
1120
1168
  declare type TCounterPosition = 'top' | 'bottom';
1121
1169
 
package/dist/pkt-card.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./card-DH-3qNgp.cjs"),t=e.PktCard;Object.defineProperty(exports,"PktCard",{enumerable:!0,get:()=>e.PktCard});exports.default=t;
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const e=require("./card-Di1MQneh.cjs"),t=e.PktCard;Object.defineProperty(exports,"PktCard",{enumerable:!0,get:()=>e.PktCard});exports.default=t;
package/dist/pkt-card.js CHANGED
@@ -1,4 +1,4 @@
1
- import { P as a } from "./card-Cyww1yKr.js";
1
+ import { P as a } from "./card-CZG7XGlj.js";
2
2
  const r = a;
3
3
  export {
4
4
  a as PktCard,
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./alert-C2EPmB0W.cjs"),l=require("./accordionitem-RFwXQC_0.cjs"),d=require("./backlink-HHM21crL.cjs"),b=require("./button-ZkEpUrbJ.cjs"),k=require("./calendar-CYY42kN4.cjs"),m=require("./card-DH-3qNgp.cjs"),g=require("./combobox-yUrUarU_.cjs"),h=require("./consent-CSspmVST.cjs"),f=require("./checkbox-zqd3KVfz.cjs"),t=require("./element-BSypUpzA.cjs"),y=require("./pkt-slot-controller-Da-RgXfS.cjs"),s=require("./ref-BvbyvXRH.cjs"),O=require("./class-map-DCyaICmy.cjs"),j=require("./datepicker-CH5ZmFhf.cjs"),q=require("./helptext-bMgnhZ1R.cjs"),x=require("./heading-BnJhJDMD.cjs"),C=require("./icon-BnKGwYjj.cjs"),v=require("./input-wrapper-B-f_SotM.cjs"),S=require("./link-BrDbM3GT.cjs"),$=require("./linkcard-s9yoOq90.cjs"),L=require("./loader-Bk4XPiOY.cjs"),_=require("./messagebox-B0kgftoP.cjs"),A=require("./modal-DZY4gZCQ.cjs"),B=require("./progressbar-DiRfScnB.cjs"),p=require("./radiobutton-CI2xaqAB.cjs"),T=require("./tag-B9kFYxHg.cjs"),I=require("./textarea-DxbylapQ.cjs"),M=require("./textinput-B__c4c1z.cjs"),R=require("./select-BCL790jM.cjs");var H=Object.defineProperty,w=Object.getOwnPropertyDescriptor,o=(a,e,r,i)=>{for(var n=i>1?void 0:i?w(e,r):e,u=a.length-1,c;u>=0;u--)(c=a[u])&&(n=(i?c(e,r,n):c(n))||n);return i&&n&&H(e,r,n),n};exports.PktComponent=class extends t.PktElement{constructor(){super(),this.string="",this.strings=[],this.darkmode=!1,this._list=[],this.defaultSlot=s.e(),this.namedSlot=s.e(),this.slotController=new y.PktSlotController(this,this.defaultSlot,this.namedSlot)}connectedCallback(){this.strings.length&&this.strings.forEach(e=>{this._list.push(e.toUpperCase())}),super.connectedCallback()}render(){const e={"pkt-component":!0,"pkt-component--has-list":this.strings.length>0,"pkt-darkmode":this.darkmode};return t.x`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const P=require("./alert-C2EPmB0W.cjs"),l=require("./accordionitem-RFwXQC_0.cjs"),d=require("./backlink-HHM21crL.cjs"),b=require("./button-ZkEpUrbJ.cjs"),k=require("./calendar-CYY42kN4.cjs"),m=require("./card-Di1MQneh.cjs"),g=require("./combobox-yUrUarU_.cjs"),h=require("./consent-CSspmVST.cjs"),f=require("./checkbox-zqd3KVfz.cjs"),t=require("./element-BSypUpzA.cjs"),y=require("./pkt-slot-controller-Da-RgXfS.cjs"),s=require("./ref-BvbyvXRH.cjs"),O=require("./class-map-DCyaICmy.cjs"),j=require("./datepicker-CH5ZmFhf.cjs"),q=require("./helptext-bMgnhZ1R.cjs"),x=require("./heading-BnJhJDMD.cjs"),C=require("./icon-BnKGwYjj.cjs"),v=require("./input-wrapper-B-f_SotM.cjs"),S=require("./link-BrDbM3GT.cjs"),$=require("./linkcard-s9yoOq90.cjs"),L=require("./loader-Bk4XPiOY.cjs"),_=require("./messagebox-B0kgftoP.cjs"),A=require("./modal-DZY4gZCQ.cjs"),B=require("./progressbar-DiRfScnB.cjs"),p=require("./radiobutton-CI2xaqAB.cjs"),T=require("./tag-B9kFYxHg.cjs"),I=require("./textarea-DxbylapQ.cjs"),M=require("./textinput-B__c4c1z.cjs"),R=require("./select-BCL790jM.cjs");var H=Object.defineProperty,w=Object.getOwnPropertyDescriptor,o=(a,e,r,i)=>{for(var n=i>1?void 0:i?w(e,r):e,u=a.length-1,c;u>=0;u--)(c=a[u])&&(n=(i?c(e,r,n):c(n))||n);return i&&n&&H(e,r,n),n};exports.PktComponent=class extends t.PktElement{constructor(){super(),this.string="",this.strings=[],this.darkmode=!1,this._list=[],this.defaultSlot=s.e(),this.namedSlot=s.e(),this.slotController=new y.PktSlotController(this,this.defaultSlot,this.namedSlot)}connectedCallback(){this.strings.length&&this.strings.forEach(e=>{this._list.push(e.toUpperCase())}),super.connectedCallback()}render(){const e={"pkt-component":!0,"pkt-component--has-list":this.strings.length>0,"pkt-darkmode":this.darkmode};return t.x`
2
2
  <div class="${O.e(e)}">
3
3
  <h1 class="pkt-txt-28">${this.string}</h1>
4
4
 
package/dist/pkt-index.js CHANGED
@@ -4,7 +4,7 @@ import { P as O } from "./backlink-hvyJmwrO.js";
4
4
  import { P as T } from "./button-D39TTsjJ.js";
5
5
  import { c as f } from "./calendar-KDcOWD6V.js";
6
6
  import { P as D } from "./calendar-KDcOWD6V.js";
7
- import { P as G } from "./card-Cyww1yKr.js";
7
+ import { P as G } from "./card-CZG7XGlj.js";
8
8
  import { P as K } from "./combobox-B6x7Qukm.js";
9
9
  import { P as U } from "./consent-BPZ8QV7q.js";
10
10
  import { P as q } from "./checkbox-Ds1FrhqK.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oslokommune/punkt-elements",
3
- "version": "12.37.8",
3
+ "version": "12.38.0",
4
4
  "description": "Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo",
5
5
  "homepage": "https://punkt.oslo.kommune.no",
6
6
  "author": "Team Designsystem, Oslo Origo",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "devDependencies": {
34
34
  "@oslokommune/punkt-assets": "^12.37.0",
35
- "@oslokommune/punkt-css": "^12.37.2",
35
+ "@oslokommune/punkt-css": "^12.38.0",
36
36
  "sass": "^1.78.0",
37
37
  "typescript": "^5.6.2",
38
38
  "vite": "^5.4.18",
@@ -59,5 +59,5 @@
59
59
  "url": "https://github.com/oslokommune/punkt/issues"
60
60
  },
61
61
  "license": "MIT",
62
- "gitHead": "ff82b384dde195e97572a47eb6f9e13c5f3c9063"
62
+ "gitHead": "02f166beaa93cb948806b224d4af7c1aafe8d346"
63
63
  }
@@ -6,78 +6,247 @@ import { IPktTag } from '@/components/tag'
6
6
  import { PktElement } from '@/base-elements/element'
7
7
  import { PktSlotController } from '@/controllers/pkt-slot-controller'
8
8
  import { ref, createRef, Ref } from 'lit/directives/ref.js'
9
+ import { IPktHeading } from '../heading'
9
10
  import specs from 'componentSpecs/card.json'
10
11
  import '@/components/icon'
11
12
  import '@/components/tag'
13
+ import { IAriaAttributes } from '@/types/aria'
12
14
 
13
- export type TCardSkin = 'outlined' | 'gray' | 'beige' | 'green' | 'blue'
15
+ export type TCardSkin = 'outlined' | 'outlined-beige' | 'gray' | 'beige' | 'green' | 'blue'
14
16
  export type TDirection = 'portrait' | 'landscape'
17
+ export type TCardPadding = 'none' | 'standard'
18
+ export type TCardImageShape = 'square' | 'round'
19
+ export type TCardTagPosition = 'top' | 'bottom'
20
+
21
+ export interface IPktCard {
22
+ ariaLabel?: IAriaAttributes['aria-label']
23
+ author?: string | null
24
+ date?: string | null
25
+ direction?: TDirection
26
+ heading?: string
27
+ headingLevel?: IPktHeading['level']
28
+ image?: { src: string; alt: string }
29
+ imageShape?: TCardImageShape
30
+ clickCardLink?: string | null
31
+ openLinkInNewTab?: boolean | null
32
+ borderOnHover?: boolean | null
33
+ padding?: TCardPadding
34
+ skin?: TCardSkin
35
+ subheading?: string
36
+ tagPosition?: TCardTagPosition
37
+ tags?: (Omit<IPktTag, 'closeTag'> & { text: string })[]
38
+ }
15
39
 
16
40
  @customElement('pkt-card')
17
- export class PktCard extends PktElement {
41
+ export class PktCard extends PktElement implements IPktCard {
42
+ // Refs
43
+
18
44
  defaultSlot: Ref<HTMLElement> = createRef()
19
45
 
46
+ //Constructor
47
+
20
48
  constructor() {
21
49
  super()
22
50
  this.slotController = new PktSlotController(this, this.defaultSlot)
23
51
  }
24
52
 
25
- @property({ type: String, reflect: true }) skin: TCardSkin = specs.props.skin.default as TCardSkin
26
- @property({ type: String, reflect: true }) direction: TDirection = specs.props.direction
27
- .default as TDirection
28
- @property({ type: Object, reflect: true }) image: { src: string; alt: string } = {
53
+ // Properties
54
+
55
+ @property({ type: String }) ariaLabel: string = ''
56
+ @property({ type: String }) author: string | null = null
57
+ @property({ type: Boolean }) borderOnHover: boolean = true
58
+ @property({ type: String, reflect: true }) clickCardLink: IPktCard['clickCardLink'] = null
59
+ @property({ type: String }) date: string | null = null
60
+ @property({ type: String }) direction: TDirection = specs.props.direction.default as TDirection
61
+ @property({ type: String }) heading: string = ''
62
+ @property({ type: Number }) headinglevel: IPktHeading['level'] = 3
63
+ @property({ type: Object }) image: { src: string; alt: string } = {
29
64
  src: '',
30
65
  alt: '',
31
66
  }
32
- @property({ type: String, reflect: true }) heading: string = ''
33
- @property({ type: String, reflect: true }) subheading: string = ''
34
- @property({ type: Array, reflect: true }) tags: (Omit<IPktTag, 'closeTag'> & { text: string })[] =
35
- []
67
+ @property({ type: String }) imageShape: TCardImageShape = 'square'
68
+ @property({ type: Boolean }) openLinkInNewTab: boolean = false
69
+ @property({ type: String }) padding: TCardPadding = specs.props.padding.default as TCardPadding
70
+ @property({ type: String }) skin: TCardSkin = specs.props.skin.default as TCardSkin
71
+ @property({ type: String }) subheading: string = ''
72
+ @property({ type: String }) tagPosition: 'top' | 'bottom' = 'top'
73
+ @property({ type: Array }) tags: (Omit<IPktTag, 'closeTag'> & { text: string })[] = []
36
74
 
37
75
  connectedCallback() {
38
76
  super.connectedCallback()
39
77
  }
40
78
 
79
+ // Render methods
80
+
81
+ // Main render method
82
+ // prettier-ignore
41
83
  render() {
42
84
  const classes = {
43
85
  'pkt-card': true,
44
86
  [`pkt-card--${this.skin}`]: this.skin,
45
87
  [`pkt-card--${this.direction}`]: this.direction,
88
+ [`pkt-card--padding-${this.padding}`]: this.padding,
89
+ [`pkt-card--border-on-hover`]: this.borderOnHover,
90
+
46
91
  }
47
92
 
93
+ //
94
+ const ariaLabelLenke =
95
+ this.ariaLabel?.trim() || (this.heading ? `${this.heading} lenkekort` : 'lenkekort')
96
+ const ariaLabelVanlig = this.ariaLabel?.trim() || (this.heading ? this.heading : 'kort')
97
+
48
98
  return html`
49
- <div class=${classMap(classes)}>
50
- ${this.image.src &&
51
- html`
52
- <div class="pkt-card__image">
53
- <img src=${this.image.src} alt=${this.image.alt || ''} />
54
- </div>
55
- `}
99
+ <article
100
+ class=${classMap(classes)}
101
+ aria-label=${ifDefined(this.clickCardLink ? ariaLabelLenke : ariaLabelVanlig)}
102
+ >
103
+ ${this.renderImage()}
56
104
  <div class="pkt-card__wrapper">
57
- ${this.tags.length > 0
58
- ? html`
59
- <div class="pkt-card__tags">
60
- ${this.tags.map(
61
- (tag) => html`
62
- <pkt-tag
63
- textStyle="normal-text"
64
- size="medium"
65
- skin=${ifDefined(tag.skin)}
66
- iconName=${ifDefined(tag.iconName)}
67
- >
68
- ${tag.text}
69
- </pkt-tag>
70
- `,
71
- )}
72
- </div>
73
- `
74
- : nothing}
75
- ${this.heading && html`<h3 class="pkt-txt-30-medium">${this.heading}</h3>`}
76
- ${this.subheading && html`<p class="pkt-txt-20-light">${this.subheading}</p>`}
77
- ${this.defaultSlot &&
78
- html`<div class="pkt-card__content" ${ref(this.defaultSlot)}></div>`}
105
+ ${this.tagPosition === 'top' ? this.renderTags() : nothing}
106
+ ${this.renderHeader()}
107
+ ${this.renderSlot()}
108
+ ${this.tagPosition === 'bottom' ? this.renderTags() : nothing}
109
+ ${this.renderCreditline()}
110
+ </div>
111
+ </article>
112
+ `
113
+ }
114
+
115
+ // Render methods for different parts of the card
116
+ renderImage() {
117
+ const imageClasses = {
118
+ 'pkt-card__image': true,
119
+ [`pkt-card__image-${this.imageShape}`]: this.imageShape,
120
+ }
121
+
122
+ return html`
123
+ ${this.image.src &&
124
+ html`
125
+ <div class=${classMap(imageClasses)}>
126
+ <img src=${this.image.src} alt=${this.image.alt || ''} />
79
127
  </div>
80
- </div>
128
+ `}
129
+ `
130
+ }
131
+
132
+ // Do not render heading if link is present, render link heading instead
133
+ // Combine the rendering for headings into a renderHeader method
134
+ renderHeading() {
135
+ return html`
136
+ ${this.heading && !this.clickCardLink
137
+ ? html`
138
+ <pkt-heading
139
+ class="pkt-card__heading"
140
+ .level=${this.headinglevel || 3}
141
+ size="medium"
142
+ nospacing
143
+ >
144
+ ${this.heading}
145
+ </pkt-heading>
146
+ `
147
+ : nothing}
148
+ `
149
+ }
150
+
151
+ renderLinkHeading() {
152
+ return html`
153
+ ${this.clickCardLink
154
+ ? html`
155
+ <pkt-heading
156
+ class="pkt-card__link-heading pkt-card__heading"
157
+ .level=${this.headinglevel || 3}
158
+ size="medium"
159
+ nospacing
160
+ >
161
+ <a
162
+ class="pkt-card__link"
163
+ href=${this.clickCardLink}
164
+ target=${this.openLinkInNewTab ? '_blank' : '_self'}
165
+ >${this.heading}</a
166
+ >
167
+ </pkt-heading>
168
+ `
169
+ : nothing}
170
+ `
171
+ }
172
+
173
+ renderSubheading() {
174
+ return html`
175
+ ${this.subheading ? html` <p class="pkt-card__subheading ">${this.subheading}</p> ` : nothing}
176
+ `
177
+ }
178
+
179
+ // Render header
180
+
181
+ // prettier-ignore
182
+ renderHeader() {
183
+ const hasHeading = !!this.heading || !!this.subheading
184
+ return html`
185
+ ${hasHeading
186
+ ? html`
187
+ <header class="pkt-card__header">
188
+ ${this.renderHeading()}
189
+ ${this.renderLinkHeading()}
190
+ ${this.renderSubheading()}
191
+ </header>
192
+ `
193
+ : nothing}
194
+ `
195
+ }
196
+
197
+ renderTags() {
198
+ const tagClasses = {
199
+ 'pkt-card__tags': true,
200
+ [`pkt-card__tags-${this.tagPosition}`]: this.tagPosition,
201
+ }
202
+ return html`
203
+ ${this.tags.length > 0
204
+ ? html`
205
+ <div
206
+ class=${classMap(tagClasses)}
207
+ role="list"
208
+ aria-label=${this.tags.length > 1 ? 'merkelapper' : 'merkelapp'}
209
+ >
210
+ ${this.tags.map(
211
+ (tag) => html`
212
+ <pkt-tag
213
+ role="listitem"
214
+ textStyle="normal-text"
215
+ size="medium"
216
+ skin=${ifDefined(tag.skin)}
217
+ iconName=${ifDefined(tag.iconName)}
218
+ >
219
+ ${tag.text}
220
+ </pkt-tag>
221
+ `,
222
+ )}
223
+ </div>
224
+ `
225
+ : nothing}
226
+ `
227
+ }
228
+
229
+ renderSlot() {
230
+ return html`
231
+ ${this.defaultSlot &&
232
+ html`<section class="pkt-card__content" ${ref(this.defaultSlot)}></section>`}
233
+ `
234
+ }
235
+
236
+ renderCreditline() {
237
+ return html`
238
+ ${this.author || this.date
239
+ ? html`
240
+ <footer class="pkt-card__creditline">
241
+ ${this.author
242
+ ? html`<span class="pkt-card__creditline-author">${this.author}</span>`
243
+ : nothing}
244
+ ${this.date
245
+ ? html`<span class="pkt-card__creditline-date">${this.date}</span>`
246
+ : nothing}
247
+ </footer>
248
+ `
249
+ : nothing}
81
250
  `
82
251
  }
83
252
  }
@@ -1,94 +0,0 @@
1
- import { e as m } from "./class-map-KyMqi0fa.js";
2
- import { o as d } from "./if-defined-BErSJCeJ.js";
3
- import { P as u, E as g, x as i, n as a, a as f } from "./element-DjjF_tEh.js";
4
- import { P as k } from "./pkt-slot-controller-DtDaD9q_.js";
5
- import { e as $, n as v } from "./ref-iIffqQAI.js";
6
- import "./icon-Beoxup8E.js";
7
- import "./tag-Cu8afZy8.js";
8
- const y = {
9
- skin: {
10
- default: "outlined"
11
- },
12
- direction: {
13
- default: "portrait"
14
- }
15
- }, h = {
16
- props: y
17
- };
18
- var _ = Object.defineProperty, P = Object.getOwnPropertyDescriptor, r = (o, t, n, p) => {
19
- for (var s = p > 1 ? void 0 : p ? P(t, n) : t, c = o.length - 1, l; c >= 0; c--)
20
- (l = o[c]) && (s = (p ? l(t, n, s) : l(s)) || s);
21
- return p && s && _(t, n, s), s;
22
- };
23
- let e = class extends u {
24
- constructor() {
25
- super(), this.defaultSlot = $(), this.skin = h.props.skin.default, this.direction = h.props.direction.default, this.image = {
26
- src: "",
27
- alt: ""
28
- }, this.heading = "", this.subheading = "", this.tags = [], this.slotController = new k(this, this.defaultSlot);
29
- }
30
- connectedCallback() {
31
- super.connectedCallback();
32
- }
33
- render() {
34
- const o = {
35
- "pkt-card": !0,
36
- [`pkt-card--${this.skin}`]: this.skin,
37
- [`pkt-card--${this.direction}`]: this.direction
38
- };
39
- return i`
40
- <div class=${m(o)}>
41
- ${this.image.src && i`
42
- <div class="pkt-card__image">
43
- <img src=${this.image.src} alt=${this.image.alt || ""} />
44
- </div>
45
- `}
46
- <div class="pkt-card__wrapper">
47
- ${this.tags.length > 0 ? i`
48
- <div class="pkt-card__tags">
49
- ${this.tags.map(
50
- (t) => i`
51
- <pkt-tag
52
- textStyle="normal-text"
53
- size="medium"
54
- skin=${d(t.skin)}
55
- iconName=${d(t.iconName)}
56
- >
57
- ${t.text}
58
- </pkt-tag>
59
- `
60
- )}
61
- </div>
62
- ` : g}
63
- ${this.heading && i`<h3 class="pkt-txt-30-medium">${this.heading}</h3>`}
64
- ${this.subheading && i`<p class="pkt-txt-20-light">${this.subheading}</p>`}
65
- ${this.defaultSlot && i`<div class="pkt-card__content" ${v(this.defaultSlot)}></div>`}
66
- </div>
67
- </div>
68
- `;
69
- }
70
- };
71
- r([
72
- a({ type: String, reflect: !0 })
73
- ], e.prototype, "skin", 2);
74
- r([
75
- a({ type: String, reflect: !0 })
76
- ], e.prototype, "direction", 2);
77
- r([
78
- a({ type: Object, reflect: !0 })
79
- ], e.prototype, "image", 2);
80
- r([
81
- a({ type: String, reflect: !0 })
82
- ], e.prototype, "heading", 2);
83
- r([
84
- a({ type: String, reflect: !0 })
85
- ], e.prototype, "subheading", 2);
86
- r([
87
- a({ type: Array, reflect: !0 })
88
- ], e.prototype, "tags", 2);
89
- e = r([
90
- f("pkt-card")
91
- ], e);
92
- export {
93
- e as P
94
- };
@@ -1,28 +0,0 @@
1
- "use strict";const h=require("./class-map-DCyaICmy.cjs"),d=require("./if-defined-a3sotaUr.cjs"),t=require("./element-BSypUpzA.cjs"),u=require("./pkt-slot-controller-Da-RgXfS.cjs"),l=require("./ref-BvbyvXRH.cjs");require("./icon-BnKGwYjj.cjs");require("./tag-B9kFYxHg.cjs");const k={skin:{default:"outlined"},direction:{default:"portrait"}},p={props:k};var g=Object.defineProperty,f=Object.getOwnPropertyDescriptor,s=(n,i,e,a)=>{for(var r=a>1?void 0:a?f(i,e):i,c=n.length-1,o;c>=0;c--)(o=n[c])&&(r=(a?o(i,e,r):o(r))||r);return a&&r&&g(i,e,r),r};exports.PktCard=class extends t.PktElement{constructor(){super(),this.defaultSlot=l.e(),this.skin=p.props.skin.default,this.direction=p.props.direction.default,this.image={src:"",alt:""},this.heading="",this.subheading="",this.tags=[],this.slotController=new u.PktSlotController(this,this.defaultSlot)}connectedCallback(){super.connectedCallback()}render(){const i={"pkt-card":!0,[`pkt-card--${this.skin}`]:this.skin,[`pkt-card--${this.direction}`]:this.direction};return t.x`
2
- <div class=${h.e(i)}>
3
- ${this.image.src&&t.x`
4
- <div class="pkt-card__image">
5
- <img src=${this.image.src} alt=${this.image.alt||""} />
6
- </div>
7
- `}
8
- <div class="pkt-card__wrapper">
9
- ${this.tags.length>0?t.x`
10
- <div class="pkt-card__tags">
11
- ${this.tags.map(e=>t.x`
12
- <pkt-tag
13
- textStyle="normal-text"
14
- size="medium"
15
- skin=${d.o(e.skin)}
16
- iconName=${d.o(e.iconName)}
17
- >
18
- ${e.text}
19
- </pkt-tag>
20
- `)}
21
- </div>
22
- `:t.E}
23
- ${this.heading&&t.x`<h3 class="pkt-txt-30-medium">${this.heading}</h3>`}
24
- ${this.subheading&&t.x`<p class="pkt-txt-20-light">${this.subheading}</p>`}
25
- ${this.defaultSlot&&t.x`<div class="pkt-card__content" ${l.n(this.defaultSlot)}></div>`}
26
- </div>
27
- </div>
28
- `}};s([t.n({type:String,reflect:!0})],exports.PktCard.prototype,"skin",2);s([t.n({type:String,reflect:!0})],exports.PktCard.prototype,"direction",2);s([t.n({type:Object,reflect:!0})],exports.PktCard.prototype,"image",2);s([t.n({type:String,reflect:!0})],exports.PktCard.prototype,"heading",2);s([t.n({type:String,reflect:!0})],exports.PktCard.prototype,"subheading",2);s([t.n({type:Array,reflect:!0})],exports.PktCard.prototype,"tags",2);exports.PktCard=s([t.t("pkt-card")],exports.PktCard);