Skip to content

Commit

Permalink
feat(widget-element)!: parse attributes to element fields
Browse files Browse the repository at this point in the history
BREAKING CHANGES: the params getter has been removed, now attributes are added as element fields
  • Loading branch information
andrepolischuk committed Aug 23, 2024
1 parent 7d2f3f7 commit adae397
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 44 deletions.
2 changes: 1 addition & 1 deletion .size-limit.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
},
{
"path": "packages/widget-element/dist/index.js",
"limit": "1.05 KB"
"limit": "950 B"
}
]
5 changes: 3 additions & 2 deletions packages/widget-element/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {WidgetElement} from '.'

class TestWidget extends WidgetElement {
root: ShadowRoot
testId: string

ready = false
changed = false
Expand Down Expand Up @@ -65,15 +66,15 @@ test('widget attribute is changed', async () => {
widget.setAttribute('test-id', '123')

expect(widget.changed).toBe(false)
expect(widget.params).toEqual({testId: '123', provider: widget})
expect(widget.testId).toBe('123')

document.body.append(widget)
widget.setAttribute('test-id', '456')

await Promise.resolve()

expect(widget.changed).toBe(true)
expect(widget.params).toEqual({testId: '456', provider: widget})
expect(widget.testId).toBe('456')
})

test('widget is destroyed', async () => {
Expand Down
50 changes: 34 additions & 16 deletions packages/widget-element/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable import/no-unused-modules */
import {getAttributesFromElement, createElementFromHtml} from './utils'

/**
* Custom Element that helps you to create widgets.
Expand All @@ -10,18 +9,16 @@ import {getAttributesFromElement, createElementFromHtml} from './utils'
* import {createApp} from './app'
*
* class CustomWidget extends WidgetElement {
* static get observedAttributes() {
* return ['app-id']
* }
* static observedAttributes = ['app-id']
*
* async initialize(shadowRoot: ShadowRoot) {
* const {appId} = this.params
* const {appId} = this
* this.app = createApp(shadowRoot)
* await this.app.render({appId})
* }
*
* attributeChanged() {
* const {appId} = this.params
* const {appId} = this
* this.app.render({appId})
* }
*
Expand Down Expand Up @@ -71,22 +68,17 @@ export class WidgetElement extends HTMLElement {
}
}

/** Widget params (an attributes map with names given in the camelCase) */
get params(): Record<string, any> {
const params = getAttributesFromElement(this)

return {...params, provider: this}
}

async connectedCallback() {
this.#fallback = createElementFromHtml(this.fallback)
this.#shadowRoot = this.attachShadow({mode: 'closed'})
this.#shadowRoot = this.#createRoot()
this.#fallback = this.#createFallback()

await this.initialize(this.#shadowRoot)
this.emit('ready')
}

attributeChangedCallback() {
attributeChangedCallback(name: string, oldValue: string, newValue: string) {
this.#updateAttribute(name, oldValue, newValue)

if (this.#shadowRoot) {
this.attributeChanged()
}
Expand All @@ -97,6 +89,32 @@ export class WidgetElement extends HTMLElement {
this.emit('destroy')
}

#createRoot() {
return this.attachShadow({mode: 'closed'})
}

#createFallback() {
const template = document.createElement('template')

template.innerHTML = this.fallback

return template.content.firstElementChild as HTMLElement
}

#updateAttribute(name: string, oldValue: string, newValue: string) {
if (newValue !== oldValue) {
const key = name.replace(/-(\w)/g, (_, char) =>
char.toUpperCase()
) as keyof this

if (typeof newValue === 'undefined') {
delete this[key]
} else {
this[key] = newValue as any
}
}
}

/** Widget is initialized, and shadow root is attached */
// eslint-disable-next-line no-empty-function
initialize(_shadowRoot: ShadowRoot) {}
Expand Down
25 changes: 0 additions & 25 deletions packages/widget-element/utils.ts

This file was deleted.

0 comments on commit adae397

Please sign in to comment.