From 9233b7b61a556117dc3a26d645121bdb0763af8c Mon Sep 17 00:00:00 2001 From: Phil Parsons Date: Mon, 23 Dec 2024 07:33:48 +0000 Subject: [PATCH] feat(share-button): small perf and size refactor for v1 release --- .changeset/tender-teachers-breathe.md | 5 ++ .gitignore | 1 + packages/share-button/README.md | 21 ++++---- packages/share-button/ShareButton.js | 77 ++++++++++++--------------- packages/share-button/min.js.map | 7 +++ packages/share-button/package.json | 9 ++-- stories/ShareButton.stories.js | 10 ++++ 7 files changed, 71 insertions(+), 59 deletions(-) create mode 100644 .changeset/tender-teachers-breathe.md create mode 100644 packages/share-button/min.js.map diff --git a/.changeset/tender-teachers-breathe.md b/.changeset/tender-teachers-breathe.md new file mode 100644 index 0000000..2abb02a --- /dev/null +++ b/.changeset/tender-teachers-breathe.md @@ -0,0 +1,5 @@ +--- +'@parsonic/share-button': major +--- + +Tidy up and release as v1 diff --git a/.gitignore b/.gitignore index f06235c..3f61650 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ node_modules dist +packages/share-button/min.js diff --git a/packages/share-button/README.md b/packages/share-button/README.md index 56ebd99..2cd50f9 100644 --- a/packages/share-button/README.md +++ b/packages/share-button/README.md @@ -21,8 +21,7 @@ Add the script tag and use the button in your page. ```html ``` @@ -68,7 +67,7 @@ supports it. If the share feature is not available the component will not be defined and will either show the fallback content or no button at all. For control over the share data you can provide the share button with data -attribute. Below is an example using Nunjucks template syntax. +attributes. Below is an example using Nunjucks template syntax. ```html ``` -Style the button use the `button` part selector. +Style the button using the `button` part selector. ```css share-button::part(button) { @@ -121,9 +120,9 @@ Provide your own button in the `button` slot. ## Share event -When the share button is clicked a custom event with the name `share` is -dispatched. This event has the share data as the payload, bubbles and is -cancelable. +When the share button is clicked a [custom event][custom-event] with the +name `share` is dispatched. This event has the share data as the payload, +bubbles and is cancelable. ```js // Example metric capture @@ -143,9 +142,10 @@ document.addEventListener('share', (ev) => { ## Fallback content -Fallback content can be provided if for some reason the native share -function isn't available or the scripts aren't loaded. Please see this -[blog post][blog-post] for thorough explanation of using fallback content. +Fallback content can be provided for situations where the native share +function isn't available or the component script isn't loaded. Please see +this [blog post][blog-post] for thorough explanation of using fallback +content. ```html @@ -164,5 +164,6 @@ function isn't available or the scripts aren't loaded. Please see this [share]: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share [open-graph]: https://ogp.me/ +[custom-event]: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent [dist]: https://cdn.jsdelivr.net/npm/@parsonic/share-button@0.2.0/dist/ [blog-post]: https://philparsons.co.uk/blog/dont-fouc-up-your-web-components/ diff --git a/packages/share-button/ShareButton.js b/packages/share-button/ShareButton.js index eac1a19..5da5b33 100644 --- a/packages/share-button/ShareButton.js +++ b/packages/share-button/ShareButton.js @@ -6,6 +6,14 @@ if (typeof HTMLElement !== 'undefined') { BaseElement = class {} } +function getGraphContent(property, defaultValue) { + return ( + document + .querySelector(`meta[property='og:${property}']`) + ?.getAttribute('content') ?? defaultValue + ) +} + export default class ShareButton extends BaseElement { static register(tag = 'share-button') { if ('share' in navigator) { @@ -14,60 +22,41 @@ export default class ShareButton extends BaseElement { } connectedCallback() { - let { url, text, title, buttonLabel } = this.dataset - - if (!url) { - url = - document - .querySelector("meta[property='og:url']") - ?.getAttribute('content') ?? location.href - } + const defaultButton = document.createElement('button') + defaultButton.textContent = this.dataset.buttonLabel ?? 'Share' + defaultButton.setAttribute('part', 'button') - if (!text) { - text = document - .querySelector("meta[property='og:description']") - ?.getAttribute('content') - } + const slot = document.createElement('slot') + slot.setAttribute('name', 'button') + slot.appendChild(defaultButton) - if (!title) { - title = - document - .querySelector("meta[property='og:title']") - ?.getAttribute('content') ?? document.title - } + const shadowRoot = this.attachShadow({ mode: 'open' }) + shadowRoot.appendChild(slot) - const data = { url, text, title } + slot.addEventListener('click', async () => { + let { + url = getGraphContent('url', location.href), + title = getGraphContent('title', document.title), + text = getGraphContent('description'), + } = this.dataset - if (navigator.canShare(data)) { - const defaultButton = document.createElement('button') - defaultButton.textContent = buttonLabel ?? 'Share' - defaultButton.setAttribute('part', 'button') + const data = { url, text, title } - const slot = document.createElement('slot') - slot.setAttribute('name', 'button') - slot.appendChild(defaultButton) - - const shadowRoot = this.attachShadow({ mode: 'open' }) - shadowRoot.appendChild(slot) - - slot.addEventListener('click', async (ev) => { - ev.preventDefault() - - const canShare = this.dispatchEvent( + if ( + navigator.canShare(data) && + this.dispatchEvent( new CustomEvent('share', { cancelable: true, bubbles: true, detail: data, }) ) - - if (canShare) { - try { - await navigator.share(data) - // eslint-disable-next-line no-empty, no-unused-vars - } catch (err) {} - } - }) - } + ) { + try { + await navigator.share(data) + // eslint-disable-next-line no-empty, no-unused-vars + } catch (err) {} + } + }) } } diff --git a/packages/share-button/min.js.map b/packages/share-button/min.js.map new file mode 100644 index 0000000..7de714e --- /dev/null +++ b/packages/share-button/min.js.map @@ -0,0 +1,7 @@ +{ + "version": 3, + "sources": ["ShareButton.js", "index.js"], + "sourcesContent": ["let BaseElement\n\nif (typeof HTMLElement !== 'undefined') {\n BaseElement = HTMLElement\n} else {\n BaseElement = class { }\n}\n\nfunction getGraphContent(property, defaultValue) {\n return (\n document\n .querySelector(`meta[property='og:${property}']`)\n ?.getAttribute('content') ?? defaultValue\n )\n}\n\nexport default class ShareButton extends BaseElement {\n static register(tag = 'share-button') {\n if ('share' in navigator) {\n customElements.define(tag, ShareButton)\n }\n }\n\n connectedCallback() {\n const defaultButton = document.createElement('button')\n defaultButton.textContent = this.dataset.buttonLabel ?? 'Share'\n defaultButton.setAttribute('part', 'button')\n\n const slot = document.createElement('slot')\n slot.setAttribute('name', 'button')\n slot.appendChild(defaultButton)\n\n const shadowRoot = this.attachShadow({ mode: 'open' })\n shadowRoot.appendChild(slot)\n\n slot.addEventListener('click', async () => {\n let {\n url = getGraphContent('url', location.href),\n title = getGraphContent('title', document.title),\n text = getGraphContent('description'),\n } = this.dataset\n\n const data = { url, text, title }\n\n if (\n navigator.canShare(data) &&\n this.dispatchEvent(\n new CustomEvent('share', {\n cancelable: true,\n bubbles: true,\n detail: data,\n })\n )\n ) {\n try {\n await navigator.share(data)\n // eslint-disable-next-line no-empty, no-unused-vars\n } catch (err) { }\n }\n })\n }\n}\n", "import ShareButton from './ShareButton'\n\nShareButton.register()\n"], + "mappings": "MAAA,IAAIA,EAEA,OAAO,YAAgB,IACzBA,EAAc,YAEdA,EAAc,KAAM,CAAE,EAGxB,SAASC,EAAgBC,EAAUC,EAAc,CAC/C,OACE,SACG,cAAc,qBAAqBD,CAAQ,IAAI,GAC9C,aAAa,SAAS,GAAKC,CAEnC,CAEA,IAAqBC,EAArB,MAAqBC,UAAoBL,CAAY,CACnD,OAAO,SAASM,EAAM,eAAgB,CAChC,UAAW,WACb,eAAe,OAAOA,EAAKD,CAAW,CAE1C,CAEA,mBAAoB,CAClB,IAAME,EAAgB,SAAS,cAAc,QAAQ,EACrDA,EAAc,YAAc,KAAK,QAAQ,aAAe,QACxDA,EAAc,aAAa,OAAQ,QAAQ,EAE3C,IAAMC,EAAO,SAAS,cAAc,MAAM,EAC1CA,EAAK,aAAa,OAAQ,QAAQ,EAClCA,EAAK,YAAYD,CAAa,EAEX,KAAK,aAAa,CAAE,KAAM,MAAO,CAAC,EAC1C,YAAYC,CAAI,EAE3BA,EAAK,iBAAiB,QAAS,SAAY,CACzC,GAAI,CACF,IAAAC,EAAMR,EAAgB,MAAO,SAAS,IAAI,EAC1C,MAAAS,EAAQT,EAAgB,QAAS,SAAS,KAAK,EAC/C,KAAAU,EAAOV,EAAgB,aAAa,CACtC,EAAI,KAAK,QAEHW,EAAO,CAAE,IAAAH,EAAK,KAAAE,EAAM,MAAAD,CAAM,EAEhC,GACE,UAAU,SAASE,CAAI,GACvB,KAAK,cACH,IAAI,YAAY,QAAS,CACvB,WAAY,GACZ,QAAS,GACT,OAAQA,CACV,CAAC,CACH,EAEA,GAAI,CACF,MAAM,UAAU,MAAMA,CAAI,CAE5B,MAAc,CAAE,CAEpB,CAAC,CACH,CACF,EC3DAC,EAAY,SAAS", + "names": ["BaseElement", "getGraphContent", "property", "defaultValue", "ShareButton", "_ShareButton", "tag", "defaultButton", "slot", "url", "title", "text", "data", "ShareButton"] +} diff --git a/packages/share-button/package.json b/packages/share-button/package.json index 13fceab..85043f1 100644 --- a/packages/share-button/package.json +++ b/packages/share-button/package.json @@ -6,13 +6,12 @@ "type": "module", "repository": { "type": "git", - "url": "https://github.com/p-m-p/parsonic/tree/main/packages/share-button" + "url": "https://github.com/p-m-p/parsonic" }, "scripts": { - "build": "esbuild index.js ShareButton.js --bundle --minify --sourcemap --outdir=dist --format=esm", - "clean": "rm -rf dist", - "prepare": "cp ../../LICENSE ./", - "test": "echo \"Error: no test specified\" && exit 1" + "build": "esbuild index.js --bundle --minify --sourcemap --outfile=min.js --format=iife", + "clean": "rm -f min.*", + "prepare": "cp ../../LICENSE ./" }, "keywords": [ "button", diff --git a/stories/ShareButton.stories.js b/stories/ShareButton.stories.js index bf4694d..87529a5 100644 --- a/stories/ShareButton.stories.js +++ b/stories/ShareButton.stories.js @@ -6,6 +6,7 @@ import './share-button.css' ShareButton.register('test-button') export default { + tags: ['autodocs'], title: 'ShareButton', } @@ -17,6 +18,15 @@ export const Label = { render: () => html``, } +export const Attributes = { + render: () => + html``, +} + export const Styled = { render: () => html``, }