drab 4.1.7 → 5.0.0-beta.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/LICENSE.md +1 -1
- package/README.md +26 -103
- package/animate/define.d.ts +2 -0
- package/animate/define.iife.js +1 -0
- package/animate/define.js +1 -0
- package/animate/index.d.ts +54 -0
- package/animate/index.iife.js +1 -0
- package/animate/index.js +1 -0
- package/base/define.d.ts +2 -0
- package/base/define.iife.js +1 -0
- package/base/define.js +1 -0
- package/base/index.d.ts +69 -0
- package/base/index.iife.js +1 -0
- package/base/index.js +1 -0
- package/breakpoint/define.d.ts +2 -0
- package/breakpoint/define.iife.js +1 -0
- package/breakpoint/define.js +1 -0
- package/breakpoint/index.d.ts +24 -0
- package/breakpoint/index.iife.js +1 -0
- package/breakpoint/index.js +1 -0
- package/chunk-2ZZQECRY.js +1 -0
- package/chunk-57VEEUFG.js +1 -0
- package/chunk-5JV4T7GM.js +1 -0
- package/chunk-6HYPZWQ4.js +1 -0
- package/chunk-7F7CQUEG.js +1 -0
- package/chunk-7KU2PRW5.js +1 -0
- package/chunk-7S6DTKGH.js +1 -0
- package/chunk-FNJ7AESC.js +9 -0
- package/chunk-IQJQPZUL.js +1 -0
- package/chunk-JMJUWKN2.js +1 -0
- package/chunk-MXKU7AKV.js +1 -0
- package/chunk-T7RZI3ZL.js +1 -0
- package/chunk-TSTTUEAF.js +1 -0
- package/chunk-VEVFQB5N.js +1 -0
- package/contextmenu/define.d.ts +2 -0
- package/contextmenu/define.iife.js +1 -0
- package/contextmenu/define.js +1 -0
- package/contextmenu/index.d.ts +15 -0
- package/contextmenu/index.iife.js +1 -0
- package/contextmenu/index.js +1 -0
- package/copy/define.d.ts +2 -0
- package/copy/define.iife.js +1 -0
- package/copy/define.js +1 -0
- package/copy/index.d.ts +13 -0
- package/copy/index.iife.js +1 -0
- package/copy/index.js +1 -0
- package/define/index.d.ts +2 -0
- package/define/index.iife.js +9 -0
- package/define/index.js +1 -0
- package/details/define.d.ts +2 -0
- package/details/define.iife.js +1 -0
- package/details/define.js +1 -0
- package/details/index.d.ts +23 -0
- package/details/index.iife.js +1 -0
- package/details/index.js +1 -0
- package/dialog/define.d.ts +2 -0
- package/dialog/define.iife.js +1 -0
- package/dialog/define.js +1 -0
- package/dialog/index.d.ts +20 -0
- package/dialog/index.iife.js +1 -0
- package/dialog/index.js +1 -0
- package/editor/define.d.ts +2 -0
- package/editor/define.iife.js +9 -0
- package/editor/define.js +1 -0
- package/editor/index.d.ts +58 -0
- package/editor/index.iife.js +9 -0
- package/editor/index.js +1 -0
- package/fullscreen/define.d.ts +2 -0
- package/fullscreen/define.iife.js +1 -0
- package/fullscreen/define.js +1 -0
- package/fullscreen/index.d.ts +23 -0
- package/fullscreen/index.iife.js +1 -0
- package/fullscreen/index.js +1 -0
- package/index-SyRipepB.d.ts +17 -0
- package/index.d.ts +14 -0
- package/index.iife.js +9 -0
- package/index.js +1 -0
- package/package.json +130 -59
- package/popover/define.d.ts +2 -0
- package/popover/define.iife.js +1 -0
- package/popover/define.js +1 -0
- package/popover/index.d.ts +29 -0
- package/popover/index.iife.js +1 -0
- package/popover/index.js +1 -0
- package/share/define.d.ts +2 -0
- package/share/define.iife.js +1 -0
- package/share/define.js +1 -0
- package/share/index.d.ts +19 -0
- package/share/index.iife.js +1 -0
- package/share/index.js +1 -0
- package/tablesort/define.d.ts +2 -0
- package/tablesort/define.iife.js +1 -0
- package/tablesort/define.js +1 -0
- package/tablesort/index.d.ts +21 -0
- package/tablesort/index.iife.js +1 -0
- package/tablesort/index.js +1 -0
- package/youtube/define.d.ts +2 -0
- package/youtube/define.iife.js +1 -0
- package/youtube/define.js +1 -0
- package/youtube/index.d.ts +29 -0
- package/youtube/index.iife.js +1 -0
- package/youtube/index.js +1 -0
- package/dist/components/Breakpoint.svelte +0 -55
- package/dist/components/Breakpoint.svelte.d.ts +0 -46
- package/dist/components/ContextMenu.svelte +0 -150
- package/dist/components/ContextMenu.svelte.d.ts +0 -76
- package/dist/components/CopyButton.svelte +0 -97
- package/dist/components/CopyButton.svelte.d.ts +0 -60
- package/dist/components/DataTable.svelte +0 -208
- package/dist/components/DataTable.svelte.d.ts +0 -155
- package/dist/components/Details.svelte +0 -101
- package/dist/components/Details.svelte.d.ts +0 -67
- package/dist/components/Editor.svelte +0 -404
- package/dist/components/Editor.svelte.d.ts +0 -111
- package/dist/components/FrettedChord.svelte +0 -213
- package/dist/components/FrettedChord.svelte.d.ts +0 -79
- package/dist/components/FullscreenButton.svelte +0 -95
- package/dist/components/FullscreenButton.svelte.d.ts +0 -62
- package/dist/components/Popover.svelte +0 -153
- package/dist/components/Popover.svelte.d.ts +0 -80
- package/dist/components/ShareButton.svelte +0 -133
- package/dist/components/ShareButton.svelte.d.ts +0 -93
- package/dist/components/Sheet.svelte +0 -180
- package/dist/components/Sheet.svelte.d.ts +0 -99
- package/dist/components/Tablature.svelte +0 -173
- package/dist/components/Tablature.svelte.d.ts +0 -93
- package/dist/components/YouTube.svelte +0 -51
- package/dist/components/YouTube.svelte.d.ts +0 -49
- package/dist/index.d.ts +0 -14
- package/dist/index.js +0 -14
- package/dist/util/accessibility.d.ts +0 -6
- package/dist/util/accessibility.js +0 -11
- package/dist/util/delay.d.ts +0 -1
- package/dist/util/delay.js +0 -1
- package/dist/util/transition.d.ts +0 -2
- package/dist/util/transition.js +0 -2
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(()=>{var f=class extends HTMLElement{#e=new AbortController;constructor(){super()}get event(){return this.getAttribute("event")??"click"}set event(e){this.setAttribute("event",e)}getTrigger(){return this.querySelectorAll(this.getAttribute("trigger")??"[data-trigger]")}getContent(e=HTMLElement){let s=this.querySelector(this.getAttribute("content")??"[data-content]");if(s instanceof e)return s;throw new Error("Content not found")}swapContent(e=!0,s=800){let t=this.querySelector(this.getAttribute("swap")??"[data-swap]");if(t){let n=Array.from(this.getContent().childNodes);t instanceof HTMLTemplateElement?this.getContent().replaceChildren(t.content.cloneNode(!0)):this.getContent().replaceChildren(...t.childNodes),e&&setTimeout(()=>this.getContent().replaceChildren(...n),s)}}safeListener(e,s,t=document.body,n={}){n.signal=this.#e.signal,t.addEventListener(e,s,n)}triggerListener(e,s=this.event){for(let t of this.getTrigger())t.addEventListener(s,e)}mount(){}connectedCallback(){queueMicrotask(()=>this.mount())}disconnectedCallback(){this.#e.abort()}};var m=class extends f{constructor(){super()}get animationOptions(){let e={};for(let s of this.getAttributeNames())if(s.startsWith("animation-option-")){let t=this.getAttribute(s),[,,n]=s.split("-");t&&(n==="duration"||n==="delay"?e[n]=Number(t):n==="easing"&&(e[n]=t))}return e}async animateElement(e={element:this.getContent(),options:{}}){let{element:s=this.getContent(),options:t={}}=e,n=this.keyframes;if(n.length&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches){t=Object.assign(this.animationOptions,t),t.duration||(t.duration=200),t.easing||(t.easing="ease-in-out");let o=n.at(0),i=n.at(-1);if(o&&i){let a=["composite","easing","offset"];for(let l of a)delete o[l],delete i[l]}t.direction?.includes("reverse")&&([o,i]=[i,o]),Object.assign(s.style,o),await s.animate(n,t).finished,Object.assign(s.style,i)}}get keyframes(){let e=[];for(let s of this.getAttributeNames()){let t=this.getAttribute(s),[,,n,...o]=s.split("-");if(s.startsWith("animation-keyframe-")){let i=o.map((r,a)=>a<1?r:r.at(0)?.toUpperCase()+r.slice(1)).join("");if(n&&i){n==="from"?n="0":n==="to"?n="1":n=String(parseInt(n)*.01);let r=Number(n),a=e.find(l=>l.offset===r);a?a[i]=t:e.push({[i]:t,offset:r})}}}return e.sort((s,t)=>Number(s.offset)-Number(t.offset)),e}};var c=class extends m{constructor(){super()}get open(){return this.hasAttribute("open")}set open(e){e?this.setAttribute("open",""):this.removeAttribute("open")}async show(){this.getContent().showPopover(),await this.animateElement()}async hide(){await this.animateElement({options:{direction:"reverse"}}),this.getContent().hidePopover()}async toggle(){this.open?this.hide():this.show()}mount(){this.triggerListener(e=>{e.preventDefault(),this.toggle()}),this.getContent().addEventListener("toggle",e=>{e.newState==="open"?this.open=!0:this.open=!1}),this.safeListener("keydown",e=>{e.key==="Escape"&&this.open&&(e.preventDefault(),this.hide())})}};customElements.define("drab-popover",c);})();
|
@@ -0,0 +1 @@
|
|
1
|
+
import{a as o}from"../chunk-T7RZI3ZL.js";import"../chunk-7KU2PRW5.js";import"../chunk-MXKU7AKV.js";customElements.define("drab-popover",o);
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { Animate } from '../animate/index.js';
|
2
|
+
import '../base/index.js';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Provides animations for the Popover API.
|
6
|
+
*
|
7
|
+
* The Popover API is not currently support in FireFox. [See the latest browser compatibility on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Popover_API#browser_compatibility).
|
8
|
+
*
|
9
|
+
* This component can be deprecated once it can be animated with CSS only,
|
10
|
+
* currently [only available in Chrome](https://developer.chrome.com/blog/introducing-popover-api#interactive_entry_and_exit).
|
11
|
+
*/
|
12
|
+
declare class Popover extends Animate {
|
13
|
+
constructor();
|
14
|
+
/**
|
15
|
+
* Whether the popover is open or closed. This doesn't get set
|
16
|
+
* automatically on the element like with the `HTMLDialogElement`.
|
17
|
+
*/
|
18
|
+
get open(): boolean;
|
19
|
+
set open(value: boolean);
|
20
|
+
/** `HTMLElement.showPopover()` with animation. */
|
21
|
+
show(): Promise<void>;
|
22
|
+
/** `HTMLElement.hidePopover()` with animation. */
|
23
|
+
hide(): Promise<void>;
|
24
|
+
/** `show` or `hide` depending on the current state. */
|
25
|
+
toggle(): Promise<void>;
|
26
|
+
mount(): void;
|
27
|
+
}
|
28
|
+
|
29
|
+
export { Popover };
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(()=>{var f=class extends HTMLElement{#e=new AbortController;constructor(){super()}get event(){return this.getAttribute("event")??"click"}set event(e){this.setAttribute("event",e)}getTrigger(){return this.querySelectorAll(this.getAttribute("trigger")??"[data-trigger]")}getContent(e=HTMLElement){let s=this.querySelector(this.getAttribute("content")??"[data-content]");if(s instanceof e)return s;throw new Error("Content not found")}swapContent(e=!0,s=800){let t=this.querySelector(this.getAttribute("swap")??"[data-swap]");if(t){let n=Array.from(this.getContent().childNodes);t instanceof HTMLTemplateElement?this.getContent().replaceChildren(t.content.cloneNode(!0)):this.getContent().replaceChildren(...t.childNodes),e&&setTimeout(()=>this.getContent().replaceChildren(...n),s)}}safeListener(e,s,t=document.body,n={}){n.signal=this.#e.signal,t.addEventListener(e,s,n)}triggerListener(e,s=this.event){for(let t of this.getTrigger())t.addEventListener(s,e)}mount(){}connectedCallback(){queueMicrotask(()=>this.mount())}disconnectedCallback(){this.#e.abort()}};var m=class extends f{constructor(){super()}get animationOptions(){let e={};for(let s of this.getAttributeNames())if(s.startsWith("animation-option-")){let t=this.getAttribute(s),[,,n]=s.split("-");t&&(n==="duration"||n==="delay"?e[n]=Number(t):n==="easing"&&(e[n]=t))}return e}async animateElement(e={element:this.getContent(),options:{}}){let{element:s=this.getContent(),options:t={}}=e,n=this.keyframes;if(n.length&&!window.matchMedia("(prefers-reduced-motion: reduce)").matches){t=Object.assign(this.animationOptions,t),t.duration||(t.duration=200),t.easing||(t.easing="ease-in-out");let o=n.at(0),i=n.at(-1);if(o&&i){let a=["composite","easing","offset"];for(let l of a)delete o[l],delete i[l]}t.direction?.includes("reverse")&&([o,i]=[i,o]),Object.assign(s.style,o),await s.animate(n,t).finished,Object.assign(s.style,i)}}get keyframes(){let e=[];for(let s of this.getAttributeNames()){let t=this.getAttribute(s),[,,n,...o]=s.split("-");if(s.startsWith("animation-keyframe-")){let i=o.map((r,a)=>a<1?r:r.at(0)?.toUpperCase()+r.slice(1)).join("");if(n&&i){n==="from"?n="0":n==="to"?n="1":n=String(parseInt(n)*.01);let r=Number(n),a=e.find(l=>l.offset===r);a?a[i]=t:e.push({[i]:t,offset:r})}}}return e.sort((s,t)=>Number(s.offset)-Number(t.offset)),e}};var h=class extends m{constructor(){super()}get open(){return this.hasAttribute("open")}set open(e){e?this.setAttribute("open",""):this.removeAttribute("open")}async show(){this.getContent().showPopover(),await this.animateElement()}async hide(){await this.animateElement({options:{direction:"reverse"}}),this.getContent().hidePopover()}async toggle(){this.open?this.hide():this.show()}mount(){this.triggerListener(e=>{e.preventDefault(),this.toggle()}),this.getContent().addEventListener("toggle",e=>{e.newState==="open"?this.open=!0:this.open=!1}),this.safeListener("keydown",e=>{e.key==="Escape"&&this.open&&(e.preventDefault(),this.hide())})}};})();
|
package/popover/index.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
import{a}from"../chunk-T7RZI3ZL.js";import"../chunk-7KU2PRW5.js";import"../chunk-MXKU7AKV.js";export{a as Popover};
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(()=>{var s=class extends HTMLElement{#e=new AbortController;constructor(){super()}get event(){return this.getAttribute("event")??"click"}set event(e){this.setAttribute("event",e)}getTrigger(){return this.querySelectorAll(this.getAttribute("trigger")??"[data-trigger]")}getContent(e=HTMLElement){let t=this.querySelector(this.getAttribute("content")??"[data-content]");if(t instanceof e)return t;throw new Error("Content not found")}swapContent(e=!0,t=800){let n=this.querySelector(this.getAttribute("swap")??"[data-swap]");if(n){let r=Array.from(this.getContent().childNodes);n instanceof HTMLTemplateElement?this.getContent().replaceChildren(n.content.cloneNode(!0)):this.getContent().replaceChildren(...n.childNodes),e&&setTimeout(()=>this.getContent().replaceChildren(...r),t)}}safeListener(e,t,n=document.body,r={}){r.signal=this.#e.signal,n.addEventListener(e,t,r)}triggerListener(e,t=this.event){for(let n of this.getTrigger())n.addEventListener(t,e)}mount(){}connectedCallback(){queueMicrotask(()=>this.mount())}disconnectedCallback(){this.#e.abort()}};var i=class extends s{constructor(){super()}get value(){return this.getAttribute("value")??""}set value(e){this.setAttribute("value",e)}async copy(e=this.value){await navigator.clipboard.writeText(e),this.swapContent()}};var o=class extends i{constructor(){super()}async share(e=this.value){if(navigator.canShare&&navigator.canShare({url:e}))try{await navigator.share({url:e})}catch(t){t?.name!=="AbortError"&&console.error(t)}else this.copy()}mount(){this.triggerListener(async()=>await this.share())}};customElements.define("drab-share",o);})();
|
package/share/define.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
import{a as e}from"../chunk-IQJQPZUL.js";import"../chunk-7F7CQUEG.js";import"../chunk-MXKU7AKV.js";customElements.define("drab-share",e);
|
package/share/index.d.ts
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
import { B as BaseCopy } from '../index-SyRipepB.js';
|
2
|
+
import '../base/index.js';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Uses the [Navigator API](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share) to share a `url`. If `share` is not supported, falls back to copy the text instead.
|
6
|
+
*/
|
7
|
+
declare class Share extends BaseCopy {
|
8
|
+
constructor();
|
9
|
+
/**
|
10
|
+
* Shares or copies the `value`.
|
11
|
+
* @param url The `url` to share, defaults to `this.value`
|
12
|
+
* @returns An object containing a `result` - whether the `url` was copied or shared
|
13
|
+
* depending on browser support.
|
14
|
+
*/
|
15
|
+
share(url?: string): Promise<void>;
|
16
|
+
mount(): void;
|
17
|
+
}
|
18
|
+
|
19
|
+
export { Share };
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(()=>{var s=class extends HTMLElement{#e=new AbortController;constructor(){super()}get event(){return this.getAttribute("event")??"click"}set event(e){this.setAttribute("event",e)}getTrigger(){return this.querySelectorAll(this.getAttribute("trigger")??"[data-trigger]")}getContent(e=HTMLElement){let t=this.querySelector(this.getAttribute("content")??"[data-content]");if(t instanceof e)return t;throw new Error("Content not found")}swapContent(e=!0,t=800){let n=this.querySelector(this.getAttribute("swap")??"[data-swap]");if(n){let r=Array.from(this.getContent().childNodes);n instanceof HTMLTemplateElement?this.getContent().replaceChildren(n.content.cloneNode(!0)):this.getContent().replaceChildren(...n.childNodes),e&&setTimeout(()=>this.getContent().replaceChildren(...r),t)}}safeListener(e,t,n=document.body,r={}){r.signal=this.#e.signal,n.addEventListener(e,t,r)}triggerListener(e,t=this.event){for(let n of this.getTrigger())n.addEventListener(t,e)}mount(){}connectedCallback(){queueMicrotask(()=>this.mount())}disconnectedCallback(){this.#e.abort()}};var i=class extends s{constructor(){super()}get value(){return this.getAttribute("value")??""}set value(e){this.setAttribute("value",e)}async copy(e=this.value){await navigator.clipboard.writeText(e),this.swapContent()}};var a=class extends i{constructor(){super()}async share(e=this.value){if(navigator.canShare&&navigator.canShare({url:e}))try{await navigator.share({url:e})}catch(t){t?.name!=="AbortError"&&console.error(t)}else this.copy()}mount(){this.triggerListener(async()=>await this.share())}};})();
|
package/share/index.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
import{a}from"../chunk-IQJQPZUL.js";import"../chunk-7F7CQUEG.js";import"../chunk-MXKU7AKV.js";export{a as Share};
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(()=>{var n=class extends HTMLElement{#t=new AbortController;constructor(){super()}get event(){return this.getAttribute("event")??"click"}set event(t){this.setAttribute("event",t)}getTrigger(){return this.querySelectorAll(this.getAttribute("trigger")??"[data-trigger]")}getContent(t=HTMLElement){let e=this.querySelector(this.getAttribute("content")??"[data-content]");if(e instanceof t)return e;throw new Error("Content not found")}swapContent(t=!0,e=800){let s=this.querySelector(this.getAttribute("swap")??"[data-swap]");if(s){let r=Array.from(this.getContent().childNodes);s instanceof HTMLTemplateElement?this.getContent().replaceChildren(s.content.cloneNode(!0)):this.getContent().replaceChildren(...s.childNodes),t&&setTimeout(()=>this.getContent().replaceChildren(...r),e)}}safeListener(t,e,s=document.body,r={}){r.signal=this.#t.signal,s.addEventListener(t,e,r)}triggerListener(t,e=this.event){for(let s of this.getTrigger())s.addEventListener(e,t)}mount(){}connectedCallback(){queueMicrotask(()=>this.mount())}disconnectedCallback(){this.#t.abort()}};var o=class extends n{constructor(){super()}mount(){let t=this.getContent(HTMLTableSectionElement);for(let e of this.getTrigger())e.addEventListener(this.event,()=>{Array.from(t.querySelectorAll("tr")).sort(d(e,e.toggleAttribute("data-ascending"))).forEach(s=>t.appendChild(s))})}},d=(i,t)=>(s,r)=>{let u=Array.from(i.parentNode?.children??[]).indexOf(i);return((a,c)=>{let m=i.dataset.type??"string";if(m==="string")return new Intl.Collator().compare(a,c);if(m==="boolean"){let l=f=>["0","false","null","undefined"].includes(f)?!1:!!f;return l(a)===l(c)?0:l(a)?-1:1}else return Number(a)-Number(c)})(p(t?s:r,u),p(t?r:s,u))},p=(i,t)=>{let e=i.children[t];return e instanceof HTMLElement?e.dataset.value??e.textContent??"":""};customElements.define("drab-tablesort",o);})();
|
@@ -0,0 +1 @@
|
|
1
|
+
import{a as e}from"../chunk-2ZZQECRY.js";import"../chunk-VEVFQB5N.js";import"../chunk-FNJ7AESC.js";import"../chunk-5JV4T7GM.js";import"../chunk-T7RZI3ZL.js";import"../chunk-IQJQPZUL.js";import"../chunk-57VEEUFG.js";import"../chunk-TSTTUEAF.js";import"../chunk-7F7CQUEG.js";import"../chunk-JMJUWKN2.js";import"../chunk-7S6DTKGH.js";import"../chunk-7KU2PRW5.js";import"../chunk-6HYPZWQ4.js";import"../chunk-MXKU7AKV.js";customElements.define("drab-tablesort",e);
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import { Base } from '../base/index.js';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Wrap a `HTMLTableElement` in the `TableSort` element to have sortable column
|
5
|
+
* headers. Set each `th` that you want to sort to the `trigger`. Set the `tbody`
|
6
|
+
* element to the `content`.
|
7
|
+
*
|
8
|
+
* The values of each cell default to the cell's `textContent`. If you would like to
|
9
|
+
* provide an alternate value than what appears in the cell to sort by instead,
|
10
|
+
* you can set a different value using the `data-value` attribute on the cell.
|
11
|
+
*
|
12
|
+
* The cells will be sorted as `string` by default. If you want to provide a different
|
13
|
+
* datatype `number` or `boolean`, set `data-type="number"` on the corresponding
|
14
|
+
* `th`/`trigger` element. The data will be converted to the specified type before sorting.
|
15
|
+
*/
|
16
|
+
declare class TableSort extends Base {
|
17
|
+
constructor();
|
18
|
+
mount(): void;
|
19
|
+
}
|
20
|
+
|
21
|
+
export { TableSort };
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(()=>{var n=class extends HTMLElement{#t=new AbortController;constructor(){super()}get event(){return this.getAttribute("event")??"click"}set event(t){this.setAttribute("event",t)}getTrigger(){return this.querySelectorAll(this.getAttribute("trigger")??"[data-trigger]")}getContent(t=HTMLElement){let e=this.querySelector(this.getAttribute("content")??"[data-content]");if(e instanceof t)return e;throw new Error("Content not found")}swapContent(t=!0,e=800){let s=this.querySelector(this.getAttribute("swap")??"[data-swap]");if(s){let r=Array.from(this.getContent().childNodes);s instanceof HTMLTemplateElement?this.getContent().replaceChildren(s.content.cloneNode(!0)):this.getContent().replaceChildren(...s.childNodes),t&&setTimeout(()=>this.getContent().replaceChildren(...r),e)}}safeListener(t,e,s=document.body,r={}){r.signal=this.#t.signal,s.addEventListener(t,e,r)}triggerListener(t,e=this.event){for(let s of this.getTrigger())s.addEventListener(e,t)}mount(){}connectedCallback(){queueMicrotask(()=>this.mount())}disconnectedCallback(){this.#t.abort()}};var c=class extends n{constructor(){super()}mount(){let t=this.getContent(HTMLTableSectionElement);for(let e of this.getTrigger())e.addEventListener(this.event,()=>{Array.from(t.querySelectorAll("tr")).sort(d(e,e.toggleAttribute("data-ascending"))).forEach(s=>t.appendChild(s))})}},d=(i,t)=>(s,r)=>{let u=Array.from(i.parentNode?.children??[]).indexOf(i);return((o,h)=>{let m=i.dataset.type??"string";if(m==="string")return new Intl.Collator().compare(o,h);if(m==="boolean"){let a=f=>["0","false","null","undefined"].includes(f)?!1:!!f;return a(o)===a(h)?0:a(o)?-1:1}else return Number(o)-Number(h)})(p(t?s:r,u),p(t?r:s,u))},p=(i,t)=>{let e=i.children[t];return e instanceof HTMLElement?e.dataset.value??e.textContent??"":""};})();
|
@@ -0,0 +1 @@
|
|
1
|
+
import{a}from"../chunk-2ZZQECRY.js";import"../chunk-VEVFQB5N.js";import"../chunk-FNJ7AESC.js";import"../chunk-5JV4T7GM.js";import"../chunk-T7RZI3ZL.js";import"../chunk-IQJQPZUL.js";import"../chunk-57VEEUFG.js";import"../chunk-TSTTUEAF.js";import"../chunk-7F7CQUEG.js";import"../chunk-JMJUWKN2.js";import"../chunk-7S6DTKGH.js";import"../chunk-7KU2PRW5.js";import"../chunk-6HYPZWQ4.js";import"../chunk-MXKU7AKV.js";export{a as TableSort};
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(()=>{var s=class extends HTMLElement{#t=new AbortController;constructor(){super()}get event(){return this.getAttribute("event")??"click"}set event(t){this.setAttribute("event",t)}getTrigger(){return this.querySelectorAll(this.getAttribute("trigger")??"[data-trigger]")}getContent(t=HTMLElement){let e=this.querySelector(this.getAttribute("content")??"[data-content]");if(e instanceof t)return e;throw new Error("Content not found")}swapContent(t=!0,e=800){let r=this.querySelector(this.getAttribute("swap")??"[data-swap]");if(r){let n=Array.from(this.getContent().childNodes);r instanceof HTMLTemplateElement?this.getContent().replaceChildren(r.content.cloneNode(!0)):this.getContent().replaceChildren(...r.childNodes),t&&setTimeout(()=>this.getContent().replaceChildren(...n),e)}}safeListener(t,e,r=document.body,n={}){n.signal=this.#t.signal,r.addEventListener(t,e,n)}triggerListener(t,e=this.event){for(let r of this.getTrigger())r.addEventListener(e,t)}mount(){}connectedCallback(){queueMicrotask(()=>this.mount())}disconnectedCallback(){this.#t.abort()}};var i=class extends s{static observedAttributes=["autoplay","start","uid"];constructor(){super()}get iframe(){return this.getContent(HTMLIFrameElement)}get autoplay(){return this.hasAttribute("autoplay")}set autoplay(t){t?this.setAttribute("autoplay",""):this.removeAttribute("autoplay")}get start(){return this.getAttribute("start")??"0"}set start(t){this.setAttribute("start",t)}get uid(){let t=this.getAttribute("uid");if(!t)throw new Error("YouTube: missing `uid` attribute.");return t}set uid(t){this.setAttribute("uid",t)}mount(){this.iframe.allowFullscreen=!0,this.iframe.allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"}attributeChangedCallback(){queueMicrotask(()=>{this.iframe.src=`https://www.youtube-nocookie.com/embed/${this.uid}?start=${this.start}${this.autoplay?"&autoplay=1":""}`})}};customElements.define("drab-youtube",i);})();
|
@@ -0,0 +1 @@
|
|
1
|
+
import{a as e}from"../chunk-VEVFQB5N.js";import"../chunk-MXKU7AKV.js";customElements.define("drab-youtube",e);
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { Base } from '../base/index.js';
|
2
|
+
|
3
|
+
/**
|
4
|
+
* Embeds a YouTube video iframe into a website with the video uid, using www.youtube-nocookie.com.
|
5
|
+
*/
|
6
|
+
declare class YouTube extends Base {
|
7
|
+
static observedAttributes: readonly ["autoplay", "start", "uid"];
|
8
|
+
constructor();
|
9
|
+
/** The `HTMLIFrameElement` within the element. */
|
10
|
+
get iframe(): HTMLIFrameElement;
|
11
|
+
/** Whether the video should start playing when loaded. */
|
12
|
+
get autoplay(): boolean;
|
13
|
+
set autoplay(value: boolean);
|
14
|
+
/** The start time of the video (seconds). */
|
15
|
+
get start(): string;
|
16
|
+
set start(value: string);
|
17
|
+
/**
|
18
|
+
* The video's YouTube uid, found within the url of the video.
|
19
|
+
*
|
20
|
+
* For example if the video url is https://youtu.be/gouiY85kD2o,
|
21
|
+
* the `uid` is `"gouiY85kD2o"`.
|
22
|
+
*/
|
23
|
+
get uid(): string;
|
24
|
+
set uid(v: string);
|
25
|
+
mount(): void;
|
26
|
+
attributeChangedCallback(): void;
|
27
|
+
}
|
28
|
+
|
29
|
+
export { YouTube };
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";(()=>{var s=class extends HTMLElement{#t=new AbortController;constructor(){super()}get event(){return this.getAttribute("event")??"click"}set event(t){this.setAttribute("event",t)}getTrigger(){return this.querySelectorAll(this.getAttribute("trigger")??"[data-trigger]")}getContent(t=HTMLElement){let e=this.querySelector(this.getAttribute("content")??"[data-content]");if(e instanceof t)return e;throw new Error("Content not found")}swapContent(t=!0,e=800){let n=this.querySelector(this.getAttribute("swap")??"[data-swap]");if(n){let r=Array.from(this.getContent().childNodes);n instanceof HTMLTemplateElement?this.getContent().replaceChildren(n.content.cloneNode(!0)):this.getContent().replaceChildren(...n.childNodes),t&&setTimeout(()=>this.getContent().replaceChildren(...r),e)}}safeListener(t,e,n=document.body,r={}){r.signal=this.#t.signal,n.addEventListener(t,e,r)}triggerListener(t,e=this.event){for(let n of this.getTrigger())n.addEventListener(e,t)}mount(){}connectedCallback(){queueMicrotask(()=>this.mount())}disconnectedCallback(){this.#t.abort()}};var i=class extends s{static observedAttributes=["autoplay","start","uid"];constructor(){super()}get iframe(){return this.getContent(HTMLIFrameElement)}get autoplay(){return this.hasAttribute("autoplay")}set autoplay(t){t?this.setAttribute("autoplay",""):this.removeAttribute("autoplay")}get start(){return this.getAttribute("start")??"0"}set start(t){this.setAttribute("start",t)}get uid(){let t=this.getAttribute("uid");if(!t)throw new Error("YouTube: missing `uid` attribute.");return t}set uid(t){this.setAttribute("uid",t)}mount(){this.iframe.allowFullscreen=!0,this.iframe.allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"}attributeChangedCallback(){queueMicrotask(()=>{this.iframe.src=`https://www.youtube-nocookie.com/embed/${this.uid}?start=${this.start}${this.autoplay?"&autoplay=1":""}`})}};})();
|
package/youtube/index.js
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
import{a}from"../chunk-VEVFQB5N.js";import"../chunk-MXKU7AKV.js";export{a as YouTube};
|
@@ -1,55 +0,0 @@
|
|
1
|
-
<!--
|
2
|
-
@component
|
3
|
-
|
4
|
-
### Breakpoints
|
5
|
-
|
6
|
-
Displays the current breakpoint and `window.innerWidth`, based on the `breakpoints` provided. Defaults to [TailwindCSS breakpoint sizes](https://tailwindcss.com/docs/responsive-design).
|
7
|
-
|
8
|
-
With SvelteKit, this component can be wrapped in an `{#if dev}` block that checks for the [dev module](https://kit.svelte.dev/docs/modules#$app-environment-dev), to show only during development.
|
9
|
-
|
10
|
-
@props
|
11
|
-
|
12
|
-
- `breakpoints` - array of objects representing the breakpoints of the application
|
13
|
-
- `class`
|
14
|
-
- `id`
|
15
|
-
|
16
|
-
@example
|
17
|
-
|
18
|
-
```svelte
|
19
|
-
<script lang="ts">
|
20
|
-
import { Breakpoint } from "drab";
|
21
|
-
</script>
|
22
|
-
|
23
|
-
<Breakpoint
|
24
|
-
class="card inline-block px-3 py-2 font-mono text-sm tabular-nums"
|
25
|
-
/>
|
26
|
-
```
|
27
|
-
-->
|
28
|
-
|
29
|
-
<script>let className = "";
|
30
|
-
export { className as class };
|
31
|
-
export let id = "";
|
32
|
-
export let breakpoints = [
|
33
|
-
{ name: "sm", width: 640 },
|
34
|
-
{ name: "md", width: 768 },
|
35
|
-
{ name: "lg", width: 1024 },
|
36
|
-
{ name: "xl", width: 1280 },
|
37
|
-
{ name: "2xl", width: 1536 }
|
38
|
-
];
|
39
|
-
breakpoints.sort((a, b) => b.width - a.width);
|
40
|
-
let innerWidth = 0;
|
41
|
-
$:
|
42
|
-
breakpoint = getBreakpoint(innerWidth);
|
43
|
-
const getBreakpoint = (innerWidth2) => {
|
44
|
-
for (let i = 0; i < breakpoints.length; i++) {
|
45
|
-
if (innerWidth2 > breakpoints[i].width) {
|
46
|
-
return breakpoints[i].name;
|
47
|
-
}
|
48
|
-
}
|
49
|
-
return "none";
|
50
|
-
};
|
51
|
-
</script>
|
52
|
-
|
53
|
-
<svelte:window bind:innerWidth />
|
54
|
-
|
55
|
-
<div class={className} {id}>{breakpoint}:{innerWidth}</div>
|
@@ -1,46 +0,0 @@
|
|
1
|
-
import { SvelteComponent } from "svelte";
|
2
|
-
declare const __propDef: {
|
3
|
-
props: {
|
4
|
-
class?: string | undefined;
|
5
|
-
id?: string | undefined;
|
6
|
-
/** array of objects representing the breakpoints of the application */ breakpoints?: {
|
7
|
-
name: string;
|
8
|
-
width: number;
|
9
|
-
}[] | undefined;
|
10
|
-
};
|
11
|
-
events: {
|
12
|
-
[evt: string]: CustomEvent<any>;
|
13
|
-
};
|
14
|
-
slots: {};
|
15
|
-
};
|
16
|
-
export type BreakpointProps = typeof __propDef.props;
|
17
|
-
export type BreakpointEvents = typeof __propDef.events;
|
18
|
-
export type BreakpointSlots = typeof __propDef.slots;
|
19
|
-
/**
|
20
|
-
* ### Breakpoints
|
21
|
-
*
|
22
|
-
* Displays the current breakpoint and `window.innerWidth`, based on the `breakpoints` provided. Defaults to [TailwindCSS breakpoint sizes](https://tailwindcss.com/docs/responsive-design).
|
23
|
-
*
|
24
|
-
* With SvelteKit, this component can be wrapped in an `{#if dev}` block that checks for the [dev module](https://kit.svelte.dev/docs/modules#$app-environment-dev), to show only during development.
|
25
|
-
*
|
26
|
-
* @props
|
27
|
-
*
|
28
|
-
* - `breakpoints` - array of objects representing the breakpoints of the application
|
29
|
-
* - `class`
|
30
|
-
* - `id`
|
31
|
-
*
|
32
|
-
* @example
|
33
|
-
*
|
34
|
-
* ```svelte
|
35
|
-
* <script lang="ts">
|
36
|
-
* import { Breakpoint } from "drab";
|
37
|
-
* </script>
|
38
|
-
*
|
39
|
-
* <Breakpoint
|
40
|
-
* class="card inline-block px-3 py-2 font-mono text-sm tabular-nums"
|
41
|
-
* />
|
42
|
-
* ```
|
43
|
-
*/
|
44
|
-
export default class Breakpoint extends SvelteComponent<BreakpointProps, BreakpointEvents, BreakpointSlots> {
|
45
|
-
}
|
46
|
-
export {};
|
@@ -1,150 +0,0 @@
|
|
1
|
-
<!--
|
2
|
-
@component
|
3
|
-
|
4
|
-
### ContextMenu
|
5
|
-
|
6
|
-
Displays when the `target` element is right clicked, or long pressed on mobile.
|
7
|
-
|
8
|
-
@props
|
9
|
-
|
10
|
-
- `class`
|
11
|
-
- `display` - shows / hides the menu
|
12
|
-
- `id`
|
13
|
-
- `target` - target element to right click, defaults to the parent element
|
14
|
-
- `transition` - scales the menu, set to `false` to disable
|
15
|
-
|
16
|
-
@slots
|
17
|
-
|
18
|
-
| name | purpose | default value |
|
19
|
-
| ---------- | ------------------------------- | ------------- |
|
20
|
-
| `default` | default | Context Menu |
|
21
|
-
|
22
|
-
@example
|
23
|
-
|
24
|
-
```svelte
|
25
|
-
<script lang="ts">
|
26
|
-
import { ContextMenu } from "drab";
|
27
|
-
|
28
|
-
let target: HTMLButtonElement;
|
29
|
-
</script>
|
30
|
-
|
31
|
-
<div class="mb-8 flex justify-center rounded border bg-muted p-12">
|
32
|
-
<div>Parent right click</div>
|
33
|
-
<ContextMenu class="z-10">
|
34
|
-
<div class="card flex w-48 flex-col gap-2 p-2 shadow-md">
|
35
|
-
<div class="font-bold">Context Menu</div>
|
36
|
-
<button role="menuitem" class="button button-secondary">Button</button>
|
37
|
-
<button role="menuitem" class="button button-secondary">Button</button>
|
38
|
-
<button role="menuitem" class="button button-secondary">Button</button>
|
39
|
-
</div>
|
40
|
-
</ContextMenu>
|
41
|
-
</div>
|
42
|
-
|
43
|
-
<button type="button" class="button button-primary" bind:this={target}>
|
44
|
-
Target Right Click
|
45
|
-
</button>
|
46
|
-
<ContextMenu {target} class="z-10">
|
47
|
-
<div class="card flex w-48 flex-col gap-2 p-2 shadow-md">
|
48
|
-
<div class="font-bold">Target</div>
|
49
|
-
<button role="menuitem" class="button button-secondary">Button</button>
|
50
|
-
<button role="menuitem" class="button button-secondary">Button</button>
|
51
|
-
<button role="menuitem" class="button button-secondary">Button</button>
|
52
|
-
</div>
|
53
|
-
</ContextMenu>
|
54
|
-
```
|
55
|
-
-->
|
56
|
-
|
57
|
-
<script>import { onMount, tick } from "svelte";
|
58
|
-
import { scale } from "svelte/transition";
|
59
|
-
import { duration, start } from "../util/transition";
|
60
|
-
import { prefersReducedMotion } from "../util/accessibility";
|
61
|
-
import { delay } from "../util/delay";
|
62
|
-
let className = "";
|
63
|
-
export { className as class };
|
64
|
-
export let id = "";
|
65
|
-
export let display = false;
|
66
|
-
export let transition = { duration, start };
|
67
|
-
export let target = null;
|
68
|
-
let contextMenu;
|
69
|
-
let base;
|
70
|
-
let coordinates = { x: 0, y: 0 };
|
71
|
-
const hide = () => display = false;
|
72
|
-
const onKeyDown = (e) => {
|
73
|
-
if (e.key === "Escape") {
|
74
|
-
display = false;
|
75
|
-
}
|
76
|
-
};
|
77
|
-
const displayMenu = async (e) => {
|
78
|
-
e.preventDefault();
|
79
|
-
const scrollY = window.scrollY;
|
80
|
-
const scrollX = window.scrollX;
|
81
|
-
const clientX = e instanceof MouseEvent ? e.clientX : e.touches[0].clientX;
|
82
|
-
const clientY = e instanceof MouseEvent ? e.clientY : e.touches[0].clientY;
|
83
|
-
coordinates.x = clientX + scrollX;
|
84
|
-
coordinates.y = clientY + scrollY;
|
85
|
-
display = true;
|
86
|
-
await tick();
|
87
|
-
const offsetWidth = contextMenu.offsetWidth + 24;
|
88
|
-
const offsetHeight = contextMenu.offsetHeight + 6;
|
89
|
-
const innerWidth = window.innerWidth;
|
90
|
-
const innerHeight = window.innerHeight;
|
91
|
-
if (coordinates.x + offsetWidth > scrollX + innerWidth) {
|
92
|
-
coordinates.x = scrollX + innerWidth - offsetWidth;
|
93
|
-
}
|
94
|
-
if (coordinates.y + offsetHeight > scrollY + innerHeight) {
|
95
|
-
coordinates.y = scrollY + innerHeight - offsetHeight;
|
96
|
-
}
|
97
|
-
};
|
98
|
-
let timer;
|
99
|
-
const onTouchStart = (e) => {
|
100
|
-
timer = setTimeout(() => {
|
101
|
-
displayMenu(e);
|
102
|
-
}, delay);
|
103
|
-
};
|
104
|
-
const onTouchEnd = () => {
|
105
|
-
clearTimeout(timer);
|
106
|
-
};
|
107
|
-
onMount(async () => {
|
108
|
-
if (prefersReducedMotion())
|
109
|
-
transition = false;
|
110
|
-
await tick();
|
111
|
-
if (!target) {
|
112
|
-
target = base.parentElement;
|
113
|
-
}
|
114
|
-
if (target) {
|
115
|
-
target.addEventListener("contextmenu", displayMenu);
|
116
|
-
target.addEventListener("touchstart", onTouchStart);
|
117
|
-
target.addEventListener("touchend", onTouchEnd);
|
118
|
-
target.addEventListener("touchcancel", onTouchEnd);
|
119
|
-
}
|
120
|
-
});
|
121
|
-
</script>
|
122
|
-
|
123
|
-
<svelte:body on:click={hide} on:keydown={onKeyDown} />
|
124
|
-
|
125
|
-
<span bind:this={base} role="presentation"></span>
|
126
|
-
|
127
|
-
{#if display}
|
128
|
-
<div
|
129
|
-
role="menu"
|
130
|
-
class={className}
|
131
|
-
{id}
|
132
|
-
bind:this={contextMenu}
|
133
|
-
style:top="{coordinates.y}px"
|
134
|
-
style:left="{coordinates.x}px"
|
135
|
-
transition:scale={transition ? transition : { duration: 0 }}
|
136
|
-
>
|
137
|
-
<slot>Context Menu</slot>
|
138
|
-
</div>
|
139
|
-
{/if}
|
140
|
-
|
141
|
-
<style>
|
142
|
-
span {
|
143
|
-
opacity: 0;
|
144
|
-
width: 0;
|
145
|
-
height: 0;
|
146
|
-
}
|
147
|
-
div {
|
148
|
-
position: absolute;
|
149
|
-
}
|
150
|
-
</style>
|
@@ -1,76 +0,0 @@
|
|
1
|
-
import { SvelteComponent } from "svelte";
|
2
|
-
import { type ScaleParams } from "svelte/transition";
|
3
|
-
declare const __propDef: {
|
4
|
-
props: {
|
5
|
-
class?: string | undefined;
|
6
|
-
id?: string | undefined;
|
7
|
-
/** shows / hides the menu */ display?: boolean | undefined;
|
8
|
-
/** scales the menu, set to `false` to disable */ transition?: false | ScaleParams | undefined;
|
9
|
-
/** target element to right click, defaults to the parent element */ target?: HTMLElement | null | undefined;
|
10
|
-
};
|
11
|
-
events: {
|
12
|
-
[evt: string]: CustomEvent<any>;
|
13
|
-
};
|
14
|
-
slots: {
|
15
|
-
default: {};
|
16
|
-
};
|
17
|
-
};
|
18
|
-
export type ContextMenuProps = typeof __propDef.props;
|
19
|
-
export type ContextMenuEvents = typeof __propDef.events;
|
20
|
-
export type ContextMenuSlots = typeof __propDef.slots;
|
21
|
-
/**
|
22
|
-
* ### ContextMenu
|
23
|
-
*
|
24
|
-
* Displays when the `target` element is right clicked, or long pressed on mobile.
|
25
|
-
*
|
26
|
-
* @props
|
27
|
-
*
|
28
|
-
* - `class`
|
29
|
-
* - `display` - shows / hides the menu
|
30
|
-
* - `id`
|
31
|
-
* - `target` - target element to right click, defaults to the parent element
|
32
|
-
* - `transition` - scales the menu, set to `false` to disable
|
33
|
-
*
|
34
|
-
* @slots
|
35
|
-
*
|
36
|
-
* | name | purpose | default value |
|
37
|
-
* | ---------- | ------------------------------- | ------------- |
|
38
|
-
* | `default` | default | Context Menu |
|
39
|
-
*
|
40
|
-
* @example
|
41
|
-
*
|
42
|
-
* ```svelte
|
43
|
-
* <script lang="ts">
|
44
|
-
* import { ContextMenu } from "drab";
|
45
|
-
*
|
46
|
-
* let target: HTMLButtonElement;
|
47
|
-
* </script>
|
48
|
-
*
|
49
|
-
* <div class="mb-8 flex justify-center rounded border bg-muted p-12">
|
50
|
-
* <div>Parent right click</div>
|
51
|
-
* <ContextMenu class="z-10">
|
52
|
-
* <div class="card flex w-48 flex-col gap-2 p-2 shadow-md">
|
53
|
-
* <div class="font-bold">Context Menu</div>
|
54
|
-
* <button role="menuitem" class="button button-secondary">Button</button>
|
55
|
-
* <button role="menuitem" class="button button-secondary">Button</button>
|
56
|
-
* <button role="menuitem" class="button button-secondary">Button</button>
|
57
|
-
* </div>
|
58
|
-
* </ContextMenu>
|
59
|
-
* </div>
|
60
|
-
*
|
61
|
-
* <button type="button" class="button button-primary" bind:this={target}>
|
62
|
-
* Target Right Click
|
63
|
-
* </button>
|
64
|
-
* <ContextMenu {target} class="z-10">
|
65
|
-
* <div class="card flex w-48 flex-col gap-2 p-2 shadow-md">
|
66
|
-
* <div class="font-bold">Target</div>
|
67
|
-
* <button role="menuitem" class="button button-secondary">Button</button>
|
68
|
-
* <button role="menuitem" class="button button-secondary">Button</button>
|
69
|
-
* <button role="menuitem" class="button button-secondary">Button</button>
|
70
|
-
* </div>
|
71
|
-
* </ContextMenu>
|
72
|
-
* ```
|
73
|
-
*/
|
74
|
-
export default class ContextMenu extends SvelteComponent<ContextMenuProps, ContextMenuEvents, ContextMenuSlots> {
|
75
|
-
}
|
76
|
-
export {};
|
@@ -1,97 +0,0 @@
|
|
1
|
-
<!--
|
2
|
-
@component
|
3
|
-
|
4
|
-
### CopyButton
|
5
|
-
|
6
|
-
Uses the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard) to copy data to the clipboard. Falls back to `writeText` if `write` is not supported and `blob.type` is text.
|
7
|
-
|
8
|
-
@props
|
9
|
-
|
10
|
-
- `blobParts` - array of `BlobParts` to copy - [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#parameters)
|
11
|
-
- `blob` - use a blob in instead of `blobParts` and `options`, defaults to `new Blob(blobParts, options)`
|
12
|
-
- `class`
|
13
|
-
- `id`
|
14
|
-
- `options` - defaults to `{ type: "text/plain" }` - [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#parameters)
|
15
|
-
- `title`
|
16
|
-
|
17
|
-
@slots
|
18
|
-
|
19
|
-
| name | purpose | default value |
|
20
|
-
| ---------- | ------------------------------- | ------------- |
|
21
|
-
| `default` | default | `Copy` |
|
22
|
-
| `complete` | displays after copy is complete | `Copied` |
|
23
|
-
|
24
|
-
@example
|
25
|
-
|
26
|
-
```svelte
|
27
|
-
<script lang="ts">
|
28
|
-
import { CopyButton } from "drab";
|
29
|
-
|
30
|
-
let value = "";
|
31
|
-
</script>
|
32
|
-
|
33
|
-
<label for="copyInput" class="label">Text to Copy</label>
|
34
|
-
<input id="copyInput" class="input mb-4" type="text" bind:value />
|
35
|
-
|
36
|
-
<CopyButton class="button button-primary" blobParts={[value]} />
|
37
|
-
```
|
38
|
-
-->
|
39
|
-
|
40
|
-
<script>import { onMount } from "svelte";
|
41
|
-
import { delay } from "../util/delay";
|
42
|
-
let className = "";
|
43
|
-
export { className as class };
|
44
|
-
export let id = "";
|
45
|
-
export let title = "";
|
46
|
-
export let options = { type: "text/plain" };
|
47
|
-
export let blobParts = void 0;
|
48
|
-
export let blob = new Blob(blobParts, options);
|
49
|
-
let disabled = true;
|
50
|
-
let complete = false;
|
51
|
-
let blobText;
|
52
|
-
const setBlobText = async (blob2) => blobText = await blob2.text();
|
53
|
-
const writeSupport = () => "write" in navigator.clipboard;
|
54
|
-
const canWriteText = () => {
|
55
|
-
const writeTextSupport = "writeText" in navigator.clipboard;
|
56
|
-
const typeText = blob.type.startsWith("text");
|
57
|
-
return writeTextSupport && typeText;
|
58
|
-
};
|
59
|
-
const copyText = async () => {
|
60
|
-
try {
|
61
|
-
if (writeSupport()) {
|
62
|
-
const data = [new ClipboardItem({ [blob.type]: blob })];
|
63
|
-
await navigator.clipboard.write(data);
|
64
|
-
} else if (canWriteText()) {
|
65
|
-
await navigator.clipboard.writeText(blobText);
|
66
|
-
}
|
67
|
-
complete = true;
|
68
|
-
setTimeout(() => complete = false, delay);
|
69
|
-
} catch (error) {
|
70
|
-
console.error(error);
|
71
|
-
}
|
72
|
-
};
|
73
|
-
onMount(async () => {
|
74
|
-
if (writeSupport() || canWriteText())
|
75
|
-
disabled = false;
|
76
|
-
});
|
77
|
-
$:
|
78
|
-
if (blobParts)
|
79
|
-
blob = new Blob(blobParts, options);
|
80
|
-
$:
|
81
|
-
setBlobText(blob);
|
82
|
-
</script>
|
83
|
-
|
84
|
-
<button
|
85
|
-
type="button"
|
86
|
-
{disabled}
|
87
|
-
on:click={copyText}
|
88
|
-
class={className}
|
89
|
-
{id}
|
90
|
-
{title}
|
91
|
-
>
|
92
|
-
{#if complete}
|
93
|
-
<slot name="complete">Copied</slot>
|
94
|
-
{:else}
|
95
|
-
<slot>Copy</slot>
|
96
|
-
{/if}
|
97
|
-
</button>
|