@oslokommune/punkt-elements 11.12.3

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.
Files changed (35) hide show
  1. package/LICENSE +21 -0
  2. package/dist/converters-01e4a1b1.cjs +5 -0
  3. package/dist/converters-92631e0d.js +105 -0
  4. package/dist/directive-6900e150.cjs +23 -0
  5. package/dist/directive-720b7cc8.js +606 -0
  6. package/dist/index-34184de4.js +173 -0
  7. package/dist/index-51027300.cjs +13 -0
  8. package/dist/pkt-el-calendar.cjs +60 -0
  9. package/dist/pkt-el-calendar.js +1504 -0
  10. package/dist/pkt-el-component-template.cjs +29 -0
  11. package/dist/pkt-el-component-template.js +100 -0
  12. package/dist/pkt-el-element.cjs +1 -0
  13. package/dist/pkt-el-element.js +5 -0
  14. package/dist/pkt-el-icon.cjs +9 -0
  15. package/dist/pkt-el-icon.js +103 -0
  16. package/dist/pkt-el-index.cjs +1 -0
  17. package/dist/pkt-el-index.js +12 -0
  18. package/dist/property-0378afc0.js +47 -0
  19. package/dist/property-e170cbca.cjs +9 -0
  20. package/dist/src/components/calendar/index.d.ts +60 -0
  21. package/dist/src/components/component-template/index.d.ts +35 -0
  22. package/dist/src/components/element/index.d.ts +25 -0
  23. package/dist/src/components/icon/index.d.ts +30 -0
  24. package/dist/src/components/index.d.ts +3 -0
  25. package/dist/src/controllers/pkt-slot-controller.d.ts +12 -0
  26. package/dist/src/helpers/converters.d.ts +3 -0
  27. package/dist/src/index.d.ts +1 -0
  28. package/dist/src/translations/no.json.d.ts +43 -0
  29. package/dist/vite.config.d.ts +2 -0
  30. package/package.json +61 -0
  31. package/src/components/calendar/index.ts +375 -0
  32. package/src/components/component-template/index.ts +113 -0
  33. package/src/components/element/index.ts +37 -0
  34. package/src/components/icon/index.ts +100 -0
  35. package/src/components/index.ts +3 -0
@@ -0,0 +1,375 @@
1
+ import { html } from 'lit'
2
+ import { customElement, property } from 'lit/decorators.js'
3
+ import { classMap } from 'lit/directives/class-map.js'
4
+ import strings from '../../translations/no.json'
5
+ import { getWeek, eachDayOfInterval, getISODay, format as dateFormat } from 'date-fns'
6
+ import { csvToArray, stringToDate, stringsToDate } from '../../helpers/converters'
7
+ import { PktElement } from '../element'
8
+ // TODO: Change this to @oslokommune/punkt-elements as soon as it exists
9
+ import '../icon'
10
+
11
+ @customElement('pkt-el-calendar')
12
+ export class PktCalendar extends PktElement {
13
+ /**
14
+ * Element attributes
15
+ */
16
+ @property({ converter: stringToDate }) date: Date = new Date()
17
+ @property({ converter: csvToArray, reflect: true }) selected: string[] = []
18
+ @property({ converter: csvToArray }) excludeweekdays: string[] = []
19
+ @property({ converter: stringsToDate }) excludedates: Date[] = []
20
+ @property({ converter: stringToDate }) earliest: Date | null = null
21
+ @property({ converter: stringToDate }) latest: Date | null = null
22
+
23
+ @property({ type: Boolean, reflect: true }) weeknumbers: boolean = false
24
+ @property({ type: Boolean, reflect: true }) withcontrols: boolean = false
25
+ @property({ type: Boolean, reflect: true }) multiple: boolean = false
26
+ @property({ type: Boolean, reflect: true }) range: boolean = false
27
+
28
+ /**
29
+ * Strings
30
+ */
31
+ @property({ type: Array }) dayStrings: string[] = strings.dates.daysShort
32
+ @property({ type: Array }) monthStrings: string[] = strings.dates.months
33
+ @property({ type: String }) weekString: string = strings.dates.week
34
+ @property({ type: String }) prevMonthString: string = strings.dates.prevMonth
35
+ @property({ type: String }) nextMonthString: string = strings.dates.nextMonth
36
+
37
+ /**
38
+ * Private properties
39
+ */
40
+ @property({ type: Array }) private _selected: Date[] = []
41
+ @property({ type: Number }) private year: number = 0
42
+ @property({ type: Number }) private month: number = 0
43
+ @property({ type: Number }) private week: number = 0
44
+ @property({ type: Date }) private rangeHovered: Date | null = null
45
+
46
+ /**
47
+ * Runs on mount, used to set up various values and whatever you need to run
48
+ */
49
+ connectedCallback() {
50
+ const today = this.date
51
+ this.year = today.getFullYear()
52
+ this.month = today.getMonth()
53
+ this.week = getWeek(new Date(this.year, this.month, 1))
54
+ this.selected.length &&
55
+ this.selected.forEach((d) => {
56
+ this._selected.push(new Date(d))
57
+ })
58
+ super.connectedCallback()
59
+ }
60
+
61
+ /**
62
+ * Component functionality and render
63
+ */
64
+ render() {
65
+ return html`
66
+ <div class="pkt-calendar ${this.weeknumbers && 'pkt-cal-weeknumbers'}">
67
+ <nav class="pkt-cal-month-nav">
68
+ <button
69
+ @click=${this.isPrevMonthAllowed() && this.prevMonth}
70
+ class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--icon-only"
71
+ ?disabled=${!this.isPrevMonthAllowed()}
72
+ >
73
+ <pkt-el-icon class="pkt-btn__icon" name="chevron-thin-left"></pkt-el-icon>
74
+ <span class="pkt-btn__text">${this.prevMonthString}</span>
75
+ </button>
76
+ ${this.renderMonthNav()}
77
+ <button
78
+ @click=${this.isNextMonthAllowed() && this.nextMonth}
79
+ class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--icon-only"
80
+ ?disabled=${!this.isNextMonthAllowed()}
81
+ >
82
+ <pkt-el-icon class="pkt-btn__icon" name="chevron-thin-right"></pkt-el-icon>
83
+ <span class="pkt-btn__text">${this.nextMonthString}</span>
84
+ </button>
85
+ </nav>
86
+ <ul class="pkt-cal-days pkt-txt-12-medium" role="grid">
87
+ ${this.renderDayNames()} ${this.renderCalendarBody()}
88
+ </ul>
89
+ </div>
90
+ `
91
+ }
92
+
93
+ private renderDayNames() {
94
+ const days = []
95
+ if (this.weeknumbers) {
96
+ days.push(html`<li>${this.weekString}</li>`)
97
+ }
98
+ for (let i = 0; i < this.dayStrings.length; i++) {
99
+ days.push(html`<li>${this.dayStrings[i]}</li>`)
100
+ }
101
+ return days
102
+ }
103
+
104
+ private renderMonthNav() {
105
+ let monthView = []
106
+ if (this.withcontrols) {
107
+ monthView.push(html`<div class="pkt-cal-month-picker">
108
+ <select
109
+ class="pkt-input pkt-input-compact"
110
+ @change=${(e: any) => {
111
+ this.changeMonth(this.year, e.target.value)
112
+ }}
113
+ >
114
+ ${this.monthStrings.map(
115
+ (month, index) =>
116
+ html`<option value=${index} ?selected=${this.month === index}>${month}</option>`,
117
+ )}
118
+ </select>
119
+ <input
120
+ class="pkt-input pkt-cal-input-year pkt-input-compact"
121
+ type="number"
122
+ size="4"
123
+ placeholder="0000"
124
+ @change=${(e: any) => {
125
+ this.changeMonth(e.target.value, this.month)
126
+ }}
127
+ value="${this.year}"
128
+ />
129
+ </div> `)
130
+ } else {
131
+ monthView.push(
132
+ html`<div class="pkt-txt-16-medium" aria-live="polite">
133
+ ${this.monthStrings[this.month]} ${this.year}
134
+ </div>`,
135
+ )
136
+ }
137
+ return monthView
138
+ }
139
+
140
+ private renderCalendarBody() {
141
+ const today = new Date()
142
+ const firstDayOfMonth = new Date(this.year, this.month, 1)
143
+ const lastDayOfMonth = new Date(this.year, this.month + 1, 0)
144
+ const startingDay = (firstDayOfMonth.getDay() + 6) % 7
145
+ const numDays = lastDayOfMonth.getDate()
146
+ const numRows = Math.ceil((numDays + startingDay) / 7)
147
+ const lastDayOfPrevMonth = new Date(this.year, this.month, 0)
148
+ const numDaysPrevMonth = lastDayOfPrevMonth.getDate()
149
+
150
+ let dayCounter = 1
151
+ this.week = getWeek(new Date(this.year, this.month, 1))
152
+
153
+ const rows = []
154
+
155
+ for (let i = 0; i < numRows; i++) {
156
+ const cells = []
157
+
158
+ this.weeknumbers && cells.push(html`<li class="pkt-cal-week">${this.week}</li>`)
159
+ this.week++
160
+
161
+ for (let j = 1; j < 8; j++) {
162
+ if (i === 0 && j < startingDay) {
163
+ const dayFromPrevMonth = numDaysPrevMonth - (startingDay - j - 1)
164
+ cells.push(html`<li class="pkt-cal-other">
165
+ <button class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--label-only" disabled>
166
+ <span class="pkt-btn__text pkt-txt-14-light">${dayFromPrevMonth}</span>
167
+ </button>
168
+ </li>`)
169
+ } else if (dayCounter > numDays) {
170
+ cells.push(html`<li class="pkt-cal-other">
171
+ <button class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--label-only" disabled>
172
+ <span class="pkt-btn__text pkt-txt-14-light">${dayCounter - numDays}</span>
173
+ </button>
174
+ </li>`)
175
+ dayCounter++
176
+ } else {
177
+ const currentDate = new Date(this.year, this.month, dayCounter)
178
+ const currentDateISO = this.formatISODate(currentDate)
179
+ const isToday = currentDateISO === this.formatISODate(today)
180
+ const isSelected = this.selected.includes(currentDateISO)
181
+ const classes = {
182
+ 'pkt-cal-today': isToday,
183
+ 'pkt-cal-selected': isSelected,
184
+ 'pkt-cal-in-range': this.isInRange(currentDate),
185
+ 'pkt-cal-excluded': this.isExcluded(j, currentDate),
186
+ 'pkt-cal-in-range-first':
187
+ this.range &&
188
+ (this.selected.length === 2 || this.rangeHovered !== null) &&
189
+ currentDateISO === this.selected[0],
190
+ 'pkt-cal-in-range-last':
191
+ this.range && this.selected.length === 2 && currentDateISO === this.selected[1],
192
+ 'pkt-cal-range-hover':
193
+ this.rangeHovered !== null &&
194
+ currentDateISO === this.formatISODate(this.rangeHovered),
195
+ }
196
+ cells.push(
197
+ html`<li class=${classMap(classes)}>
198
+ <button
199
+ class="pkt-btn pkt-btn--tertiary pkt-btn--small pkt-btn--label-only"
200
+ @click=${() => this.handleDateSelect(currentDate)}
201
+ @mouseover=${() =>
202
+ this.range &&
203
+ !this.isExcluded(j, currentDate) &&
204
+ this.handleRangeHover(currentDate)}
205
+ ?disabled=${this.isExcluded(j, currentDate)}
206
+ >
207
+ <span class="pkt-btn__text pkt-txt-14-light">${dayCounter}</span>
208
+ </button>
209
+ </li>`,
210
+ )
211
+ dayCounter++
212
+ }
213
+ }
214
+
215
+ rows.push(html`${cells}`)
216
+ }
217
+
218
+ return rows
219
+ }
220
+
221
+ private isExcluded(weekday: number, date: Date) {
222
+ if (this.excludeweekdays.includes(weekday.toString())) return true
223
+ if (this.earliest && date < this.earliest) return true
224
+ if (this.latest && date > this.latest) return true
225
+ return this.excludedates.some((x) => {
226
+ return x.toDateString() === date.toDateString()
227
+ })
228
+ }
229
+
230
+ private formatISODate(date: Date) {
231
+ return dateFormat(date, 'yyyy-MM-dd')
232
+ }
233
+
234
+ isPrevMonthAllowed() {
235
+ const prevMonth = new Date(this.year, this.month, 0)
236
+ if (this.earliest && this.earliest > prevMonth) return false
237
+ return true
238
+ }
239
+
240
+ private prevMonth() {
241
+ const newMonth = this.month === 0 ? 11 : this.month - 1
242
+ const newYear = this.month === 0 ? this.year - 1 : this.year
243
+ this.changeMonth(newYear, newMonth)
244
+ }
245
+
246
+ isNextMonthAllowed() {
247
+ const nextMonth = new Date(this.year, this.month === 11 ? 0 : this.month + 1, 1)
248
+ if (this.latest && this.latest < nextMonth) return false
249
+ return true
250
+ }
251
+
252
+ private nextMonth() {
253
+ const newMonth = this.month === 11 ? 0 : this.month + 1
254
+ const newYear = this.month === 11 ? this.year + 1 : this.year
255
+ this.changeMonth(newYear, newMonth)
256
+ }
257
+
258
+ private changeMonth(year: number, month: number) {
259
+ this.year = year
260
+ this.month = month
261
+ this.requestUpdate()
262
+ }
263
+
264
+ private isInRange(date: Date) {
265
+ if (this.range && this._selected.length === 2) {
266
+ if (date > this._selected[0] && date < this._selected[1]) return true
267
+ } else if (this.range && this._selected.length === 1 && this.rangeHovered) {
268
+ if (date > this._selected[0] && date < this.rangeHovered) return true
269
+ }
270
+ return false
271
+ }
272
+
273
+ private isRangeAllowed(date: Date) {
274
+ let allowed = true
275
+ if (this._selected.length === 1) {
276
+ const days = eachDayOfInterval({
277
+ start: this._selected[0],
278
+ end: date,
279
+ })
280
+
281
+ if (Array.isArray(days) && days.length) {
282
+ for (let i = 0; i < days.length; i++) {
283
+ this.excludedates.forEach((d) => {
284
+ if (d > this._selected[0] && d < date) {
285
+ allowed = false
286
+ }
287
+ })
288
+ if (this.excludeweekdays.includes(getISODay(days[i]).toString())) {
289
+ allowed = false
290
+ }
291
+ }
292
+ }
293
+ }
294
+ return allowed
295
+ }
296
+
297
+ private emptySelected() {
298
+ this.selected.splice(0, this.selected.length)
299
+ this._selected.splice(0, this._selected.length)
300
+ }
301
+
302
+ private addToSelected(selectedDate: Date) {
303
+ this.selected.push(this.formatISODate(selectedDate))
304
+ this._selected.push(selectedDate)
305
+ this.requestUpdate()
306
+ }
307
+
308
+ private removeFromSelected(selectedDate: Date) {
309
+ const selectedDateISO = this.formatISODate(selectedDate)
310
+ this.selected.splice(this.selected.indexOf(selectedDateISO), 1)
311
+ this._selected.splice(this.selected.indexOf(selectedDateISO), 1)
312
+ }
313
+
314
+ private toggleSelected(selectedDate: Date) {
315
+ const selectedDateISO = this.formatISODate(selectedDate)
316
+ this.selected.includes(selectedDateISO)
317
+ ? this.removeFromSelected(selectedDate)
318
+ : this.addToSelected(selectedDate)
319
+ }
320
+
321
+ private handleRangeSelect(selectedDate: Date) {
322
+ const selectedDateISO = this.formatISODate(selectedDate)
323
+ if (this.selected.includes(selectedDateISO)) {
324
+ if (this.selected.indexOf(selectedDateISO) === 0) {
325
+ this.emptySelected()
326
+ } else {
327
+ this.removeFromSelected(selectedDate)
328
+ }
329
+ } else {
330
+ if (this.selected.length > 1) {
331
+ this.emptySelected()
332
+ this.addToSelected(selectedDate)
333
+ } else {
334
+ if (this.selected.length === 1 && !this.isRangeAllowed(selectedDate)) {
335
+ this.emptySelected()
336
+ }
337
+ if (this.selected.length === 1 && this._selected[0] > selectedDate) {
338
+ this.emptySelected()
339
+ }
340
+ this.addToSelected(selectedDate)
341
+ }
342
+ }
343
+ }
344
+
345
+ private handleRangeHover(date: Date) {
346
+ if (
347
+ this.range &&
348
+ this._selected.length === 1 &&
349
+ this.isRangeAllowed(date) &&
350
+ this._selected[0] < date
351
+ ) {
352
+ this.rangeHovered = date
353
+ } else {
354
+ this.rangeHovered = null
355
+ }
356
+ }
357
+
358
+ private handleDateSelect(selectedDate: Date) {
359
+ if (this.range) {
360
+ this.handleRangeSelect(selectedDate)
361
+ } else if (this.multiple) {
362
+ this.toggleSelected(selectedDate)
363
+ } else {
364
+ this.emptySelected()
365
+ this.addToSelected(selectedDate)
366
+ }
367
+ this.dispatchEvent(
368
+ new CustomEvent('date-selected', {
369
+ detail: this.selected,
370
+ bubbles: true,
371
+ composed: true,
372
+ }),
373
+ )
374
+ }
375
+ }
@@ -0,0 +1,113 @@
1
+ import { html } from 'lit'
2
+ import { customElement, property } from 'lit/decorators.js'
3
+ import { ref } from 'lit/directives/ref.js'
4
+ import { PktElement } from '../element'
5
+
6
+ // If you need to convert an object to a list of classes, use classMap
7
+ import { classMap } from 'lit/directives/class-map.js'
8
+
9
+ // If you need text strings add them in this file and include it
10
+ import translations from '../../translations/no.json'
11
+
12
+ // If you need to convert attribute strings to JavaScript objects,
13
+ // use helpers from converters.ts
14
+ import { csvToArray } from '../../helpers/converters'
15
+
16
+ @customElement('pkt-el-component')
17
+ export class PktComponent extends PktElement {
18
+ /**
19
+ * Element attributes => props
20
+ * Example:
21
+ * <pkt-el-component string="hei" strings="hei,og,hallo" darkmode>
22
+ * Hei!
23
+ * </pkt-el-component>
24
+ */
25
+
26
+ @property({ type: String }) string: string = ''
27
+ @property({ converter: csvToArray }) strings: string[] = []
28
+ @property({ type: Boolean }) darkmode: boolean = false
29
+
30
+ /**
31
+ * Private properties, for internal use only
32
+ */
33
+
34
+ @property({ type: Array }) private _list: string[] = []
35
+
36
+ /**
37
+ * Runs on mount, used to set up various values and whatever you need to run
38
+ */
39
+ connectedCallback() {
40
+ this.strings.length &&
41
+ this.strings.forEach((string) => {
42
+ this._list.push(string.toUpperCase())
43
+ })
44
+ super.connectedCallback()
45
+ }
46
+
47
+ /**
48
+ * Render functions
49
+ */
50
+ render() {
51
+ const classes = {
52
+ 'pkt-component': true,
53
+ 'pkt-component--has-list': this.strings.length > 0,
54
+ 'pkt-darkmode': this.darkmode,
55
+ }
56
+
57
+ return html`
58
+ <div class="${classMap(classes)}">
59
+ <h1 class="pkt-txt-28">${this.string}</h1>
60
+
61
+ <h2 class="pkt-txt-22">Innhold fra attributter og funksjoner</h2>
62
+ <div>${this.renderList(this.strings)}</div>
63
+ <div>${this.renderList(this.doStuff(this._list))}</div>
64
+
65
+ <h2 class="pkt-txt-22">Slot</h2>
66
+ <div ${ref(this.defaultSlot)}>defaultSlotRef</div>
67
+ <h2 class="pkt-txt-22">Named slot</h2>
68
+ <select
69
+ name="named-slot"
70
+ ${ref(this.namedSlot)}
71
+ @change=${(e: Event) => alert((e.target as HTMLSelectElement).value)}
72
+ >
73
+ namedSlotRef
74
+ </select>
75
+
76
+ <h2 class="pkt-txt-22">Knapp som emitter en event</h2>
77
+ <button type="button" @click=${() => this.handleGreeting()}>
78
+ Si ${translations.example.hi}
79
+ </button>
80
+ </div>
81
+ `
82
+ }
83
+
84
+ private renderList(list: string[]) {
85
+ return html`
86
+ <ul>
87
+ ${list.map((i) => html`<li>${i}</li>`)}
88
+ </ul>
89
+ `
90
+ }
91
+
92
+ /**
93
+ * Add other functionality under here
94
+ */
95
+
96
+ private doStuff(val: string[]) {
97
+ return val.reverse()
98
+ }
99
+
100
+ /**
101
+ * Handlers for returning data from the component
102
+ */
103
+
104
+ private handleGreeting() {
105
+ this.dispatchEvent(
106
+ new CustomEvent('pkt-greeting', {
107
+ detail: 'Hei på deg!',
108
+ bubbles: true,
109
+ composed: true,
110
+ }),
111
+ )
112
+ }
113
+ }
@@ -0,0 +1,37 @@
1
+ import { LitElement } from 'lit'
2
+ import { Ref, createRef } from 'lit/directives/ref.js'
3
+ import { PktSlotController } from '@/controllers/pkt-slot-controller'
4
+
5
+ export class PktElement extends LitElement {
6
+ /**
7
+ * Runs on mount, used to set up various values and whatever you need to run
8
+ */
9
+ connectedCallback() {
10
+ super.connectedCallback()
11
+ }
12
+ /**
13
+ * Make sure the component renders in light DOM instead of shadow DOM
14
+ */
15
+ createRenderRoot() {
16
+ return this
17
+ }
18
+
19
+ /**
20
+ * Add support for Hot Module Reloading in dev mode
21
+ */
22
+ hotReplacedCallback() {
23
+ this.requestUpdate()
24
+ }
25
+
26
+ /**
27
+ * Set up slot support for Light DOM
28
+ */
29
+ slotController: PktSlotController
30
+ defaultSlot: Ref<HTMLElement> = createRef()
31
+ namedSlot: Ref<HTMLElement> = createRef()
32
+
33
+ constructor() {
34
+ super()
35
+ this.slotController = new PktSlotController(this, this.defaultSlot, this.namedSlot)
36
+ }
37
+ }
@@ -0,0 +1,100 @@
1
+ import { LitElement, html } from 'lit'
2
+ import { customElement, property } from 'lit/decorators.js'
3
+ import { unsafeSVG } from 'lit/directives/unsafe-svg.js'
4
+
5
+ const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
6
+ const errorSvg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"></svg>'
7
+ const dlStatus: { [key: string]: string } = {}
8
+
9
+ const downloadIconOrGetFromCache = async (name: string, path: string): Promise<string | null> => {
10
+ let i = 0
11
+ while (dlStatus[path + name + '.svg'] === 'fetching') {
12
+ i++
13
+ if (i > 50) break
14
+ await sleep(50)
15
+ }
16
+ if (localStorage.getItem(path + name + '.svg')) {
17
+ return Promise.resolve(localStorage.getItem(path + name + '.svg'))
18
+ } else if (typeof window.fetch === 'function') {
19
+ dlStatus[path + name + '.svg'] = 'fetching'
20
+ return Promise.resolve(
21
+ fetch(path + name + '.svg')
22
+ .then((response) => {
23
+ if (!response.ok) {
24
+ // eslint-disable-next-line no-console
25
+ console.error('Missing icon: ' + path + name + '.svg')
26
+ return errorSvg
27
+ } else {
28
+ return response.text()
29
+ }
30
+ })
31
+ .then((text) => {
32
+ if (text !== errorSvg) {
33
+ localStorage.setItem(path + name + '.svg', text)
34
+ }
35
+ dlStatus[path + name + '.svg'] = 'fetched'
36
+ return text
37
+ }),
38
+ )
39
+ }
40
+ return Promise.resolve(errorSvg)
41
+ }
42
+
43
+ @customElement('pkt-el-icon')
44
+ export class PktIcon extends LitElement {
45
+ /**
46
+ * Element attributes
47
+ */
48
+ @property({ type: String, reflect: true }) name: string = ''
49
+ @property({ type: String, reflect: true }) path: string =
50
+ 'https://punkt-cdn.oslo.kommune.no/latest/icons/'
51
+
52
+ @property({ type: SVGElement }) private icon: any = unsafeSVG(errorSvg)
53
+
54
+ /**
55
+ * Make sure the component renders in light DOM instead of shadow DOM
56
+ */
57
+ createRenderRoot() {
58
+ return this
59
+ }
60
+
61
+ /**
62
+ * Add support for Hot Module Reloading in dev mode
63
+ */
64
+ hotReplacedCallback() {
65
+ this.requestUpdate()
66
+ }
67
+
68
+ /**
69
+ * Runs on mount, used to set up various values and whatever you need to run
70
+ */
71
+ async connectedCallback() {
72
+ if (this.name && this.path) {
73
+ this.icon = unsafeSVG(
74
+ await downloadIconOrGetFromCache(this.name, this.path).then((res) => res),
75
+ ) as SVGElement
76
+ }
77
+ super.connectedCallback()
78
+ }
79
+
80
+ /**
81
+ * Runs every time a property changes
82
+ */
83
+ async update(changedProperties: Map<string, unknown>) {
84
+ if (changedProperties.has('name')) {
85
+ if (this.name && this.path) {
86
+ this.icon = unsafeSVG(
87
+ await downloadIconOrGetFromCache(this.name, this.path).then((res) => res),
88
+ ) as SVGElement
89
+ }
90
+ }
91
+ super.update(changedProperties)
92
+ }
93
+
94
+ /**
95
+ * Component functionality and render
96
+ */
97
+ render() {
98
+ return html`${this.icon}`
99
+ }
100
+ }
@@ -0,0 +1,3 @@
1
+ export { PktCalendar } from './calendar'
2
+ export { PktIcon } from './icon'
3
+ export { PktComponent } from './component-template'