drab 1.10.1 → 2.1.0
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/dist/components/Chord.svelte +2 -0
- package/dist/components/Chord.svelte.d.ts +9 -8
- package/dist/components/ContextMenu.svelte +30 -14
- package/dist/components/ContextMenu.svelte.d.ts +2 -0
- package/dist/components/CopyButton.svelte +9 -2
- package/dist/components/CopyButton.svelte.d.ts +2 -0
- package/dist/components/DataTable.svelte +55 -43
- package/dist/components/DataTable.svelte.d.ts +30 -28
- package/dist/components/Editor.svelte +57 -44
- package/dist/components/Editor.svelte.d.ts +19 -17
- package/dist/components/FullscreenButton.svelte +18 -7
- package/dist/components/FullscreenButton.svelte.d.ts +4 -2
- package/dist/components/Popover.svelte +155 -0
- package/dist/components/Popover.svelte.d.ts +69 -0
- package/dist/components/ShareButton.svelte +10 -3
- package/dist/components/ShareButton.svelte.d.ts +4 -2
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/util/messages.d.ts +1 -0
- package/dist/util/messages.js +1 -0
- package/package.json +6 -4
@@ -1,4 +1,12 @@
|
|
1
1
|
import { SvelteComponent } from "svelte";
|
2
|
+
export interface ChordNote {
|
3
|
+
/** recommended finger to use */
|
4
|
+
finger: number | string;
|
5
|
+
/** string number */
|
6
|
+
string: number;
|
7
|
+
/** fret number */
|
8
|
+
fret: number;
|
9
|
+
}
|
2
10
|
declare const __propDef: {
|
3
11
|
props: {
|
4
12
|
class?: string | undefined;
|
@@ -6,14 +14,7 @@ declare const __propDef: {
|
|
6
14
|
/** total number of strings for the instrument */ strings?: number | undefined;
|
7
15
|
/** name of chord */ name?: string | undefined;
|
8
16
|
/** total size of chord square */ size?: number | undefined;
|
9
|
-
/** list of the positioning of the notes required for the chord */ notes?:
|
10
|
-
/** recommended finger to use */
|
11
|
-
finger: number | string;
|
12
|
-
/** string number */
|
13
|
-
string: number;
|
14
|
-
/** fret number */
|
15
|
-
fret: number;
|
16
|
-
}[] | undefined;
|
17
|
+
/** list of the positioning of the notes required for the chord */ notes?: ChordNote[] | undefined;
|
17
18
|
};
|
18
19
|
events: {
|
19
20
|
[evt: string]: CustomEvent<any>;
|
@@ -7,6 +7,7 @@ Displays when the parent element is right clicked.
|
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
10
|
+
- `classNoscript` - noscript class
|
10
11
|
- `class`
|
11
12
|
- `display` - controls `display` css property
|
12
13
|
- `id`
|
@@ -43,29 +44,36 @@ let className = "";
|
|
43
44
|
export { className as class };
|
44
45
|
export let id = "";
|
45
46
|
export let display = false;
|
47
|
+
export let classNoscript = "";
|
46
48
|
let contextMenu;
|
47
|
-
let
|
49
|
+
let coordinates = { x: 0, y: 0 };
|
48
50
|
const hide = () => display = false;
|
51
|
+
const onKeyDown = (e) => {
|
52
|
+
if (e.key === "Escape") {
|
53
|
+
display = false;
|
54
|
+
}
|
55
|
+
};
|
49
56
|
onMount(() => {
|
50
|
-
const
|
51
|
-
if (
|
52
|
-
|
57
|
+
const parentElement = contextMenu.parentElement;
|
58
|
+
if (parentElement) {
|
59
|
+
parentElement.addEventListener("contextmenu", async (e) => {
|
53
60
|
if (contextMenu) {
|
54
61
|
e.preventDefault();
|
55
62
|
const scrollY = window.scrollY;
|
56
|
-
|
57
|
-
|
63
|
+
const scrollX = window.scrollX;
|
64
|
+
coordinates.x = e.clientX + scrollX;
|
65
|
+
coordinates.y = e.clientY + scrollY;
|
58
66
|
display = true;
|
59
67
|
await tick();
|
60
68
|
const offsetWidth = contextMenu.offsetWidth + 24;
|
61
69
|
const offsetHeight = contextMenu.offsetHeight + 6;
|
62
70
|
const innerWidth = window.innerWidth;
|
63
71
|
const innerHeight = window.innerHeight;
|
64
|
-
if (
|
65
|
-
|
72
|
+
if (coordinates.x + offsetWidth > scrollX + innerWidth) {
|
73
|
+
coordinates.x = scrollX + innerWidth - offsetWidth;
|
66
74
|
}
|
67
|
-
if (
|
68
|
-
|
75
|
+
if (coordinates.y + offsetHeight > scrollY + innerHeight) {
|
76
|
+
coordinates.y = scrollY + innerHeight - offsetHeight;
|
69
77
|
}
|
70
78
|
}
|
71
79
|
});
|
@@ -73,21 +81,29 @@ onMount(() => {
|
|
73
81
|
});
|
74
82
|
</script>
|
75
83
|
|
76
|
-
<svelte:document on:click={hide} />
|
84
|
+
<svelte:document on:click={hide} on:keydown={onKeyDown} />
|
77
85
|
|
78
86
|
<div
|
79
87
|
class={className}
|
80
88
|
{id}
|
81
89
|
bind:this={contextMenu}
|
82
|
-
style="
|
83
|
-
|
84
|
-
|
90
|
+
style:z-index={display ? "10" : "-10"}
|
91
|
+
style:opacity={display ? "100%" : "0%"}
|
92
|
+
style:top="{coordinates.y}px"
|
93
|
+
style:left="{coordinates.x}px"
|
85
94
|
>
|
86
95
|
<slot>Context Menu</slot>
|
87
96
|
</div>
|
88
97
|
|
98
|
+
<noscript>
|
99
|
+
<div class={classNoscript}>
|
100
|
+
<slot />
|
101
|
+
</div>
|
102
|
+
</noscript>
|
103
|
+
|
89
104
|
<style>
|
90
105
|
div {
|
91
106
|
position: absolute;
|
107
|
+
z-index: 1;
|
92
108
|
}
|
93
109
|
</style>
|
@@ -4,6 +4,7 @@ declare const __propDef: {
|
|
4
4
|
class?: string | undefined;
|
5
5
|
id?: string | undefined;
|
6
6
|
/** controls `display` css property */ display?: boolean | undefined;
|
7
|
+
/** noscript class */ classNoscript?: string | undefined;
|
7
8
|
};
|
8
9
|
events: {
|
9
10
|
[evt: string]: CustomEvent<any>;
|
@@ -22,6 +23,7 @@ export type ContextMenuSlots = typeof __propDef.slots;
|
|
22
23
|
*
|
23
24
|
* @props
|
24
25
|
*
|
26
|
+
* - `classNoscript` - noscript class
|
25
27
|
* - `class`
|
26
28
|
* - `display` - controls `display` css property
|
27
29
|
* - `id`
|
@@ -7,6 +7,7 @@ Uses the navigator api to copy text to the clipboard.
|
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
10
|
+
- `classNoscript` - noscript class
|
10
11
|
- `class`
|
11
12
|
- `id`
|
12
13
|
- `text` - text to copy
|
@@ -30,11 +31,14 @@ Uses the navigator api to copy text to the clipboard.
|
|
30
31
|
```
|
31
32
|
-->
|
32
33
|
|
33
|
-
<script>
|
34
|
+
<script>import { onMount } from "svelte";
|
35
|
+
let className = "";
|
34
36
|
export { className as class };
|
35
37
|
export let id = "";
|
36
38
|
export let title = "Copy";
|
37
39
|
export let text;
|
40
|
+
export let classNoscript = "";
|
41
|
+
let clientJs = false;
|
38
42
|
let complete = false;
|
39
43
|
const copyText = async () => {
|
40
44
|
try {
|
@@ -45,12 +49,15 @@ const copyText = async () => {
|
|
45
49
|
console.error(error);
|
46
50
|
}
|
47
51
|
};
|
52
|
+
onMount(() => clientJs = true);
|
48
53
|
</script>
|
49
54
|
|
50
|
-
<button on:click={copyText} class={className} {id} {title}>
|
55
|
+
<button disabled={!clientJs} on:click={copyText} class={className} {id} {title}>
|
51
56
|
{#if complete}
|
52
57
|
<slot name="complete">Copied</slot>
|
53
58
|
{:else}
|
54
59
|
<slot>Copy</slot>
|
55
60
|
{/if}
|
56
61
|
</button>
|
62
|
+
|
63
|
+
<noscript><span class={classNoscript}>{text}</span></noscript>
|
@@ -5,6 +5,7 @@ declare const __propDef: {
|
|
5
5
|
id?: string | undefined;
|
6
6
|
title?: string | undefined;
|
7
7
|
/** text to copy */ text: string;
|
8
|
+
/** noscript class */ classNoscript?: string | undefined;
|
8
9
|
};
|
9
10
|
events: {
|
10
11
|
[evt: string]: CustomEvent<any>;
|
@@ -24,6 +25,7 @@ export type CopyButtonSlots = typeof __propDef.slots;
|
|
24
25
|
*
|
25
26
|
* @props
|
26
27
|
*
|
28
|
+
* - `classNoscript` - noscript class
|
27
29
|
* - `class`
|
28
30
|
* - `id`
|
29
31
|
* - `text` - text to copy
|
@@ -8,25 +8,26 @@ Data table to display an array of JS objects. Click a column header to sort.
|
|
8
8
|
@props
|
9
9
|
|
10
10
|
- `ascending` - default sort order
|
11
|
-
- `
|
11
|
+
- `classButton` - button class
|
12
|
+
- `classFooter` - footer class
|
13
|
+
- `classNoscript` - noscript class
|
14
|
+
- `classPageControls` - class of `div` that wraps the "Previous" and "Next" buttons
|
15
|
+
- `classPageNumber` - class of `div` wrapping page numbers
|
16
|
+
- `classTable` - table class
|
17
|
+
- `classTbodyTr` - tbody tr class
|
18
|
+
- `classTbody` - tbody class
|
19
|
+
- `classTdSorted` - currently sorted td
|
20
|
+
- `classTd` - td class
|
21
|
+
- `classThSorted` - currently sorted th
|
22
|
+
- `classTh` - th class
|
23
|
+
- `classTheadTr` - thead tr class
|
24
|
+
- `classThead` - thead class
|
12
25
|
- `columns` - table columns, in order
|
13
26
|
- `currentPage` - current page, defaults to `1`
|
14
27
|
- `data` - a list of objects to render in the table
|
15
|
-
- `
|
16
|
-
- `pageControlsClass` - class of `div` that wraps the "Previous" and "Next" buttons
|
17
|
-
- `pageNumberClass` - class of `div` wrapping page numbers
|
28
|
+
- `idTable` - table id
|
18
29
|
- `paginate` - number of rows to show on each page, defaults to `0` - no pagination
|
19
30
|
- `sortBy` - column to sort by--defaults to first column
|
20
|
-
- `sortedTdClass` - currently sorted td
|
21
|
-
- `sortedThClass` - currently sorted th
|
22
|
-
- `tBodyClass` - tbody class
|
23
|
-
- `tBodyTrClass` - tbody tr class
|
24
|
-
- `tHeadClass` - thead class
|
25
|
-
- `tHeadTrClass` - thead tr class
|
26
|
-
- `tableClass` - table class
|
27
|
-
- `tableId` - table id
|
28
|
-
- `tdClass` - td class
|
29
|
-
- `thClass` - th class
|
30
31
|
|
31
32
|
@slots
|
32
33
|
|
@@ -57,29 +58,33 @@ Data table to display an array of JS objects. Click a column header to sort.
|
|
57
58
|
|
58
59
|
<script context="module"></script>
|
59
60
|
|
60
|
-
<script>
|
61
|
+
<script>import { messageNoScript } from "../util/messages";
|
62
|
+
import { onMount } from "svelte";
|
63
|
+
export let data;
|
61
64
|
export let columns = [];
|
62
65
|
if (!columns.length && data[0]) {
|
63
66
|
columns = Object.keys(data[0]);
|
64
67
|
}
|
65
68
|
export let sortBy = columns[0];
|
66
69
|
export let ascending = true;
|
67
|
-
export let
|
68
|
-
export let
|
69
|
-
export let
|
70
|
-
export let
|
71
|
-
export let
|
72
|
-
export let
|
73
|
-
export let
|
74
|
-
export let
|
75
|
-
export let
|
76
|
-
export let
|
77
|
-
export let
|
78
|
-
export let
|
79
|
-
export let
|
80
|
-
export let
|
70
|
+
export let classTable = "";
|
71
|
+
export let idTable = "";
|
72
|
+
export let classThead = "";
|
73
|
+
export let classTbody = "";
|
74
|
+
export let classTheadTr = "";
|
75
|
+
export let classTbodyTr = "";
|
76
|
+
export let classTh = "";
|
77
|
+
export let classTd = "";
|
78
|
+
export let classThSorted = "";
|
79
|
+
export let classTdSorted = "";
|
80
|
+
export let classButton = "";
|
81
|
+
export let classFooter = "";
|
82
|
+
export let classPageNumber = "";
|
83
|
+
export let classPageControls = "";
|
81
84
|
export let paginate = 0;
|
82
85
|
export let currentPage = 1;
|
86
|
+
export let classNoscript = "";
|
87
|
+
let clientJs = false;
|
83
88
|
$:
|
84
89
|
numberOfPages = Math.floor(data.length / paginate) + 1;
|
85
90
|
const sort = (column, toggleAscending = true) => {
|
@@ -117,14 +122,15 @@ const sort = (column, toggleAscending = true) => {
|
|
117
122
|
sortBy = column;
|
118
123
|
};
|
119
124
|
sort(sortBy, false);
|
125
|
+
onMount(() => clientJs = true);
|
120
126
|
</script>
|
121
127
|
|
122
|
-
<table class={
|
123
|
-
<thead class={
|
124
|
-
<tr class={
|
128
|
+
<table class={classTable} id={idTable}>
|
129
|
+
<thead class={classThead}>
|
130
|
+
<tr class={classTheadTr}>
|
125
131
|
{#each columns as column}
|
126
132
|
<th
|
127
|
-
class="{
|
133
|
+
class="{classTh} {sortBy === column ? classThSorted : ''}"
|
128
134
|
on:click={() => sort(column)}
|
129
135
|
>
|
130
136
|
{column}
|
@@ -132,14 +138,14 @@ sort(sortBy, false);
|
|
132
138
|
{/each}
|
133
139
|
</tr>
|
134
140
|
</thead>
|
135
|
-
<tbody class={
|
141
|
+
<tbody class={classTbody}>
|
136
142
|
{#each data as row, i}
|
137
143
|
{@const showRow =
|
138
144
|
i < paginate * currentPage && i >= paginate * (currentPage - 1)}
|
139
145
|
{#if paginate ? showRow : true}
|
140
|
-
<tr class={
|
146
|
+
<tr class={classTbodyTr}>
|
141
147
|
{#each columns as column}
|
142
|
-
<td class="{
|
148
|
+
<td class="{classTd} {sortBy === column ? classTdSorted : ''}">
|
143
149
|
{row[column]}
|
144
150
|
</td>
|
145
151
|
{/each}
|
@@ -150,23 +156,29 @@ sort(sortBy, false);
|
|
150
156
|
</table>
|
151
157
|
|
152
158
|
{#if paginate}
|
153
|
-
<div class={
|
154
|
-
<div class={
|
155
|
-
<div class={
|
159
|
+
<div class={classFooter}>
|
160
|
+
<div class={classPageNumber}>{currentPage} / {numberOfPages}</div>
|
161
|
+
<div class={classPageControls}>
|
156
162
|
<button
|
157
|
-
class={
|
158
|
-
disabled={currentPage < 2}
|
163
|
+
class={classButton}
|
164
|
+
disabled={!clientJs || currentPage < 2}
|
159
165
|
on:click={() => currentPage--}
|
160
166
|
>
|
161
167
|
<slot name="previous">Previous</slot>
|
162
168
|
</button>
|
163
169
|
<button
|
164
|
-
class={
|
165
|
-
disabled={currentPage >= numberOfPages}
|
170
|
+
class={classButton}
|
171
|
+
disabled={!clientJs || currentPage >= numberOfPages}
|
166
172
|
on:click={() => currentPage++}
|
167
173
|
>
|
168
174
|
<slot name="next">Next</slot>
|
169
175
|
</button>
|
170
176
|
</div>
|
171
177
|
</div>
|
178
|
+
|
179
|
+
<noscript>
|
180
|
+
<div class={classNoscript}>
|
181
|
+
{messageNoScript}
|
182
|
+
</div>
|
183
|
+
</noscript>
|
172
184
|
{/if}
|
@@ -8,22 +8,23 @@ declare const __propDef: {
|
|
8
8
|
/** table columns, in order */ columns?: string[] | undefined;
|
9
9
|
/** column to sort by--defaults to first column */ sortBy?: string | undefined;
|
10
10
|
/** default sort order */ ascending?: boolean | undefined;
|
11
|
-
/** table class */
|
12
|
-
/** table id */
|
13
|
-
/** thead class */
|
14
|
-
/** tbody class */
|
15
|
-
/** thead tr class */
|
16
|
-
/** tbody tr class */
|
17
|
-
/** th class */
|
18
|
-
/** td class */
|
19
|
-
/** currently sorted th */
|
20
|
-
/** currently sorted td */
|
21
|
-
/** button class */
|
22
|
-
/** footer class */
|
23
|
-
/** class of `div` wrapping page numbers */
|
24
|
-
/** class of `div` that wraps the "Previous" and "Next" buttons */
|
11
|
+
/** table class */ classTable?: string | undefined;
|
12
|
+
/** table id */ idTable?: string | undefined;
|
13
|
+
/** thead class */ classThead?: string | undefined;
|
14
|
+
/** tbody class */ classTbody?: string | undefined;
|
15
|
+
/** thead tr class */ classTheadTr?: string | undefined;
|
16
|
+
/** tbody tr class */ classTbodyTr?: string | undefined;
|
17
|
+
/** th class */ classTh?: string | undefined;
|
18
|
+
/** td class */ classTd?: string | undefined;
|
19
|
+
/** currently sorted th */ classThSorted?: string | undefined;
|
20
|
+
/** currently sorted td */ classTdSorted?: string | undefined;
|
21
|
+
/** button class */ classButton?: string | undefined;
|
22
|
+
/** footer class */ classFooter?: string | undefined;
|
23
|
+
/** class of `div` wrapping page numbers */ classPageNumber?: string | undefined;
|
24
|
+
/** class of `div` that wraps the "Previous" and "Next" buttons */ classPageControls?: string | undefined;
|
25
25
|
/** number of rows to show on each page, defaults to `0` - no pagination */ paginate?: number | undefined;
|
26
26
|
/** current page, defaults to `1` */ currentPage?: number | undefined;
|
27
|
+
/** noscript class */ classNoscript?: string | undefined;
|
27
28
|
};
|
28
29
|
events: {
|
29
30
|
[evt: string]: CustomEvent<any>;
|
@@ -44,25 +45,26 @@ export type DataTableSlots = typeof __propDef.slots;
|
|
44
45
|
* @props
|
45
46
|
*
|
46
47
|
* - `ascending` - default sort order
|
47
|
-
* - `
|
48
|
+
* - `classButton` - button class
|
49
|
+
* - `classFooter` - footer class
|
50
|
+
* - `classNoscript` - noscript class
|
51
|
+
* - `classPageControls` - class of `div` that wraps the "Previous" and "Next" buttons
|
52
|
+
* - `classPageNumber` - class of `div` wrapping page numbers
|
53
|
+
* - `classTable` - table class
|
54
|
+
* - `classTbodyTr` - tbody tr class
|
55
|
+
* - `classTbody` - tbody class
|
56
|
+
* - `classTdSorted` - currently sorted td
|
57
|
+
* - `classTd` - td class
|
58
|
+
* - `classThSorted` - currently sorted th
|
59
|
+
* - `classTh` - th class
|
60
|
+
* - `classTheadTr` - thead tr class
|
61
|
+
* - `classThead` - thead class
|
48
62
|
* - `columns` - table columns, in order
|
49
63
|
* - `currentPage` - current page, defaults to `1`
|
50
64
|
* - `data` - a list of objects to render in the table
|
51
|
-
* - `
|
52
|
-
* - `pageControlsClass` - class of `div` that wraps the "Previous" and "Next" buttons
|
53
|
-
* - `pageNumberClass` - class of `div` wrapping page numbers
|
65
|
+
* - `idTable` - table id
|
54
66
|
* - `paginate` - number of rows to show on each page, defaults to `0` - no pagination
|
55
67
|
* - `sortBy` - column to sort by--defaults to first column
|
56
|
-
* - `sortedTdClass` - currently sorted td
|
57
|
-
* - `sortedThClass` - currently sorted th
|
58
|
-
* - `tBodyClass` - tbody class
|
59
|
-
* - `tBodyTrClass` - tbody tr class
|
60
|
-
* - `tHeadClass` - thead class
|
61
|
-
* - `tHeadTrClass` - thead tr class
|
62
|
-
* - `tableClass` - table class
|
63
|
-
* - `tableId` - table id
|
64
|
-
* - `tdClass` - td class
|
65
|
-
* - `thClass` - th class
|
66
68
|
*
|
67
69
|
* @slots
|
68
70
|
*
|
@@ -7,17 +7,18 @@ Text editor with controls to add elements and keyboard shortcuts.
|
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
10
|
-
- `
|
10
|
+
- `classButton` - `class` of all the `button` elements
|
11
|
+
- `classControls` - `class` of the `div` that wraps the controls
|
12
|
+
- `classNoscript` - noscript class
|
13
|
+
- `classTextarea` - `class` of the `textarea` element
|
11
14
|
- `contentElements` - an array of content elements for the controls
|
12
|
-
- `
|
13
|
-
- `
|
15
|
+
- `idControls` - `id` of the `div` that wraps the controls
|
16
|
+
- `idTextarea` - `id` of the `textarea` element
|
14
17
|
- `keyPairs` - keys that will auto-close if typed, value is their closing character
|
18
|
+
- `nameTextarea` - `name` of the `textarea` element
|
19
|
+
- `placeholderTextarea` - `placeholder` of the `textarea` element
|
15
20
|
- `selectionStart` - `selectionStart` value of the text area
|
16
|
-
- `
|
17
|
-
- `textAreaId` - `id` of the `textarea` element
|
18
|
-
- `textAreaName` - `name` of the `textarea` element
|
19
|
-
- `textAreaPlaceholder` - `placeholder` of the `textarea` element
|
20
|
-
- `textAreaValue` - `value` of the `textarea` element
|
21
|
+
- `valueTextarea` - `value` of the `textarea` element
|
21
22
|
|
22
23
|
@example
|
23
24
|
|
@@ -55,15 +56,17 @@ Text editor with controls to add elements and keyboard shortcuts.
|
|
55
56
|
|
56
57
|
<script context="module"></script>
|
57
58
|
|
58
|
-
<script>
|
59
|
-
|
60
|
-
export let
|
61
|
-
export let
|
62
|
-
export let
|
63
|
-
export let
|
64
|
-
export let
|
65
|
-
export let
|
66
|
-
export let
|
59
|
+
<script>import { onMount } from "svelte";
|
60
|
+
import { messageNoScript } from "../util/messages";
|
61
|
+
export let contentElements = [];
|
62
|
+
export let valueTextarea = "";
|
63
|
+
export let placeholderTextarea = "";
|
64
|
+
export let classTextarea = "";
|
65
|
+
export let idTextarea = "";
|
66
|
+
export let nameTextarea = "";
|
67
|
+
export let classButton = "";
|
68
|
+
export let classControls = "";
|
69
|
+
export let idControls = "";
|
67
70
|
export let selectionStart = 0;
|
68
71
|
export let keyPairs = {
|
69
72
|
"(": ")",
|
@@ -73,6 +76,8 @@ export let keyPairs = {
|
|
73
76
|
'"': '"',
|
74
77
|
"`": "`"
|
75
78
|
};
|
79
|
+
export let classNoscript = "";
|
80
|
+
let clientJs = false;
|
76
81
|
let textArea;
|
77
82
|
contentElements.forEach((el) => {
|
78
83
|
if (el.display === "wrap")
|
@@ -87,11 +92,11 @@ const removeChar = (str, index) => {
|
|
87
92
|
};
|
88
93
|
const insertText = async (el, selectionStart2, selectionEnd) => {
|
89
94
|
if (el.display === "inline") {
|
90
|
-
|
95
|
+
valueTextarea = `${valueTextarea.slice(0, selectionEnd)}${el.text}${valueTextarea.slice(selectionEnd)}`;
|
91
96
|
} else if (el.display === "wrap") {
|
92
|
-
|
93
|
-
|
94
|
-
|
97
|
+
valueTextarea = insertChar(valueTextarea, el.text, selectionStart2);
|
98
|
+
valueTextarea = insertChar(
|
99
|
+
valueTextarea,
|
95
100
|
keyPairs[el.text],
|
96
101
|
selectionEnd + el.text.length
|
97
102
|
);
|
@@ -104,15 +109,15 @@ const insertText = async (el, selectionStart2, selectionEnd) => {
|
|
104
109
|
} else {
|
105
110
|
lines[lineNumber] = el.text + lines[lineNumber];
|
106
111
|
}
|
107
|
-
|
112
|
+
valueTextarea = lines.join("\n");
|
108
113
|
}
|
109
114
|
};
|
110
115
|
const setCaretPosition = async (text, selectionStart2, selectionEnd) => {
|
111
116
|
let startPos = 0;
|
112
117
|
let endPos = 0;
|
113
118
|
if (/[a-z]/i.test(text)) {
|
114
|
-
for (let i = selectionEnd; i <
|
115
|
-
if (
|
119
|
+
for (let i = selectionEnd; i < valueTextarea.length; i++) {
|
120
|
+
if (valueTextarea[i].match(/[a-z]/i)) {
|
116
121
|
if (!startPos) {
|
117
122
|
startPos = i;
|
118
123
|
} else {
|
@@ -137,17 +142,17 @@ const addContent = async (el) => {
|
|
137
142
|
};
|
138
143
|
const onKeyDown = async (e) => {
|
139
144
|
const resetKeys = ["ArrowUp", "ArrowDown", "Delete"];
|
140
|
-
const nextChar =
|
145
|
+
const nextChar = valueTextarea[textArea.selectionEnd];
|
141
146
|
if (resetKeys.includes(e.key)) {
|
142
147
|
openChars = [];
|
143
148
|
} else if (e.key === "Backspace") {
|
144
|
-
const prevChar =
|
149
|
+
const prevChar = valueTextarea[textArea.selectionStart - 1];
|
145
150
|
if (prevChar in keyPairs && nextChar === keyPairs[prevChar]) {
|
146
151
|
e.preventDefault();
|
147
152
|
const start = textArea.selectionStart - 1;
|
148
153
|
const end = textArea.selectionEnd - 1;
|
149
|
-
|
150
|
-
|
154
|
+
valueTextarea = removeChar(valueTextarea, start);
|
155
|
+
valueTextarea = removeChar(valueTextarea, end);
|
151
156
|
setTimeout(() => {
|
152
157
|
textArea.setSelectionRange(start, end);
|
153
158
|
}, 0);
|
@@ -158,7 +163,7 @@ const onKeyDown = async (e) => {
|
|
158
163
|
const newPos = textArea.selectionStart - 1;
|
159
164
|
const { lineNumber } = getLineInfo();
|
160
165
|
correctFollowing(lineNumber, true);
|
161
|
-
|
166
|
+
valueTextarea = removeChar(valueTextarea, newPos);
|
162
167
|
setTimeout(async () => {
|
163
168
|
textArea.setSelectionRange(newPos, newPos);
|
164
169
|
}, 0);
|
@@ -197,8 +202,8 @@ ${repeat}`,
|
|
197
202
|
const selectionEnd = textArea.selectionEnd;
|
198
203
|
const newPos = selectionEnd - original.length;
|
199
204
|
for (let i = 0; i < original.length; i++) {
|
200
|
-
|
201
|
-
|
205
|
+
valueTextarea = removeChar(
|
206
|
+
valueTextarea,
|
202
207
|
textArea.selectionEnd - (i + 1)
|
203
208
|
);
|
204
209
|
}
|
@@ -242,13 +247,13 @@ ${repeat}`,
|
|
242
247
|
};
|
243
248
|
const trimSelection = () => {
|
244
249
|
if (textArea.selectionStart !== textArea.selectionEnd) {
|
245
|
-
if (
|
250
|
+
if (valueTextarea[textArea.selectionStart] === " ") {
|
246
251
|
textArea.setSelectionRange(
|
247
252
|
textArea.selectionStart + 1,
|
248
253
|
textArea.selectionEnd
|
249
254
|
);
|
250
255
|
}
|
251
|
-
if (
|
256
|
+
if (valueTextarea[textArea.selectionEnd - 1] === " ") {
|
252
257
|
textArea.setSelectionRange(
|
253
258
|
textArea.selectionStart,
|
254
259
|
textArea.selectionEnd - 1
|
@@ -260,7 +265,7 @@ const updateSelectionStart = () => {
|
|
260
265
|
selectionStart = textArea.selectionStart;
|
261
266
|
};
|
262
267
|
const getLineInfo = () => {
|
263
|
-
const lines =
|
268
|
+
const lines = valueTextarea.split("\n");
|
264
269
|
let characterCount = 0;
|
265
270
|
for (let i = 0; i < lines.length; i++) {
|
266
271
|
characterCount++;
|
@@ -276,7 +281,7 @@ const getLineInfo = () => {
|
|
276
281
|
return { lines, lineNumber: 0, columnNumber: 0 };
|
277
282
|
};
|
278
283
|
const getCurrentBlock = () => {
|
279
|
-
const blocks =
|
284
|
+
const blocks = valueTextarea.split("```");
|
280
285
|
let totalChars = 0;
|
281
286
|
for (const [i, block] of blocks.entries()) {
|
282
287
|
totalChars += block.length + 3;
|
@@ -328,19 +333,20 @@ const correctFollowing = (currentLineNumber, decrement = false) => {
|
|
328
333
|
lines[i] = String(newNum) + lines[i];
|
329
334
|
}
|
330
335
|
}
|
331
|
-
|
336
|
+
valueTextarea = lines.join("\n");
|
332
337
|
};
|
338
|
+
onMount(() => clientJs = true);
|
333
339
|
</script>
|
334
340
|
|
335
341
|
<textarea
|
336
|
-
id={
|
337
|
-
class={
|
338
|
-
name={
|
339
|
-
placeholder={
|
342
|
+
id={idTextarea}
|
343
|
+
class={classTextarea}
|
344
|
+
name={nameTextarea}
|
345
|
+
placeholder={placeholderTextarea}
|
340
346
|
on:keydown={onKeyDown}
|
341
347
|
on:keyup={updateSelectionStart}
|
342
348
|
on:dblclick={trimSelection}
|
343
|
-
bind:value={
|
349
|
+
bind:value={valueTextarea}
|
344
350
|
bind:this={textArea}
|
345
351
|
on:click={() => {
|
346
352
|
openChars = [];
|
@@ -348,13 +354,14 @@ const correctFollowing = (currentLineNumber, decrement = false) => {
|
|
348
354
|
}}
|
349
355
|
on:input
|
350
356
|
/>
|
351
|
-
|
357
|
+
|
358
|
+
<div id={idControls} class={classControls}>
|
352
359
|
{#each contentElements as el}
|
353
360
|
<button
|
354
|
-
class={el.class ? `${
|
361
|
+
class={el.class ? `${classButton} ${el.class}` : classButton}
|
355
362
|
on:click={() => addContent(el)}
|
356
363
|
title={el.name}
|
357
|
-
|
364
|
+
disabled={!clientJs}
|
358
365
|
>
|
359
366
|
{#if typeof el.icon !== "string"}
|
360
367
|
<svelte:component this={el.icon} />
|
@@ -364,3 +371,9 @@ const correctFollowing = (currentLineNumber, decrement = false) => {
|
|
364
371
|
</button>
|
365
372
|
{/each}
|
366
373
|
</div>
|
374
|
+
|
375
|
+
<noscript>
|
376
|
+
<div class={classNoscript}>
|
377
|
+
{messageNoScript}
|
378
|
+
</div>
|
379
|
+
</noscript>
|
@@ -18,22 +18,23 @@ export interface EditorContentElement {
|
|
18
18
|
/** class to apply to the specific button */
|
19
19
|
class?: string;
|
20
20
|
}
|
21
|
-
import type
|
21
|
+
import { type ComponentType } from "svelte";
|
22
22
|
declare const __propDef: {
|
23
23
|
props: {
|
24
24
|
/** an array of content elements for the controls */ contentElements?: EditorContentElement[] | undefined;
|
25
|
-
/** `value` of the `textarea` element */
|
26
|
-
/** `placeholder` of the `textarea` element */
|
27
|
-
/** `class` of the `textarea` element */
|
28
|
-
/** `id` of the `textarea` element */
|
29
|
-
/** `name` of the `textarea` element */
|
30
|
-
/** `class` of all the `button` elements */
|
31
|
-
/** `class` of the `div` that wraps the controls */
|
32
|
-
/** `id` of the `div` that wraps the controls */
|
25
|
+
/** `value` of the `textarea` element */ valueTextarea?: string | undefined;
|
26
|
+
/** `placeholder` of the `textarea` element */ placeholderTextarea?: string | undefined;
|
27
|
+
/** `class` of the `textarea` element */ classTextarea?: string | undefined;
|
28
|
+
/** `id` of the `textarea` element */ idTextarea?: string | undefined;
|
29
|
+
/** `name` of the `textarea` element */ nameTextarea?: string | undefined;
|
30
|
+
/** `class` of all the `button` elements */ classButton?: string | undefined;
|
31
|
+
/** `class` of the `div` that wraps the controls */ classControls?: string | undefined;
|
32
|
+
/** `id` of the `div` that wraps the controls */ idControls?: string | undefined;
|
33
33
|
/** `selectionStart` value of the text area */ selectionStart?: number | undefined;
|
34
34
|
/** keys that will auto-close if typed, value is their closing character */ keyPairs?: {
|
35
35
|
[key: string]: string;
|
36
36
|
} | undefined;
|
37
|
+
/** noscript class */ classNoscript?: string | undefined;
|
37
38
|
};
|
38
39
|
events: {
|
39
40
|
input: Event;
|
@@ -52,17 +53,18 @@ export type EditorSlots = typeof __propDef.slots;
|
|
52
53
|
*
|
53
54
|
* @props
|
54
55
|
*
|
55
|
-
* - `
|
56
|
+
* - `classButton` - `class` of all the `button` elements
|
57
|
+
* - `classControls` - `class` of the `div` that wraps the controls
|
58
|
+
* - `classNoscript` - noscript class
|
59
|
+
* - `classTextarea` - `class` of the `textarea` element
|
56
60
|
* - `contentElements` - an array of content elements for the controls
|
57
|
-
* - `
|
58
|
-
* - `
|
61
|
+
* - `idControls` - `id` of the `div` that wraps the controls
|
62
|
+
* - `idTextarea` - `id` of the `textarea` element
|
59
63
|
* - `keyPairs` - keys that will auto-close if typed, value is their closing character
|
64
|
+
* - `nameTextarea` - `name` of the `textarea` element
|
65
|
+
* - `placeholderTextarea` - `placeholder` of the `textarea` element
|
60
66
|
* - `selectionStart` - `selectionStart` value of the text area
|
61
|
-
* - `
|
62
|
-
* - `textAreaId` - `id` of the `textarea` element
|
63
|
-
* - `textAreaName` - `name` of the `textarea` element
|
64
|
-
* - `textAreaPlaceholder` - `placeholder` of the `textarea` element
|
65
|
-
* - `textAreaValue` - `value` of the `textarea` element
|
67
|
+
* - `valueTextarea` - `value` of the `textarea` element
|
66
68
|
*
|
67
69
|
* @example
|
68
70
|
*
|
@@ -7,6 +7,7 @@ Make the document or a specific element fullscreen.
|
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
10
|
+
- `classNoscript` - noscript class
|
10
11
|
- `class`
|
11
12
|
- `confirmMessage` - message to display in the `confirm` popup, set this to empty string `""` to disable `confirm`
|
12
13
|
- `id`
|
@@ -17,8 +18,8 @@ Make the document or a specific element fullscreen.
|
|
17
18
|
|
18
19
|
| name | purpose | default value |
|
19
20
|
| ---------- | ---------------------------------------------- | -------------------- |
|
21
|
+
| `default` | content to display when fullscreen is disabled | `Enabled Fullscreen` |
|
20
22
|
| `enabled` | content to display when fullscreen is enabled | `Exit Fullscreen` |
|
21
|
-
| `disabled` | content to display when fullscreen is disabled | `Enabled Fullscreen` |
|
22
23
|
|
23
24
|
@example
|
24
25
|
|
@@ -42,17 +43,16 @@ Make the document or a specific element fullscreen.
|
|
42
43
|
-->
|
43
44
|
|
44
45
|
<script>import { onMount } from "svelte";
|
46
|
+
import { messageNoScript } from "../util/messages";
|
45
47
|
let className = "";
|
46
48
|
export { className as class };
|
47
49
|
export let id = "";
|
48
50
|
export let title = "Fullscreen";
|
49
51
|
export let targetElement = null;
|
50
52
|
export let confirmMessage = "";
|
53
|
+
export let classNoscript = "";
|
54
|
+
let clientJs = false;
|
51
55
|
let fullscreen = false;
|
52
|
-
onMount(() => {
|
53
|
-
if (!targetElement)
|
54
|
-
targetElement = document.documentElement;
|
55
|
-
});
|
56
56
|
const onClick = () => {
|
57
57
|
if (fullscreen) {
|
58
58
|
document.exitFullscreen();
|
@@ -68,14 +68,25 @@ const onClick = () => {
|
|
68
68
|
}
|
69
69
|
}
|
70
70
|
};
|
71
|
+
onMount(() => {
|
72
|
+
clientJs = true;
|
73
|
+
if (!targetElement)
|
74
|
+
targetElement = document.documentElement;
|
75
|
+
});
|
71
76
|
</script>
|
72
77
|
|
73
78
|
<svelte:window on:fullscreenchange={() => (fullscreen = !fullscreen)} />
|
74
79
|
|
75
|
-
<button on:click={onClick} class={className} {id} {title}>
|
80
|
+
<button disabled={!clientJs} on:click={onClick} class={className} {id} {title}>
|
76
81
|
{#if fullscreen}
|
77
82
|
<slot name="enabled">Exit Fullscreen</slot>
|
78
83
|
{:else}
|
79
|
-
<slot
|
84
|
+
<slot>Enable Fullscreen</slot>
|
80
85
|
{/if}
|
81
86
|
</button>
|
87
|
+
|
88
|
+
<noscript>
|
89
|
+
<div class={classNoscript}>
|
90
|
+
{messageNoScript}
|
91
|
+
</div>
|
92
|
+
</noscript>
|
@@ -6,13 +6,14 @@ declare const __propDef: {
|
|
6
6
|
title?: string | undefined;
|
7
7
|
/** element to make fullscreen (defaults to `document.documentElement` upon mount) */ targetElement?: HTMLElement | null | undefined;
|
8
8
|
/** message to display in the `confirm` popup, set this to empty string `""` to disable `confirm` */ confirmMessage?: string | undefined;
|
9
|
+
/** noscript class */ classNoscript?: string | undefined;
|
9
10
|
};
|
10
11
|
events: {
|
11
12
|
[evt: string]: CustomEvent<any>;
|
12
13
|
};
|
13
14
|
slots: {
|
14
15
|
enabled: {};
|
15
|
-
|
16
|
+
default: {};
|
16
17
|
};
|
17
18
|
};
|
18
19
|
export type FullscreenButtonProps = typeof __propDef.props;
|
@@ -25,6 +26,7 @@ export type FullscreenButtonSlots = typeof __propDef.slots;
|
|
25
26
|
*
|
26
27
|
* @props
|
27
28
|
*
|
29
|
+
* - `classNoscript` - noscript class
|
28
30
|
* - `class`
|
29
31
|
* - `confirmMessage` - message to display in the `confirm` popup, set this to empty string `""` to disable `confirm`
|
30
32
|
* - `id`
|
@@ -35,8 +37,8 @@ export type FullscreenButtonSlots = typeof __propDef.slots;
|
|
35
37
|
*
|
36
38
|
* | name | purpose | default value |
|
37
39
|
* | ---------- | ---------------------------------------------- | -------------------- |
|
40
|
+
* | `default` | content to display when fullscreen is disabled | `Enabled Fullscreen` |
|
38
41
|
* | `enabled` | content to display when fullscreen is enabled | `Exit Fullscreen` |
|
39
|
-
* | `disabled` | content to display when fullscreen is disabled | `Enabled Fullscreen` |
|
40
42
|
*
|
41
43
|
* @example
|
42
44
|
*
|
@@ -0,0 +1,155 @@
|
|
1
|
+
<!--
|
2
|
+
@component
|
3
|
+
|
4
|
+
### Popover
|
5
|
+
|
6
|
+
Displays a popover relatively positioned to the button.
|
7
|
+
|
8
|
+
@props
|
9
|
+
|
10
|
+
- `classButton` - button class
|
11
|
+
- `classPopover` - popover class
|
12
|
+
- `class`
|
13
|
+
- `display` - if `eventType="click"`, controls the display
|
14
|
+
- `eventType` - controls if hovering or clicking the button displays the popover
|
15
|
+
- `idButton` - button id
|
16
|
+
- `idPopover` - popover id
|
17
|
+
- `id`
|
18
|
+
- `position` - where the popover is displayed in relation to the button
|
19
|
+
|
20
|
+
@slots
|
21
|
+
|
22
|
+
| name | purpose | default value |
|
23
|
+
| ---------- | ------------------------------- | ------------- |
|
24
|
+
| `default` | default | Popover |
|
25
|
+
| `button` | button contents | Open |
|
26
|
+
|
27
|
+
@example
|
28
|
+
|
29
|
+
```svelte
|
30
|
+
<script>
|
31
|
+
import { Popover } from "drab";
|
32
|
+
</script>
|
33
|
+
|
34
|
+
<Popover>
|
35
|
+
<span slot="button">Hover</span>
|
36
|
+
<div>
|
37
|
+
<div>Popover</div>
|
38
|
+
<button>Button</button>
|
39
|
+
<button>Button</button>
|
40
|
+
<button>Button</button>
|
41
|
+
</div>
|
42
|
+
</Popover>
|
43
|
+
```
|
44
|
+
-->
|
45
|
+
|
46
|
+
<script>import { onMount, tick } from "svelte";
|
47
|
+
let className = "";
|
48
|
+
export { className as class };
|
49
|
+
export let id = "";
|
50
|
+
export let classButton = "";
|
51
|
+
export let classPopover = "";
|
52
|
+
export let idButton = "";
|
53
|
+
export let idPopover = "";
|
54
|
+
export let display = false;
|
55
|
+
export let position = "bottom";
|
56
|
+
export let eventType = "hover";
|
57
|
+
let clientEventType = "hover";
|
58
|
+
let popover;
|
59
|
+
let button;
|
60
|
+
let coordinates = { x: 0, y: 0 };
|
61
|
+
const correctPosition = async () => {
|
62
|
+
if (position === "top" || position === "bottom") {
|
63
|
+
coordinates.x = button.offsetWidth / 2 - popover.offsetWidth / 2;
|
64
|
+
if (position === "top") {
|
65
|
+
coordinates.y = -popover.offsetHeight;
|
66
|
+
} else {
|
67
|
+
coordinates.y = button.offsetHeight;
|
68
|
+
}
|
69
|
+
} else {
|
70
|
+
coordinates.y = button.offsetHeight / 2 - popover.offsetHeight / 2;
|
71
|
+
if (position === "left") {
|
72
|
+
coordinates.x = -popover.offsetWidth;
|
73
|
+
} else {
|
74
|
+
coordinates.x = button.offsetWidth;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
await tick();
|
78
|
+
const rect = popover.getBoundingClientRect();
|
79
|
+
if (rect.x < 0) {
|
80
|
+
coordinates.x += Math.abs(rect.x);
|
81
|
+
} else if (rect.x + popover.offsetWidth > window.innerWidth) {
|
82
|
+
coordinates.x -= rect.x + popover.offsetWidth - window.innerWidth + 16;
|
83
|
+
}
|
84
|
+
if (rect.y < 0) {
|
85
|
+
coordinates.y += Math.abs(rect.y);
|
86
|
+
} else if (rect.y + popover.offsetHeight > window.innerHeight) {
|
87
|
+
coordinates.y -= rect.y + popover.offsetHeight - window.innerHeight;
|
88
|
+
}
|
89
|
+
};
|
90
|
+
const clickOutside = (e) => {
|
91
|
+
if (popover && e.target instanceof HTMLElement) {
|
92
|
+
if (!popover.contains(e.target)) {
|
93
|
+
display = false;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
};
|
97
|
+
const onKeyDown = (e) => {
|
98
|
+
if (e.key === "Escape") {
|
99
|
+
display = false;
|
100
|
+
}
|
101
|
+
};
|
102
|
+
const openPopover = async (e) => {
|
103
|
+
e.stopPropagation();
|
104
|
+
display = true;
|
105
|
+
};
|
106
|
+
onMount(() => {
|
107
|
+
clientEventType = eventType;
|
108
|
+
correctPosition();
|
109
|
+
});
|
110
|
+
</script>
|
111
|
+
|
112
|
+
<svelte:document on:keydown={onKeyDown} on:click={clickOutside} />
|
113
|
+
|
114
|
+
<div class="db-relative {className}" {id}>
|
115
|
+
<button
|
116
|
+
bind:this={button}
|
117
|
+
id={idButton}
|
118
|
+
class={classButton}
|
119
|
+
on:click={openPopover}
|
120
|
+
on:mouseover={correctPosition}
|
121
|
+
on:focus={correctPosition}
|
122
|
+
>
|
123
|
+
<slot name="button">Open</slot>
|
124
|
+
</button>
|
125
|
+
<div
|
126
|
+
bind:this={popover}
|
127
|
+
id={idPopover}
|
128
|
+
class="db-popover {classPopover}"
|
129
|
+
class:db-type-click={clientEventType === "click" && display}
|
130
|
+
class:db-type-hover={clientEventType === "hover"}
|
131
|
+
style:top="{coordinates.y}px"
|
132
|
+
style:left="{coordinates.x}px"
|
133
|
+
>
|
134
|
+
<slot>Popover</slot>
|
135
|
+
</div>
|
136
|
+
</div>
|
137
|
+
|
138
|
+
<style>
|
139
|
+
.db-relative {
|
140
|
+
position: relative;
|
141
|
+
}
|
142
|
+
.db-popover {
|
143
|
+
position: absolute;
|
144
|
+
opacity: 0;
|
145
|
+
z-index: -10;
|
146
|
+
}
|
147
|
+
button:hover + .db-type-hover,
|
148
|
+
button:focus + .db-type-hover,
|
149
|
+
.db-type-hover:hover,
|
150
|
+
.db-type-hover:focus-within,
|
151
|
+
.db-type-click {
|
152
|
+
opacity: 1;
|
153
|
+
z-index: 10;
|
154
|
+
}
|
155
|
+
</style>
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import { SvelteComponent } from "svelte";
|
2
|
+
declare const __propDef: {
|
3
|
+
props: {
|
4
|
+
class?: string | undefined;
|
5
|
+
id?: string | undefined;
|
6
|
+
/** button class */ classButton?: string | undefined;
|
7
|
+
/** popover class */ classPopover?: string | undefined;
|
8
|
+
/** button id */ idButton?: string | undefined;
|
9
|
+
/** popover id */ idPopover?: string | undefined;
|
10
|
+
/** if `eventType="click"`, controls the display */ display?: boolean | undefined;
|
11
|
+
/** where the popover is displayed in relation to the button */ position?: "top" | "bottom" | "left" | "right" | undefined;
|
12
|
+
/** controls if hovering or clicking the button displays the popover */ eventType?: ("click" | "hover") | undefined;
|
13
|
+
};
|
14
|
+
events: {
|
15
|
+
[evt: string]: CustomEvent<any>;
|
16
|
+
};
|
17
|
+
slots: {
|
18
|
+
button: {};
|
19
|
+
default: {};
|
20
|
+
};
|
21
|
+
};
|
22
|
+
export type PopoverProps = typeof __propDef.props;
|
23
|
+
export type PopoverEvents = typeof __propDef.events;
|
24
|
+
export type PopoverSlots = typeof __propDef.slots;
|
25
|
+
/**
|
26
|
+
* ### Popover
|
27
|
+
*
|
28
|
+
* Displays a popover relatively positioned to the button.
|
29
|
+
*
|
30
|
+
* @props
|
31
|
+
*
|
32
|
+
* - `classButton` - button class
|
33
|
+
* - `classPopover` - popover class
|
34
|
+
* - `class`
|
35
|
+
* - `display` - if `eventType="click"`, controls the display
|
36
|
+
* - `eventType` - controls if hovering or clicking the button displays the popover
|
37
|
+
* - `idButton` - button id
|
38
|
+
* - `idPopover` - popover id
|
39
|
+
* - `id`
|
40
|
+
* - `position` - where the popover is displayed in relation to the button
|
41
|
+
*
|
42
|
+
* @slots
|
43
|
+
*
|
44
|
+
* | name | purpose | default value |
|
45
|
+
* | ---------- | ------------------------------- | ------------- |
|
46
|
+
* | `default` | default | Popover |
|
47
|
+
* | `button` | button contents | Open |
|
48
|
+
*
|
49
|
+
* @example
|
50
|
+
*
|
51
|
+
* ```svelte
|
52
|
+
* <script>
|
53
|
+
* import { Popover } from "drab";
|
54
|
+
* </script>
|
55
|
+
*
|
56
|
+
* <Popover>
|
57
|
+
* <span slot="button">Hover</span>
|
58
|
+
* <div>
|
59
|
+
* <div>Popover</div>
|
60
|
+
* <button>Button</button>
|
61
|
+
* <button>Button</button>
|
62
|
+
* <button>Button</button>
|
63
|
+
* </div>
|
64
|
+
* </Popover>
|
65
|
+
* ```
|
66
|
+
*/
|
67
|
+
export default class Popover extends SvelteComponent<PopoverProps, PopoverEvents, PopoverSlots> {
|
68
|
+
}
|
69
|
+
export {};
|
@@ -7,10 +7,11 @@ Uses the navigator api to share or copy a url link depending on browser support.
|
|
7
7
|
|
8
8
|
@props
|
9
9
|
|
10
|
+
- `classNoscript` - noscript class
|
10
11
|
- `class`
|
11
12
|
- `id`
|
12
13
|
- `text` - prefixed text in share message
|
13
|
-
- `title` - title of share message and button attribute
|
14
|
+
- `title` - title of share message and button attribute, defaults to end of url
|
14
15
|
- `url` - url to be shared
|
15
16
|
|
16
17
|
@slots
|
@@ -35,12 +36,15 @@ Uses the navigator api to share or copy a url link depending on browser support.
|
|
35
36
|
```
|
36
37
|
-->
|
37
38
|
|
38
|
-
<script>
|
39
|
+
<script>import { onMount } from "svelte";
|
40
|
+
let className = "";
|
39
41
|
export { className as class };
|
40
42
|
export let id = "";
|
41
43
|
export let text = "";
|
42
44
|
export let url;
|
43
45
|
export let title = url.split("/").splice(-1)[0];
|
46
|
+
export let classNoscript = "";
|
47
|
+
let clientJs = false;
|
44
48
|
let complete = false;
|
45
49
|
const onClick = async () => {
|
46
50
|
try {
|
@@ -55,12 +59,15 @@ const onClick = async () => {
|
|
55
59
|
console.log(error);
|
56
60
|
}
|
57
61
|
};
|
62
|
+
onMount(() => clientJs = true);
|
58
63
|
</script>
|
59
64
|
|
60
|
-
<button on:click={onClick} class={className} {id} {title}>
|
65
|
+
<button disabled={!clientJs} on:click={onClick} class={className} {id} {title}>
|
61
66
|
{#if complete}
|
62
67
|
<slot name="complete">Copied</slot>
|
63
68
|
{:else}
|
64
69
|
<slot>Share</slot>
|
65
70
|
{/if}
|
66
71
|
</button>
|
72
|
+
|
73
|
+
<noscript><span class={classNoscript}>{url}</span></noscript>
|
@@ -5,7 +5,8 @@ declare const __propDef: {
|
|
5
5
|
id?: string | undefined;
|
6
6
|
/** prefixed text in share message */ text?: string | undefined;
|
7
7
|
/** url to be shared */ url: string;
|
8
|
-
/** title of share message and button attribute */ title?: string | undefined;
|
8
|
+
/** title of share message and button attribute, defaults to end of url */ title?: string | undefined;
|
9
|
+
/** noscript class */ classNoscript?: string | undefined;
|
9
10
|
};
|
10
11
|
events: {
|
11
12
|
[evt: string]: CustomEvent<any>;
|
@@ -25,10 +26,11 @@ export type ShareButtonSlots = typeof __propDef.slots;
|
|
25
26
|
*
|
26
27
|
* @props
|
27
28
|
*
|
29
|
+
* - `classNoscript` - noscript class
|
28
30
|
* - `class`
|
29
31
|
* - `id`
|
30
32
|
* - `text` - prefixed text in share message
|
31
|
-
* - `title` - title of share message and button attribute
|
33
|
+
* - `title` - title of share message and button attribute, defaults to end of url
|
32
34
|
* - `url` - url to be shared
|
33
35
|
*
|
34
36
|
* @slots
|
package/dist/index.d.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import Chord from "./components/Chord.svelte";
|
2
|
+
import type { ChordNote } from "./components/Chord.svelte";
|
2
3
|
import ContextMenu from "./components/ContextMenu.svelte";
|
3
4
|
import CopyButton from "./components/CopyButton.svelte";
|
4
5
|
import DataTable from "./components/DataTable.svelte";
|
@@ -6,6 +7,7 @@ import type { DataTableRow } from "./components/DataTable.svelte";
|
|
6
7
|
import Editor from "./components/Editor.svelte";
|
7
8
|
import type { EditorContentElement } from "./components/Editor.svelte";
|
8
9
|
import FullscreenButton from "./components/FullscreenButton.svelte";
|
10
|
+
import Popover from "./components/Popover.svelte";
|
9
11
|
import ShareButton from "./components/ShareButton.svelte";
|
10
12
|
import YouTube from "./components/YouTube.svelte";
|
11
|
-
export { Chord, ContextMenu, CopyButton, DataTable, type DataTableRow, Editor, type EditorContentElement, FullscreenButton, ShareButton, YouTube, };
|
13
|
+
export { Chord, type ChordNote, ContextMenu, CopyButton, DataTable, type DataTableRow, Editor, type EditorContentElement, FullscreenButton, Popover, ShareButton, YouTube, };
|
package/dist/index.js
CHANGED
@@ -4,6 +4,7 @@ import CopyButton from "./components/CopyButton.svelte";
|
|
4
4
|
import DataTable from "./components/DataTable.svelte";
|
5
5
|
import Editor from "./components/Editor.svelte";
|
6
6
|
import FullscreenButton from "./components/FullscreenButton.svelte";
|
7
|
+
import Popover from "./components/Popover.svelte";
|
7
8
|
import ShareButton from "./components/ShareButton.svelte";
|
8
9
|
import YouTube from "./components/YouTube.svelte";
|
9
|
-
export { Chord, ContextMenu, CopyButton, DataTable, Editor, FullscreenButton, ShareButton, YouTube, };
|
10
|
+
export { Chord, ContextMenu, CopyButton, DataTable, Editor, FullscreenButton, Popover, ShareButton, YouTube, };
|
@@ -0,0 +1 @@
|
|
1
|
+
export declare const messageNoScript = "JavaScript is disabled on your device. This feature requires JavaScript for full functionality.";
|
@@ -0,0 +1 @@
|
|
1
|
+
export const messageNoScript = "JavaScript is disabled on your device. This feature requires JavaScript for full functionality.";
|
package/package.json
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
{
|
2
2
|
"name": "drab",
|
3
|
-
"version": "1.
|
3
|
+
"version": "2.1.0",
|
4
4
|
"description": "An unstyled Svelte component library",
|
5
5
|
"keywords": [
|
6
6
|
"components",
|
7
7
|
"Svelte",
|
8
8
|
"SvelteKit",
|
9
9
|
"Chord",
|
10
|
+
"ContextMenu",
|
10
11
|
"Copy",
|
11
12
|
"DataTable",
|
12
13
|
"Editor",
|
13
14
|
"Fullscreen",
|
15
|
+
"Popover",
|
14
16
|
"Share",
|
15
17
|
"YouTube"
|
16
18
|
],
|
@@ -48,8 +50,8 @@
|
|
48
50
|
},
|
49
51
|
"devDependencies": {
|
50
52
|
"@sveltejs/adapter-vercel": "^3.0.3",
|
51
|
-
"@sveltejs/kit": "^1.22.
|
52
|
-
"@sveltejs/package": "^2.2.
|
53
|
+
"@sveltejs/kit": "^1.22.5",
|
54
|
+
"@sveltejs/package": "^2.2.1",
|
53
55
|
"@tailwindcss/typography": "^0.5.9",
|
54
56
|
"@types/node": "^20.4.9",
|
55
57
|
"@typescript-eslint/eslint-plugin": "^6.3.0",
|
@@ -61,7 +63,7 @@
|
|
61
63
|
"postcss": "^8.4.27",
|
62
64
|
"prettier": "^3.0.1",
|
63
65
|
"prettier-plugin-svelte": "^3.0.3",
|
64
|
-
"prettier-plugin-tailwindcss": "^0.
|
66
|
+
"prettier-plugin-tailwindcss": "^0.5.1",
|
65
67
|
"publint": "^0.2.0",
|
66
68
|
"svelte-check": "^3.4.6",
|
67
69
|
"tailwindcss": "^3.3.3",
|