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 +125 -125
- package/dist/components/Breakpoint.svelte +33 -33
- package/dist/components/ContextMenu.svelte +84 -84
- package/dist/components/CopyButton.svelte +64 -61
- package/dist/components/CopyButton.svelte.d.ts +6 -4
- package/dist/components/DataTable.svelte +143 -143
- package/dist/components/Details.svelte +85 -85
- package/dist/components/Editor.svelte +98 -98
- package/dist/components/FrettedChord.svelte +154 -154
- package/dist/components/FullscreenButton.svelte +60 -60
- package/dist/components/Popover.svelte +77 -77
- package/dist/components/ShareButton.svelte +85 -85
- package/dist/components/Sheet.svelte +120 -120
- package/dist/components/YouTube.svelte +33 -33
- package/package.json +81 -81
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.
|
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
|
-
- `
|
13
|
-
- `
|
14
|
-
- `
|
15
|
-
- `
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
|
21
|
-
|
|
22
|
-
| `
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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(
|
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
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
{
|
83
|
-
|
84
|
-
{
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
{
|
90
|
-
|
91
|
-
|
92
|
-
|
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>
|