drab 3.0.1 → 3.0.2

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/README.md CHANGED
@@ -1,125 +1,125 @@
1
- # An Unstyled Svelte Component Library
2
-
3
- - [Docs](https://drab.robino.dev)
4
- - [GitHub](https://github.com/rossrobino/drab)
5
- - [npm](https://www.npmjs.com/package/drab)
6
- - [MIT License](https://github.com/rossrobino/drab/blob/main/LICENSE.md)
7
-
8
- ## About
9
-
10
- **drab** focuses on providing JavaScript functionality where it's most useful. Many of the components are helpful wrappers around browser APIs. Whenever possible, components are [progressively enhanced](https://drab.robino.dev/docs/ShareButton) or provide a fallback [noscript](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript) message. Additionally, transitions are disabled for users who prefer reduced motion.
11
-
12
- This library takes a more opinionated approach compared to some headless UI libraries by providing the basic HTML structure for every component, as well as default positioning for elements like the [sheet](https://drab.robino.dev/docs/Sheet). However, these components can still be further customized using styles, [slots](https://svelte.dev/tutorial/slots), and [slot props](https://svelte.dev/tutorial/slot-props).
13
-
14
- ## Install
15
-
16
- If you haven't used Svelte before, start with the [tutorial](https://svelte.dev/tutorial/basics). **drab** works anywhere Svelte does.
17
-
18
- - [SvelteKit](https://kit.svelte.dev)
19
- - [Astro](https://docs.astro.build/en/tutorial/1-setup/2/)
20
- - [Vite](https://vitejs.dev/guide/)
21
-
22
- ```bash
23
- npm install -D drab
24
- ```
25
-
26
- ## Documentation
27
-
28
- The library provides inline documentation for each component, allowing you to conveniently access the documentation by hovering over the component in your text editor after importing it. Additionally, every prop is documented using JSDoc and TypeScript. By hovering over a prop, you can retrieve its type and description.
29
-
30
- These docs use the [TailwindCSS Typography plugin](https://tailwindcss.com/docs/typography-plugin) for base styles along with a few custom utility classes you can find [here](https://github.com/rossrobino/drab/blob/main/src/app.postcss). Styles on this site are based on [shadcn/ui](https://ui.shadcn.com/).
31
-
32
- ## Other UI Libraries
33
-
34
- **drab** is a collection of useful components, not a complete UI kit. If **drab** isn't what you are looking for, here are some other libraries to check out.
35
-
36
- - [Skeleton](https://skeleton.dev)
37
- - [Melt UI](https://www.melt-ui.com/)
38
- - [shadcn-svelte](https://www.shadcn-svelte.com/)
39
- - [Svelte-HeadlessUI](https://captaincodeman.github.io/svelte-headlessui/)
40
-
41
- ## Styling
42
-
43
- Components without styles can appear rather drab. You have the freedom to bring your own styles to these components. Using unstyled components allows you to selectively choose what you need and avoid being tied to any specific library.
44
-
45
- To style the markup provided by the components, you can make use of [global styles](https://joyofcode.xyz/global-styles-in-sveltekit). Each component exports `class` and `id` props that can be leveraged for this purpose. This process can be expedited by utilizing CSS frameworks like [TailwindCSS](https://tailwindcss.com/). Tailwind generates a global stylesheet based on the utility classes used in your project. The examples in this documentation are styled with Tailwind classes, but Tailwind does not have to be used with this library.
46
-
47
- ### Stylesheet
48
-
49
- Here's a SvelteKit example using CSS imported in a layout. By using a layout, these styles can be accessed anywhere.
50
-
51
- ```css
52
- /* src/app.css */
53
- .btn {
54
- color: white;
55
- background-color: black;
56
- border-radius: 5px;
57
- padding: 5px;
58
- }
59
- ```
60
-
61
- ```svelte
62
- <!-- src/routes/+layout.svelte -->
63
- <script>
64
- import "../app.css";
65
- </script>
66
-
67
- <slot />
68
- ```
69
-
70
- ```svelte
71
- <!-- src/routes/+page.svelte -->
72
- <script>
73
- import { FullscreenButton } from "drab";
74
- </script>
75
-
76
- <FullscreenButton class="btn" />
77
- ```
78
-
79
- ### Global modifier
80
-
81
- Alternatively, the [`:global()` modifier](https://svelte.dev/docs/svelte-components#style) can be used instead of a separate stylesheet.
82
-
83
- ```svelte
84
- <!-- src/routes/+page.svelte -->
85
- <script>
86
- import { FullscreenButton } from "drab";
87
- </script>
88
-
89
- <FullscreenButton class="btn" />
90
-
91
- <style>
92
- :global(.btn) {
93
- color: white;
94
- background-color: black;
95
- border-radius: 5px;
96
- padding: 5px;
97
- }
98
- </style>
99
- ```
100
-
101
- ## Contributing
102
-
103
- Find an bug or have an idea? Feel free to create an issue on [GitHub](https://github.com/rossrobino/drab). **drab** is meant to house all kinds of components including ones outside of the standard UI elements.
104
-
105
- Currently, **drab** has only one dependency - Svelte. Not to say it will never have another, but please consider this when proposing additional functionality. **drab** is meant to make the most of what Svelte and the web platform provide.
106
-
107
- Since this is an unstyled library, simple components like a badge that can be easily created with HTML and CSS are not included.
108
-
109
- ### Local Development
110
-
111
- Contribute to the project, or use **drab** as a template for another component library. This library is built with SvelteKit, TypeScript, and npm. The package contents are located in `src/lib`, the site is contained within `src/routes` and `src/site`. The site is deployed to Vercel using `@sveltejs/adapter-vercel`. If you are using this project as a template, be sure to [update the adapter](https://kit.svelte.dev/docs/adapters) based on how you deploy.
112
-
113
- #### Make changes
114
-
115
- 1. Clone the [repository](https://github.com/rossrobino/drab)
116
- 2. `npm install`
117
- 3. `npm run dev -- --open`
118
-
119
- #### Add or edit a component
120
-
121
- 1. Add or edit the component in `src/lib/components/Component.svelte` - if you're adding a new one, copy and paste an existing one to get started with the conventions
122
- 2. Add or edit the example in `src/routes/docs/Component/+page.svelte`
123
- 3. Document the component with an `@component` comment, include a description, and the `@slots` available. Add a placeholder `@props` and `@example` to the comment. These sections will be generated based on the JSDoc comment above each prop and the example route upon running `npm run doc`
124
- 4. If new, add the link to `src/site/components/NavItems.svelte`
125
- 5. Run `npm run build` to verify your build
1
+ # An Unstyled Svelte Component Library
2
+
3
+ - [Docs](https://drab.robino.dev)
4
+ - [GitHub](https://github.com/rossrobino/drab)
5
+ - [npm](https://www.npmjs.com/package/drab)
6
+ - [MIT License](https://github.com/rossrobino/drab/blob/main/LICENSE.md)
7
+
8
+ ## About
9
+
10
+ **drab** focuses on providing JavaScript functionality where it's most useful. Many of the components are helpful wrappers around browser APIs. Whenever possible, components are [progressively enhanced](https://drab.robino.dev/docs/ShareButton) or provide a fallback [noscript](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/noscript) message. Additionally, transitions are disabled for users who prefer reduced motion.
11
+
12
+ This library takes a more opinionated approach compared to some headless UI libraries by providing the basic HTML structure for every component, as well as default positioning for elements like the [sheet](https://drab.robino.dev/docs/Sheet). However, these components can still be further customized using styles, [slots](https://svelte.dev/tutorial/slots), and [slot props](https://svelte.dev/tutorial/slot-props).
13
+
14
+ ## Install
15
+
16
+ If you haven't used Svelte before, start with the [tutorial](https://svelte.dev/tutorial/basics). **drab** works anywhere Svelte does.
17
+
18
+ - [SvelteKit](https://kit.svelte.dev)
19
+ - [Astro](https://docs.astro.build/en/tutorial/1-setup/2/)
20
+ - [Vite](https://vitejs.dev/guide/)
21
+
22
+ ```bash
23
+ npm install -D drab
24
+ ```
25
+
26
+ ## Documentation
27
+
28
+ The library provides inline documentation for each component, allowing you to conveniently access the documentation by hovering over the component in your text editor after importing it. Additionally, every prop is documented using JSDoc and TypeScript. By hovering over a prop, you can retrieve its type and description.
29
+
30
+ These docs use the [TailwindCSS Typography plugin](https://tailwindcss.com/docs/typography-plugin) for base styles along with a few custom utility classes you can find [here](https://github.com/rossrobino/drab/blob/main/src/app.postcss). Styles on this site are based on [shadcn/ui](https://ui.shadcn.com/).
31
+
32
+ ## Other UI Libraries
33
+
34
+ **drab** is a collection of useful components, not a complete UI kit. If **drab** isn't what you are looking for, here are some other libraries to check out.
35
+
36
+ - [Skeleton](https://skeleton.dev)
37
+ - [Melt UI](https://www.melt-ui.com/)
38
+ - [shadcn-svelte](https://www.shadcn-svelte.com/)
39
+ - [Svelte-HeadlessUI](https://captaincodeman.github.io/svelte-headlessui/)
40
+
41
+ ## Styling
42
+
43
+ Components without styles can appear rather drab. You have the freedom to bring your own styles to these components. Using unstyled components allows you to selectively choose what you need and avoid being tied to any specific library.
44
+
45
+ To style the markup provided by the components, you can make use of [global styles](https://joyofcode.xyz/global-styles-in-sveltekit). Each component exports `class` and `id` props that can be leveraged for this purpose. This process can be expedited by utilizing CSS frameworks like [TailwindCSS](https://tailwindcss.com/). Tailwind generates a global stylesheet based on the utility classes used in your project. The examples in this documentation are styled with Tailwind classes, but Tailwind does not have to be used with this library.
46
+
47
+ ### Stylesheet
48
+
49
+ Here's a SvelteKit example using CSS imported in a layout. By using a layout, these styles can be accessed anywhere.
50
+
51
+ ```css
52
+ /* src/app.css */
53
+ .btn {
54
+ color: white;
55
+ background-color: black;
56
+ border-radius: 5px;
57
+ padding: 5px;
58
+ }
59
+ ```
60
+
61
+ ```svelte
62
+ <!-- src/routes/+layout.svelte -->
63
+ <script>
64
+ import "../app.css";
65
+ </script>
66
+
67
+ <slot />
68
+ ```
69
+
70
+ ```svelte
71
+ <!-- src/routes/+page.svelte -->
72
+ <script>
73
+ import { FullscreenButton } from "drab";
74
+ </script>
75
+
76
+ <FullscreenButton class="btn" />
77
+ ```
78
+
79
+ ### Global modifier
80
+
81
+ Alternatively, the [`:global()` modifier](https://svelte.dev/docs/svelte-components#style) can be used instead of a separate stylesheet.
82
+
83
+ ```svelte
84
+ <!-- src/routes/+page.svelte -->
85
+ <script>
86
+ import { FullscreenButton } from "drab";
87
+ </script>
88
+
89
+ <FullscreenButton class="btn" />
90
+
91
+ <style>
92
+ :global(.btn) {
93
+ color: white;
94
+ background-color: black;
95
+ border-radius: 5px;
96
+ padding: 5px;
97
+ }
98
+ </style>
99
+ ```
100
+
101
+ ## Contributing
102
+
103
+ Find an bug or have an idea? Feel free to create an issue on [GitHub](https://github.com/rossrobino/drab). **drab** is meant to house all kinds of components including ones outside of the standard UI elements.
104
+
105
+ Currently, **drab** has only one dependency - Svelte. Not to say it will never have another, but please consider this when proposing additional functionality. **drab** is meant to make the most of what Svelte and the web platform provide.
106
+
107
+ Since this is an unstyled library, simple components like a badge that can be easily created with HTML and CSS are not included.
108
+
109
+ ### Local Development
110
+
111
+ Contribute to the project, or use **drab** as a template for another component library. This library is built with SvelteKit, TypeScript, and npm. The package contents are located in `src/lib`, the site is contained within `src/routes` and `src/site`. The site is deployed to Vercel using `@sveltejs/adapter-vercel`. If you are using this project as a template, be sure to [update the adapter](https://kit.svelte.dev/docs/adapters) based on how you deploy.
112
+
113
+ #### Make changes
114
+
115
+ 1. Clone the [repository](https://github.com/rossrobino/drab)
116
+ 2. `npm install`
117
+ 3. `npm run dev -- --open`
118
+
119
+ #### Add or edit a component
120
+
121
+ 1. Add or edit the component in `src/lib/components/Component.svelte` - if you're adding a new one, copy and paste an existing one to get started with the conventions
122
+ 2. Add or edit the example in `src/routes/docs/Component/+page.svelte`
123
+ 3. Document the component with an `@component` comment, include a description, and the `@slots` available. Add a placeholder `@props` and `@example` to the comment. These sections will be generated based on the JSDoc comment above each prop and the example route upon running `npm run doc`
124
+ 4. If new, add the link to `src/site/components/NavItems.svelte`
125
+ 5. Run `npm run build` to verify your build
@@ -1,31 +1,31 @@
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="inline-block rounded border bg-white px-2 py-1 font-mono tabular-nums shadow"
25
- />
26
- ```
27
- -->
28
-
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="inline-block rounded border bg-white px-2 py-1 font-mono tabular-nums shadow"
25
+ />
26
+ ```
27
+ -->
28
+
29
29
  <script>let className = "";
30
30
  export { className as class };
31
31
  export let id = "";
@@ -48,8 +48,8 @@ const getBreakpoint = (innerWidth2) => {
48
48
  }
49
49
  return "none";
50
50
  };
51
- </script>
52
-
53
- <svelte:window bind:innerWidth />
54
-
55
- <div class={className} {id}>{breakpoint}:{innerWidth}</div>
51
+ </script>
52
+
53
+ <svelte:window bind:innerWidth />
54
+
55
+ <div class={className} {id}>{breakpoint}:{innerWidth}</div>
@@ -1,57 +1,57 @@
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 border-dashed p-12">
32
- <div>Parent right click</div>
33
- <ContextMenu>
34
- <div class="flex w-48 flex-col gap-2 rounded border bg-white p-2 shadow">
35
- <div class="font-bold">Context Menu</div>
36
- <button role="menuitem" class="btn">Button</button>
37
- <button role="menuitem" class="btn">Button</button>
38
- <button role="menuitem" class="btn">Button</button>
39
- </div>
40
- </ContextMenu>
41
- </div>
42
-
43
- <button type="button" class="btn" bind:this={target}>Target Right Click</button>
44
- <ContextMenu {target}>
45
- <div class="flex w-48 flex-col gap-2 rounded border bg-white p-2 shadow">
46
- <div class="font-bold">Target</div>
47
- <button role="menuitem" class="btn">Button</button>
48
- <button role="menuitem" class="btn">Button</button>
49
- <button role="menuitem" class="btn">Button</button>
50
- </div>
51
- </ContextMenu>
52
- ```
53
- -->
54
-
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 border-dashed p-12">
32
+ <div>Parent right click</div>
33
+ <ContextMenu>
34
+ <div class="flex w-48 flex-col gap-2 rounded border bg-white p-2 shadow">
35
+ <div class="font-bold">Context Menu</div>
36
+ <button role="menuitem" class="btn">Button</button>
37
+ <button role="menuitem" class="btn">Button</button>
38
+ <button role="menuitem" class="btn">Button</button>
39
+ </div>
40
+ </ContextMenu>
41
+ </div>
42
+
43
+ <button type="button" class="btn" bind:this={target}>Target Right Click</button>
44
+ <ContextMenu {target}>
45
+ <div class="flex w-48 flex-col gap-2 rounded border bg-white p-2 shadow">
46
+ <div class="font-bold">Target</div>
47
+ <button role="menuitem" class="btn">Button</button>
48
+ <button role="menuitem" class="btn">Button</button>
49
+ <button role="menuitem" class="btn">Button</button>
50
+ </div>
51
+ </ContextMenu>
52
+ ```
53
+ -->
54
+
55
55
  <script>import { onMount, tick } from "svelte";
56
56
  import { scale } from "svelte/transition";
57
57
  import { duration, start } from "../util/transition";
@@ -116,33 +116,33 @@ onMount(async () => {
116
116
  target.addEventListener("touchcancel", onTouchEnd);
117
117
  }
118
118
  });
119
- </script>
120
-
121
- <svelte:body on:click={hide} on:keydown={onKeyDown} />
122
-
123
- <span bind:this={base} role="presentation"></span>
124
-
125
- {#if display}
126
- <div
127
- role="menu"
128
- class={className}
129
- {id}
130
- bind:this={contextMenu}
131
- style:top="{coordinates.y}px"
132
- style:left="{coordinates.x}px"
133
- transition:scale={transition ? transition : { duration: 0 }}
134
- >
135
- <slot>Context Menu</slot>
136
- </div>
137
- {/if}
138
-
139
- <style>
140
- span {
141
- width: 0;
142
- height: 0;
143
- opacity: 0;
144
- }
145
- div {
146
- position: absolute;
147
- }
148
- </style>
119
+ </script>
120
+
121
+ <svelte:body on:click={hide} on:keydown={onKeyDown} />
122
+
123
+ <span bind:this={base} role="presentation"></span>
124
+
125
+ {#if display}
126
+ <div
127
+ role="menu"
128
+ class={className}
129
+ {id}
130
+ bind:this={contextMenu}
131
+ style:top="{coordinates.y}px"
132
+ style:left="{coordinates.x}px"
133
+ transition:scale={transition ? transition : { duration: 0 }}
134
+ >
135
+ <slot>Context Menu</slot>
136
+ </div>
137
+ {/if}
138
+
139
+ <style>
140
+ span {
141
+ width: 0;
142
+ height: 0;
143
+ opacity: 0;
144
+ }
145
+ div {
146
+ position: absolute;
147
+ }
148
+ </style>
@@ -1,38 +1,41 @@
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. If JavaScript is disabled, the button is disabled and `blobParts.join()` is displayed after the button if `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
- - `classNoscript` - `noscript` class
13
- - `class`
14
- - `id`
15
- - `options` - defaults to `{ type: "text/plain" }` - [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob#parameters)
16
- - `title`
17
-
18
- @slots
19
-
20
- | name | purpose | default value |
21
- | ---------- | ------------------------------- | ------------- |
22
- | `default` | default | `Copy` |
23
- | `complete` | displays after copy is complete | `Copied` |
24
-
25
- @example
26
-
27
- ```svelte
28
- <script lang="ts">
29
- import { CopyButton } from "drab";
30
- </script>
31
-
32
- <CopyButton class="btn" blobParts={["Text to copy"]} />
33
- ```
34
- -->
35
-
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 = "Text to copy";
31
+ </script>
32
+
33
+ <input class="input mb-4" type="text" bind:value />
34
+
35
+ <CopyButton class="btn" blobParts={[value]} />
36
+ ```
37
+ -->
38
+
36
39
  <script>import { onMount } from "svelte";
37
40
  import { delay } from "../util/delay";
38
41
  let className = "";
@@ -42,13 +45,14 @@ export let title = "";
42
45
  export let options = { type: "text/plain" };
43
46
  export let blobParts = void 0;
44
47
  export let blob = new Blob(blobParts, options);
45
- export let classNoscript = "";
46
48
  let disabled = true;
47
49
  let complete = false;
50
+ let blobText;
51
+ const setBlobText = async (blob2) => blobText = await blob2.text();
48
52
  const writeSupport = () => "write" in navigator.clipboard;
49
- const typeText = blob.type.startsWith("text");
50
53
  const canWriteText = () => {
51
54
  const writeTextSupport = "writeText" in navigator.clipboard;
55
+ const typeText = blob.type.startsWith("text");
52
56
  return writeTextSupport && typeText;
53
57
  };
54
58
  const copyText = async () => {
@@ -57,7 +61,7 @@ const copyText = async () => {
57
61
  const data = [new ClipboardItem({ [blob.type]: blob })];
58
62
  await navigator.clipboard.write(data);
59
63
  } else if (canWriteText()) {
60
- await navigator.clipboard.writeText(blobParts ? blobParts.join() : "");
64
+ await navigator.clipboard.writeText(blobText);
61
65
  }
62
66
  complete = true;
63
67
  setTimeout(() => complete = false, delay);
@@ -65,29 +69,28 @@ const copyText = async () => {
65
69
  console.error(error);
66
70
  }
67
71
  };
68
- onMount(() => {
72
+ onMount(async () => {
69
73
  if (writeSupport() || canWriteText())
70
74
  disabled = false;
71
75
  });
72
- </script>
73
-
74
- <button
75
- type="button"
76
- {disabled}
77
- on:click={copyText}
78
- class={className}
79
- {id}
80
- {title}
81
- >
82
- {#if complete}
83
- <slot name="complete">Copied</slot>
84
- {:else}
85
- <slot>Copy</slot>
86
- {/if}
87
- </button>
88
-
89
- {#if typeText}
90
- <noscript>
91
- <span class={classNoscript}>{blobParts ? blobParts.join() : ""}</span>
92
- </noscript>
93
- {/if}
76
+ $:
77
+ if (blobParts)
78
+ blob = new Blob(blobParts, options);
79
+ $:
80
+ setBlobText(blob);
81
+ </script>
82
+
83
+ <button
84
+ type="button"
85
+ {disabled}
86
+ on:click={copyText}
87
+ class={className}
88
+ {id}
89
+ {title}
90
+ >
91
+ {#if complete}
92
+ <slot name="complete">Copied</slot>
93
+ {:else}
94
+ <slot>Copy</slot>
95
+ {/if}
96
+ </button>