drab 1.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Ross Robino
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,35 @@
1
+ # drab
2
+
3
+ ## An unstyled Svelte component library
4
+
5
+ ### MIT License
6
+
7
+ ### Install
8
+
9
+ ```bash
10
+ npm create svelte@latest
11
+ ```
12
+
13
+ ```bash
14
+ npm i -D drab
15
+ ```
16
+
17
+ ### Use
18
+
19
+ ```svelte
20
+ <script>
21
+ import { ShareButton } from "drab";
22
+ </script>
23
+
24
+ <ShareButton
25
+ text="Check out this page: "
26
+ title="drab"
27
+ url="https://drab.robino.dev"
28
+ />
29
+ ```
30
+
31
+ ### Preview
32
+
33
+ [drab.robino.dev](https://drab.robino.dev)
34
+
35
+ ### Open to contributions
@@ -0,0 +1,208 @@
1
+ <!--
2
+ @component
3
+
4
+ ### Chord
5
+
6
+ Generates a guitar chord `svg`.
7
+
8
+ @props
9
+
10
+ - `class`
11
+ - `id`
12
+ - `name` - name of chord
13
+ - `notes` - list of the positioning of the notes required for the chord
14
+ - `size` - total size of chord square
15
+ - `strings` - total number of strings for the instrument
16
+
17
+ @example
18
+
19
+ ```svelte
20
+ <script>
21
+ import { Chord } from "drab";
22
+ </script>
23
+
24
+ <Chord name="D" notes={[
25
+ {
26
+ finger: 0,
27
+ string: 4,
28
+ fret: 0,
29
+ },
30
+ {
31
+ finger: 1,
32
+ string: 3,
33
+ fret: 2,
34
+ },
35
+ {
36
+ finger: 2,
37
+ string: 1,
38
+ fret: 2,
39
+ },
40
+ {
41
+ finger: 3,
42
+ string: 2,
43
+ fret: 3,
44
+ },
45
+ ]}
46
+ />
47
+ ```
48
+ -->
49
+
50
+ <script>let className = "";
51
+ export { className as class };
52
+ export let id = "";
53
+ export let strings = 6;
54
+ export let name = "";
55
+ export let size = 200;
56
+ const boxSize = size * 0.61;
57
+ const offset = (size - boxSize) / 2;
58
+ const strokeWidth = size / 60;
59
+ const stringList = Array.from(Array(strings).keys());
60
+ export let notes = [];
61
+ let notesList = structuredClone(notes);
62
+ const usedStrings = notesList.map((note) => note.string);
63
+ for (let i = 1; i < strings + 1; i++) {
64
+ if (!usedStrings.includes(i)) {
65
+ notesList.push({
66
+ finger: "X",
67
+ string: i,
68
+ fret: 0
69
+ });
70
+ }
71
+ }
72
+ const frets = notesList.map((note) => note.fret).filter((fret) => fret !== 0);
73
+ if (!frets.length)
74
+ frets.push(0);
75
+ const highFret = Math.max(...frets);
76
+ const lowFret = Math.min(...frets);
77
+ let fretRange = highFret - lowFret + 1;
78
+ if (fretRange < 5)
79
+ fretRange = 5;
80
+ let firstFret = lowFret;
81
+ if (firstFret < 4 && highFret < 5) {
82
+ firstFret = 1;
83
+ if (lowFret !== 0)
84
+ fretRange += lowFret - 1;
85
+ if (lowFret === 2 && highFret < 5)
86
+ fretRange -= 1;
87
+ if (lowFret === 3 && highFret < 5)
88
+ fretRange -= 2;
89
+ } else {
90
+ notesList.forEach((note) => {
91
+ if (note.fret !== 0) {
92
+ note.fret = note.fret - firstFret + 1;
93
+ }
94
+ });
95
+ }
96
+ const circleRadius = boxSize / fretRange / 2.3;
97
+ const stringX = (string) => {
98
+ return boxSize / (strings - 1) * string + offset;
99
+ };
100
+ const fretY = (fret) => {
101
+ return boxSize / fretRange * fret + offset;
102
+ };
103
+ const noteX = (string) => {
104
+ return boxSize + offset - boxSize / (strings - 1) * (string - 1);
105
+ };
106
+ const noteY = (fret) => {
107
+ return boxSize / fretRange * fret + offset / 2 - boxSize / fretRange / 2;
108
+ };
109
+ </script>
110
+
111
+ {#if notes.length}
112
+ <svg
113
+ width={size}
114
+ height={size}
115
+ stroke="currentColor"
116
+ fill="currentColor"
117
+ class={className}
118
+ {id}
119
+ >
120
+ <title>{name}</title>
121
+
122
+ <!-- BACKGROUND -->
123
+ <rect
124
+ width={boxSize}
125
+ height={boxSize}
126
+ fill="transparent"
127
+ x={offset}
128
+ y={offset / 2}
129
+ stroke-width={strokeWidth}
130
+ />
131
+ <line
132
+ x1={offset - strokeWidth / 2}
133
+ y1={offset / 2 - strokeWidth / 2}
134
+ x2={boxSize + offset + strokeWidth / 2}
135
+ y2={offset / 2 - strokeWidth / 2}
136
+ stroke-width={strokeWidth * 2}
137
+ />
138
+
139
+ <!-- FRETS -->
140
+ {#each Array.from(Array(fretRange).keys()) as fret}
141
+ <line
142
+ x1={offset}
143
+ y1={fretY(fret) - offset / 2}
144
+ x2={boxSize + offset}
145
+ y2={fretY(fret) - offset / 2}
146
+ stroke-width={strokeWidth}
147
+ opacity="0.2"
148
+ />
149
+ {/each}
150
+
151
+ <!-- STRINGS -->
152
+ {#each stringList as string}
153
+ <line
154
+ x1={stringX(string)}
155
+ y1={offset / 2}
156
+ x2={stringX(string)}
157
+ y2={boxSize + offset / 2}
158
+ stroke-width={strokeWidth}
159
+ />
160
+ {/each}
161
+
162
+ <!-- NOTES -->
163
+ {#each notesList as note}
164
+ {#if note.fret !== 0}
165
+ <circle
166
+ cx={noteX(note.string)}
167
+ cy={noteY(note.fret)}
168
+ r={circleRadius}
169
+ />
170
+ {/if}
171
+ {#if note.finger !== 0}
172
+ <!-- RECOMMENDED FINGER -->
173
+ <text
174
+ x={noteX(note.string) - size / 50}
175
+ y={note.fret === 0
176
+ ? offset / 2 - strokeWidth * 2.4
177
+ : size - offset * 1.1}
178
+ color="currentColor"
179
+ fill="currentColor"
180
+ font-size={size / 13}
181
+ >
182
+ {note.finger}
183
+ </text>
184
+ {/if}
185
+ {/each}
186
+
187
+ <!-- CHORD NAME -->
188
+ <text
189
+ x={offset}
190
+ y={size - offset / 2.5}
191
+ font-size={boxSize / 6}
192
+ font-weight="600"
193
+ >
194
+ {name}
195
+ </text>
196
+
197
+ <!-- STARTING FRET -->
198
+ {#if firstFret > 1}
199
+ <text
200
+ x={size - offset / 1.8}
201
+ y={offset / 2 + boxSize / 7}
202
+ font-size={size / 13}
203
+ >
204
+ {firstFret}f
205
+ </text>
206
+ {/if}
207
+ </svg>
208
+ {/if}
@@ -0,0 +1,74 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ class?: string | undefined;
5
+ id?: string | undefined;
6
+ /** total number of strings for the instrument */ strings?: number | undefined;
7
+ /** name of chord */ name?: string | undefined;
8
+ /** 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
+ };
18
+ events: {
19
+ [evt: string]: CustomEvent<any>;
20
+ };
21
+ slots: {};
22
+ };
23
+ export type ChordProps = typeof __propDef.props;
24
+ export type ChordEvents = typeof __propDef.events;
25
+ export type ChordSlots = typeof __propDef.slots;
26
+ /**
27
+ * ### Chord
28
+ *
29
+ * Generates a guitar chord `svg`.
30
+ *
31
+ * @props
32
+ *
33
+ * - `class`
34
+ * - `id`
35
+ * - `name` - name of chord
36
+ * - `notes` - list of the positioning of the notes required for the chord
37
+ * - `size` - total size of chord square
38
+ * - `strings` - total number of strings for the instrument
39
+ *
40
+ * @example
41
+ *
42
+ * ```svelte
43
+ * <script>
44
+ * import { Chord } from "drab";
45
+ * </script>
46
+ *
47
+ * <Chord name="D" notes={[
48
+ * {
49
+ * finger: 0,
50
+ * string: 4,
51
+ * fret: 0,
52
+ * },
53
+ * {
54
+ * finger: 1,
55
+ * string: 3,
56
+ * fret: 2,
57
+ * },
58
+ * {
59
+ * finger: 2,
60
+ * string: 1,
61
+ * fret: 2,
62
+ * },
63
+ * {
64
+ * finger: 3,
65
+ * string: 2,
66
+ * fret: 3,
67
+ * },
68
+ * ]}
69
+ * />
70
+ * ```
71
+ */
72
+ export default class Chord extends SvelteComponent<ChordProps, ChordEvents, ChordSlots> {
73
+ }
74
+ export {};
@@ -0,0 +1,93 @@
1
+ <!--
2
+ @component
3
+
4
+ ### ContextMenu
5
+
6
+ Displays when the parent element is right clicked.
7
+
8
+ @props
9
+
10
+ - `class`
11
+ - `display` - controls `display` css property
12
+ - `id`
13
+
14
+ @slots
15
+
16
+ | name | purpose | default value |
17
+ | ---------- | ------------------------------- | ------------- |
18
+ | `default` | default | Context Menu |
19
+
20
+ @example
21
+
22
+ ```svelte
23
+ <script>
24
+ import { ContextMenu } from "@rossrobino/components";
25
+ </script>
26
+
27
+ <div class="p-12 border border-dashed flex justify-center">
28
+ <div>Right click here</div>
29
+ <ContextMenu class="rounded shadow p-2 bg-white">
30
+ <div class="flex flex-col gap-2 not-prose w-48">
31
+ <div class="font-bold">Context Menu</div>
32
+ <button class="btn">Button</button>
33
+ <button class="btn">Button</button>
34
+ <button class="btn">Button</button>
35
+ </div>
36
+ </ContextMenu>
37
+ </div>
38
+ ```
39
+ -->
40
+
41
+ <script>import { onMount, tick } from "svelte";
42
+ let className = "";
43
+ export { className as class };
44
+ export let id = "";
45
+ export let display = false;
46
+ let contextMenu;
47
+ let position = { x: 0, y: 0 };
48
+ const hide = () => display = false;
49
+ onMount(() => {
50
+ const parent = contextMenu.parentElement;
51
+ if (parent) {
52
+ parent.addEventListener("contextmenu", async (e) => {
53
+ if (contextMenu) {
54
+ e.preventDefault();
55
+ const scrollY = window.scrollY;
56
+ position.x = e.clientX;
57
+ position.y = e.clientY + scrollY;
58
+ display = true;
59
+ await tick();
60
+ const offsetWidth = contextMenu.offsetWidth + 24;
61
+ const offsetHeight = contextMenu.offsetHeight + 6;
62
+ const innerWidth = window.innerWidth;
63
+ const innerHeight = window.innerHeight;
64
+ if (position.x + offsetWidth > innerWidth) {
65
+ position.x = innerWidth - offsetWidth;
66
+ }
67
+ if (position.y + offsetHeight > scrollY + innerHeight) {
68
+ position.y = scrollY + innerHeight - offsetHeight;
69
+ }
70
+ }
71
+ });
72
+ }
73
+ });
74
+ </script>
75
+
76
+ <svelte:document on:click={hide} />
77
+
78
+ <div
79
+ class={className}
80
+ {id}
81
+ bind:this={contextMenu}
82
+ style="display: {display
83
+ ? 'block'
84
+ : 'none'}; top: {position.y}px; left: {position.x}px;"
85
+ >
86
+ <slot>Context Menu</slot>
87
+ </div>
88
+
89
+ <style>
90
+ div {
91
+ position: absolute;
92
+ }
93
+ </style>
@@ -0,0 +1,57 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ class?: string | undefined;
5
+ id?: string | undefined;
6
+ /** controls `display` css property */ display?: boolean | undefined;
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {
12
+ default: {};
13
+ };
14
+ };
15
+ export type ContextMenuProps = typeof __propDef.props;
16
+ export type ContextMenuEvents = typeof __propDef.events;
17
+ export type ContextMenuSlots = typeof __propDef.slots;
18
+ /**
19
+ * ### ContextMenu
20
+ *
21
+ * Displays when the parent element is right clicked.
22
+ *
23
+ * @props
24
+ *
25
+ * - `class`
26
+ * - `display` - controls `display` css property
27
+ * - `id`
28
+ *
29
+ * @slots
30
+ *
31
+ * | name | purpose | default value |
32
+ * | ---------- | ------------------------------- | ------------- |
33
+ * | `default` | default | Context Menu |
34
+ *
35
+ * @example
36
+ *
37
+ * ```svelte
38
+ * <script>
39
+ * import { ContextMenu } from "@rossrobino/components";
40
+ * </script>
41
+ *
42
+ * <div class="p-12 border border-dashed flex justify-center">
43
+ * <div>Right click here</div>
44
+ * <ContextMenu class="rounded shadow p-2 bg-white">
45
+ * <div class="flex flex-col gap-2 not-prose w-48">
46
+ * <div class="font-bold">Context Menu</div>
47
+ * <button class="btn">Button</button>
48
+ * <button class="btn">Button</button>
49
+ * <button class="btn">Button</button>
50
+ * </div>
51
+ * </ContextMenu>
52
+ * </div>
53
+ * ```
54
+ */
55
+ export default class ContextMenu extends SvelteComponent<ContextMenuProps, ContextMenuEvents, ContextMenuSlots> {
56
+ }
57
+ export {};
@@ -0,0 +1,56 @@
1
+ <!--
2
+ @component
3
+
4
+ ### CopyButton
5
+
6
+ Uses the navigator api to copy text to the clipboard.
7
+
8
+ @props
9
+
10
+ - `class`
11
+ - `id`
12
+ - `text` - text to copy
13
+ - `title`
14
+
15
+ @slots
16
+
17
+ | name | purpose | default value |
18
+ | ---------- | ------------------------------- | ------------- |
19
+ | `default` | default | `Copy` |
20
+ | `complete` | displays after copy is complete | `Copied` |
21
+
22
+ @example
23
+
24
+ ```svelte
25
+ <script>
26
+ import { CopyButton } from "@rossrobino/components";
27
+ </script>
28
+
29
+ <CopyButton text="Text to copy" />
30
+ ```
31
+ -->
32
+
33
+ <script>let className = "";
34
+ export { className as class };
35
+ export let id = "";
36
+ export let title = "Copy";
37
+ export let text;
38
+ let complete = false;
39
+ const copyText = async () => {
40
+ try {
41
+ await navigator.clipboard.writeText(text);
42
+ complete = true;
43
+ setTimeout(() => complete = false, 800);
44
+ } catch (error) {
45
+ console.error(error);
46
+ }
47
+ };
48
+ </script>
49
+
50
+ <button on:click={copyText} class={className} {id} {title}>
51
+ {#if complete}
52
+ <slot name="complete">Copied</slot>
53
+ {:else}
54
+ <slot>Copy</slot>
55
+ {/if}
56
+ </button>
@@ -0,0 +1,51 @@
1
+ import { SvelteComponent } from "svelte";
2
+ declare const __propDef: {
3
+ props: {
4
+ class?: string | undefined;
5
+ id?: string | undefined;
6
+ title?: string | undefined;
7
+ /** text to copy */ text: string;
8
+ };
9
+ events: {
10
+ [evt: string]: CustomEvent<any>;
11
+ };
12
+ slots: {
13
+ complete: {};
14
+ default: {};
15
+ };
16
+ };
17
+ export type CopyButtonProps = typeof __propDef.props;
18
+ export type CopyButtonEvents = typeof __propDef.events;
19
+ export type CopyButtonSlots = typeof __propDef.slots;
20
+ /**
21
+ * ### CopyButton
22
+ *
23
+ * Uses the navigator api to copy text to the clipboard.
24
+ *
25
+ * @props
26
+ *
27
+ * - `class`
28
+ * - `id`
29
+ * - `text` - text to copy
30
+ * - `title`
31
+ *
32
+ * @slots
33
+ *
34
+ * | name | purpose | default value |
35
+ * | ---------- | ------------------------------- | ------------- |
36
+ * | `default` | default | `Copy` |
37
+ * | `complete` | displays after copy is complete | `Copied` |
38
+ *
39
+ * @example
40
+ *
41
+ * ```svelte
42
+ * <script>
43
+ * import { CopyButton } from "@rossrobino/components";
44
+ * </script>
45
+ *
46
+ * <CopyButton text="Text to copy" />
47
+ * ```
48
+ */
49
+ export default class CopyButton extends SvelteComponent<CopyButtonProps, CopyButtonEvents, CopyButtonSlots> {
50
+ }
51
+ export {};