drab 4.1.6 → 5.0.0-beta.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.
Files changed (136) hide show
  1. package/animate/define.d.ts +2 -0
  2. package/animate/define.iife.js +1 -0
  3. package/animate/define.js +1 -0
  4. package/animate.d.ts +54 -0
  5. package/animate.iife.js +1 -0
  6. package/animate.js +1 -0
  7. package/base/define.d.ts +2 -0
  8. package/base/define.iife.js +1 -0
  9. package/base/define.js +1 -0
  10. package/base.d.ts +69 -0
  11. package/base.iife.js +1 -0
  12. package/base.js +1 -0
  13. package/breakpoint/define.d.ts +2 -0
  14. package/breakpoint/define.iife.js +1 -0
  15. package/breakpoint/define.js +1 -0
  16. package/breakpoint.d.ts +24 -0
  17. package/breakpoint.iife.js +1 -0
  18. package/breakpoint.js +1 -0
  19. package/chunk-2ZZQECRY.js +1 -0
  20. package/chunk-57VEEUFG.js +1 -0
  21. package/chunk-5JV4T7GM.js +1 -0
  22. package/chunk-6HYPZWQ4.js +1 -0
  23. package/chunk-7F7CQUEG.js +1 -0
  24. package/chunk-7KU2PRW5.js +1 -0
  25. package/chunk-7S6DTKGH.js +1 -0
  26. package/chunk-FNJ7AESC.js +9 -0
  27. package/chunk-IQJQPZUL.js +1 -0
  28. package/chunk-JMJUWKN2.js +1 -0
  29. package/chunk-MXKU7AKV.js +1 -0
  30. package/chunk-T7RZI3ZL.js +1 -0
  31. package/chunk-TSTTUEAF.js +1 -0
  32. package/chunk-VEVFQB5N.js +1 -0
  33. package/contextmenu/define.d.ts +2 -0
  34. package/contextmenu/define.iife.js +1 -0
  35. package/contextmenu/define.js +1 -0
  36. package/contextmenu.d.ts +15 -0
  37. package/contextmenu.iife.js +1 -0
  38. package/contextmenu.js +1 -0
  39. package/copy/define.d.ts +2 -0
  40. package/copy/define.iife.js +1 -0
  41. package/copy/define.js +1 -0
  42. package/copy.d.ts +13 -0
  43. package/copy.iife.js +1 -0
  44. package/copy.js +1 -0
  45. package/define.d.ts +2 -0
  46. package/define.iife.js +9 -0
  47. package/define.js +1 -0
  48. package/details/define.d.ts +2 -0
  49. package/details/define.iife.js +1 -0
  50. package/details/define.js +1 -0
  51. package/details.d.ts +23 -0
  52. package/details.iife.js +1 -0
  53. package/details.js +1 -0
  54. package/dialog/define.d.ts +2 -0
  55. package/dialog/define.iife.js +1 -0
  56. package/dialog/define.js +1 -0
  57. package/dialog.d.ts +20 -0
  58. package/dialog.iife.js +1 -0
  59. package/dialog.js +1 -0
  60. package/editor/define.d.ts +2 -0
  61. package/editor/define.iife.js +9 -0
  62. package/editor/define.js +1 -0
  63. package/editor.d.ts +58 -0
  64. package/editor.iife.js +9 -0
  65. package/editor.js +1 -0
  66. package/fullscreen/define.d.ts +2 -0
  67. package/fullscreen/define.iife.js +1 -0
  68. package/fullscreen/define.js +1 -0
  69. package/fullscreen.d.ts +23 -0
  70. package/fullscreen.iife.js +1 -0
  71. package/fullscreen.js +1 -0
  72. package/index-22PHGcPf.d.ts +17 -0
  73. package/index.d.ts +14 -0
  74. package/index.iife.js +9 -0
  75. package/index.js +1 -0
  76. package/package.json +131 -59
  77. package/popover/define.d.ts +2 -0
  78. package/popover/define.iife.js +1 -0
  79. package/popover/define.js +1 -0
  80. package/popover.d.ts +29 -0
  81. package/popover.iife.js +1 -0
  82. package/popover.js +1 -0
  83. package/share/define.d.ts +2 -0
  84. package/share/define.iife.js +1 -0
  85. package/share/define.js +1 -0
  86. package/share.d.ts +19 -0
  87. package/share.iife.js +1 -0
  88. package/share.js +1 -0
  89. package/tablesort/define.d.ts +2 -0
  90. package/tablesort/define.iife.js +1 -0
  91. package/tablesort/define.js +1 -0
  92. package/tablesort.d.ts +21 -0
  93. package/tablesort.iife.js +1 -0
  94. package/tablesort.js +1 -0
  95. package/youtube/define.d.ts +2 -0
  96. package/youtube/define.iife.js +1 -0
  97. package/youtube/define.js +1 -0
  98. package/youtube.d.ts +29 -0
  99. package/youtube.iife.js +1 -0
  100. package/youtube.js +1 -0
  101. package/LICENSE.md +0 -21
  102. package/README.md +0 -131
  103. package/dist/components/Breakpoint.svelte +0 -55
  104. package/dist/components/Breakpoint.svelte.d.ts +0 -46
  105. package/dist/components/ContextMenu.svelte +0 -150
  106. package/dist/components/ContextMenu.svelte.d.ts +0 -76
  107. package/dist/components/CopyButton.svelte +0 -97
  108. package/dist/components/CopyButton.svelte.d.ts +0 -60
  109. package/dist/components/DataTable.svelte +0 -208
  110. package/dist/components/DataTable.svelte.d.ts +0 -155
  111. package/dist/components/Details.svelte +0 -101
  112. package/dist/components/Details.svelte.d.ts +0 -67
  113. package/dist/components/Editor.svelte +0 -404
  114. package/dist/components/Editor.svelte.d.ts +0 -111
  115. package/dist/components/FrettedChord.svelte +0 -213
  116. package/dist/components/FrettedChord.svelte.d.ts +0 -79
  117. package/dist/components/FullscreenButton.svelte +0 -95
  118. package/dist/components/FullscreenButton.svelte.d.ts +0 -62
  119. package/dist/components/Popover.svelte +0 -153
  120. package/dist/components/Popover.svelte.d.ts +0 -80
  121. package/dist/components/ShareButton.svelte +0 -133
  122. package/dist/components/ShareButton.svelte.d.ts +0 -93
  123. package/dist/components/Sheet.svelte +0 -180
  124. package/dist/components/Sheet.svelte.d.ts +0 -99
  125. package/dist/components/Tablature.svelte +0 -173
  126. package/dist/components/Tablature.svelte.d.ts +0 -93
  127. package/dist/components/YouTube.svelte +0 -51
  128. package/dist/components/YouTube.svelte.d.ts +0 -49
  129. package/dist/index.d.ts +0 -14
  130. package/dist/index.js +0 -14
  131. package/dist/util/accessibility.d.ts +0 -6
  132. package/dist/util/accessibility.js +0 -11
  133. package/dist/util/delay.d.ts +0 -1
  134. package/dist/util/delay.js +0 -1
  135. package/dist/util/transition.d.ts +0 -2
  136. package/dist/util/transition.js +0 -2
@@ -1,133 +0,0 @@
1
- <!--
2
- @component
3
-
4
- ### ShareButton
5
-
6
- Uses the [Navigator API](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share) to share data. Progressively enhances according to browser support.
7
-
8
- - If the browser cannot share the provided data:
9
- - `url` - uses the the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText) to copy
10
- - `files` - uses a hidden `anchor` element to download the first file in the `files` array
11
- - If no JavaScript:
12
- - `button` is disabled
13
- - `url` - displayed after the `button`
14
-
15
- @props
16
-
17
- - `classNoscript` - `noscript` class
18
- - `class`
19
- - `id`
20
- - `shareData` - [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share)
21
- - `title`
22
-
23
- @slots
24
-
25
- | name | purpose | default value |
26
- | ---------- | ------------------------------- | ------------- |
27
- | `default` | default | `Share` |
28
- | `complete` | displays after copy is complete | `Copied` |
29
-
30
- @example
31
-
32
- ```svelte
33
- <script lang="ts">
34
- import { ShareButton } from "drab";
35
-
36
- let fileInput: HTMLInputElement;
37
-
38
- let fileShareData: ShareData;
39
-
40
- const onInput = () => {
41
- if (fileInput.files) {
42
- fileShareData.files = [fileInput.files[0]];
43
- }
44
- };
45
- </script>
46
-
47
- <ShareButton
48
- class="button button-primary mb-8"
49
- shareData={{
50
- text: "Check out this page: ",
51
- title: "drab",
52
- url: "https://drab.robino.dev",
53
- }}
54
- >
55
- Share URL
56
- </ShareButton>
57
-
58
- <div>
59
- <label class="label" for="fileInput">Upload File</label>
60
- <input
61
- type="file"
62
- id="fileInput"
63
- class="input mb-4"
64
- bind:this={fileInput}
65
- on:input={onInput}
66
- />
67
- <ShareButton class="button button-primary" bind:shareData={fileShareData}>
68
- Share File
69
- </ShareButton>
70
- </div>
71
- ```
72
- -->
73
-
74
- <script>import { onMount } from "svelte";
75
- import { delay } from "../util/delay";
76
- let className = "";
77
- export { className as class };
78
- export let id = "";
79
- export let title = "";
80
- export let shareData = {};
81
- let downloadAnchor;
82
- export let classNoscript = "";
83
- let clientJs = false;
84
- let complete = false;
85
- const onClick = async () => {
86
- if (navigator.canShare && navigator.canShare(shareData)) {
87
- try {
88
- await navigator.share(shareData);
89
- } catch (error) {
90
- if (error.name !== "AbortError") {
91
- console.error(error);
92
- }
93
- }
94
- } else if (shareData.url) {
95
- try {
96
- await navigator.clipboard.writeText(shareData.url);
97
- complete = true;
98
- setTimeout(() => complete = false, delay);
99
- } catch (error) {
100
- console.error(error);
101
- }
102
- } else if (shareData.files) {
103
- const file = shareData.files.at(0);
104
- if (file) {
105
- downloadAnchor.download = file.name;
106
- downloadAnchor.href = URL.createObjectURL(file);
107
- downloadAnchor.click();
108
- }
109
- }
110
- };
111
- onMount(() => clientJs = true);
112
- </script>
113
-
114
- <button
115
- type="button"
116
- disabled={!clientJs || (!shareData.url && !shareData.files)}
117
- on:click={onClick}
118
- class={className}
119
- {id}
120
- {title}
121
- >
122
- {#if complete}
123
- <slot name="complete">Copied</slot>
124
- {:else}
125
- <slot>Share</slot>
126
- {/if}
127
- </button>
128
-
129
- <a href="/" bind:this={downloadAnchor} style:display="none">Download</a>
130
-
131
- {#if shareData.url}
132
- <noscript><span class={classNoscript}>{shareData.url}</span></noscript>
133
- {/if}
@@ -1,93 +0,0 @@
1
- import { SvelteComponent } from "svelte";
2
- declare const __propDef: {
3
- props: {
4
- class?: string | undefined;
5
- id?: string | undefined;
6
- title?: string | undefined;
7
- /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share) */ shareData?: ShareData | undefined;
8
- /** `noscript` class */ classNoscript?: string | undefined;
9
- };
10
- events: {
11
- [evt: string]: CustomEvent<any>;
12
- };
13
- slots: {
14
- complete: {};
15
- default: {};
16
- };
17
- };
18
- export type ShareButtonProps = typeof __propDef.props;
19
- export type ShareButtonEvents = typeof __propDef.events;
20
- export type ShareButtonSlots = typeof __propDef.slots;
21
- /**
22
- * ### ShareButton
23
- *
24
- * Uses the [Navigator API](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share) to share data. Progressively enhances according to browser support.
25
- *
26
- * - If the browser cannot share the provided data:
27
- * - `url` - uses the the [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/writeText) to copy
28
- * - `files` - uses a hidden `anchor` element to download the first file in the `files` array
29
- * - If no JavaScript:
30
- * - `button` is disabled
31
- * - `url` - displayed after the `button`
32
- *
33
- * @props
34
- *
35
- * - `classNoscript` - `noscript` class
36
- * - `class`
37
- * - `id`
38
- * - `shareData` - [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share)
39
- * - `title`
40
- *
41
- * @slots
42
- *
43
- * | name | purpose | default value |
44
- * | ---------- | ------------------------------- | ------------- |
45
- * | `default` | default | `Share` |
46
- * | `complete` | displays after copy is complete | `Copied` |
47
- *
48
- * @example
49
- *
50
- * ```svelte
51
- * <script lang="ts">
52
- * import { ShareButton } from "drab";
53
- *
54
- * let fileInput: HTMLInputElement;
55
- *
56
- * let fileShareData: ShareData;
57
- *
58
- * const onInput = () => {
59
- * if (fileInput.files) {
60
- * fileShareData.files = [fileInput.files[0]];
61
- * }
62
- * };
63
- * </script>
64
- *
65
- * <ShareButton
66
- * class="button button-primary mb-8"
67
- * shareData={{
68
- * text: "Check out this page: ",
69
- * title: "drab",
70
- * url: "https://drab.robino.dev",
71
- * }}
72
- * >
73
- * Share URL
74
- * </ShareButton>
75
- *
76
- * <div>
77
- * <label class="label" for="fileInput">Upload File</label>
78
- * <input
79
- * type="file"
80
- * id="fileInput"
81
- * class="input mb-4"
82
- * bind:this={fileInput}
83
- * on:input={onInput}
84
- * />
85
- * <ShareButton class="button button-primary" bind:shareData={fileShareData}>
86
- * Share File
87
- * </ShareButton>
88
- * </div>
89
- * ```
90
- */
91
- export default class ShareButton extends SvelteComponent<ShareButtonProps, ShareButtonEvents, ShareButtonSlots> {
92
- }
93
- export {};
@@ -1,180 +0,0 @@
1
- <!--
2
- @component
3
-
4
- ### Sheet
5
-
6
- Creates a sheet element based on the `position` provided. `maxSize` is set to width or height of the sheet depending on the `position` provided. The `transition` is calculated based on the `position` and `maxSize` of the sheet.
7
-
8
- @props
9
-
10
- - `classSheet` - sheet class - not the backdrop
11
- - `class`
12
- - `display` - controls whether the sheet is displayed
13
- - `id`
14
- - `maxSize` - max width/height of sheet based on the `side` - can also use css instead
15
- - `position` - determines the position of sheet
16
- - `transition` - flies the sheet, set to `false` to remove
17
-
18
- @slots
19
-
20
- | name | purpose | default value |
21
- | ---------- | ------------------------------- | ------------- |
22
- | `default` | content | `Content` |
23
-
24
- @events
25
-
26
- | name | event |
27
- | --------- | ------------------ |
28
- | `mount` | sheet is mounted |
29
- | `destroy` | sheet is destroyed |
30
-
31
- @example
32
-
33
- ```svelte
34
- <script lang="ts">
35
- import { Sheet } from "drab";
36
-
37
- let display = false;
38
- </script>
39
-
40
- <button
41
- type="button"
42
- class="button button-primary"
43
- on:click={() => (display = true)}
44
- >
45
- Open
46
- </button>
47
-
48
- <Sheet
49
- bind:display
50
- class="z-40 backdrop-blur"
51
- classSheet="card rounded-none border-none"
52
- position="r"
53
- >
54
- <div class="mb-4 flex items-center justify-between">
55
- <h2 class="my-0">Sheet</h2>
56
- <button
57
- type="button"
58
- class="button button-ghost"
59
- on:click={() => (display = false)}
60
- >
61
- Close
62
- </button>
63
- </div>
64
- <div>
65
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
66
- tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
67
- quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
68
- consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
69
- cillum dolore eu fugiat nulla pariatur.
70
- </div>
71
- </Sheet>
72
- ```
73
- -->
74
-
75
- <script>import { createEventDispatcher, onMount, tick } from "svelte";
76
- import { fly } from "svelte/transition";
77
- import { prefersReducedMotion } from "../util/accessibility";
78
- import { duration } from "../util/transition";
79
- let className = "";
80
- export { className as class };
81
- export let id = "";
82
- export let classSheet = "";
83
- export let display = false;
84
- export let position = "l";
85
- export let maxSize = 488;
86
- export let transition = { duration, opacity: 1 };
87
- let sheet;
88
- let backdropStyles = true;
89
- let displaySheet = false;
90
- const dispatch = createEventDispatcher();
91
- const close = () => display = false;
92
- const onKeyDown = (e) => {
93
- if (e.key === "Escape")
94
- close();
95
- };
96
- const lifecycle = (node) => {
97
- dispatch("mount");
98
- if (node instanceof HTMLElement)
99
- node.focus();
100
- return { destroy: () => dispatch("destroy") };
101
- };
102
- const displayController = async (display2) => {
103
- if (display2) {
104
- backdropStyles = true;
105
- displaySheet = true;
106
- } else {
107
- backdropStyles = false;
108
- await tick();
109
- displaySheet = false;
110
- }
111
- };
112
- if (transition && !transition.x && !transition.y) {
113
- if (position === "b") {
114
- transition.y = maxSize;
115
- } else if (position === "t") {
116
- transition.y = -maxSize;
117
- } else if (position === "r") {
118
- transition.x = maxSize;
119
- } else {
120
- transition.x = -maxSize;
121
- }
122
- }
123
- onMount(() => {
124
- if (prefersReducedMotion())
125
- transition = false;
126
- });
127
- $:
128
- displayController(display);
129
- </script>
130
-
131
- <svelte:body on:keydown={onKeyDown} />
132
-
133
- {#if displaySheet}
134
- <div
135
- class="backdrop {backdropStyles ? className : ''}"
136
- class:backdrop-bottom={position === "b"}
137
- class:backdrop-top={position === "t"}
138
- class:backdrop-right={position === "r"}
139
- {id}
140
- >
141
- <div
142
- bind:this={sheet}
143
- transition:fly={transition ? transition : { duration: 0 }}
144
- use:lifecycle
145
- role="dialog"
146
- tabindex="-1"
147
- style="outline: none; {position === 't' || position === 'b'
148
- ? `max-height: ${maxSize}px;`
149
- : `max-width: ${maxSize}px`}"
150
- class={classSheet}
151
- >
152
- <slot>Content</slot>
153
- </div>
154
- <button title="Close" on:click={close}></button>
155
- </div>
156
- {/if}
157
-
158
- <style>
159
- button {
160
- flex-grow: 1;
161
- }
162
- .backdrop {
163
- display: flex;
164
- position: fixed;
165
- top: 0;
166
- right: 0;
167
- bottom: 0;
168
- left: 0;
169
- overflow: hidden;
170
- }
171
- .backdrop-bottom {
172
- flex-direction: column-reverse;
173
- }
174
- .backdrop-top {
175
- flex-direction: column;
176
- }
177
- .backdrop-right {
178
- flex-direction: row-reverse;
179
- }
180
- </style>
@@ -1,99 +0,0 @@
1
- import { SvelteComponent } from "svelte";
2
- import { type FlyParams } from "svelte/transition";
3
- declare const __propDef: {
4
- props: {
5
- class?: string | undefined;
6
- id?: string | undefined;
7
- /** sheet class - not the backdrop */ classSheet?: string | undefined;
8
- /** controls whether the sheet is displayed*/ display?: boolean | undefined;
9
- /** determines the position of sheet */ position?: "t" | "r" | "b" | "l" | undefined;
10
- /** max width/height of sheet based on the `side` - can also use css instead */ maxSize?: number | undefined;
11
- /** flies the sheet, set to `false` to remove */ transition?: false | FlyParams | undefined;
12
- };
13
- events: {
14
- mount: CustomEvent<any>;
15
- destroy: CustomEvent<any>;
16
- } & {
17
- [evt: string]: CustomEvent<any>;
18
- };
19
- slots: {
20
- default: {};
21
- };
22
- };
23
- export type SheetProps = typeof __propDef.props;
24
- export type SheetEvents = typeof __propDef.events;
25
- export type SheetSlots = typeof __propDef.slots;
26
- /**
27
- * ### Sheet
28
- *
29
- * Creates a sheet element based on the `position` provided. `maxSize` is set to width or height of the sheet depending on the `position` provided. The `transition` is calculated based on the `position` and `maxSize` of the sheet.
30
- *
31
- * @props
32
- *
33
- * - `classSheet` - sheet class - not the backdrop
34
- * - `class`
35
- * - `display` - controls whether the sheet is displayed
36
- * - `id`
37
- * - `maxSize` - max width/height of sheet based on the `side` - can also use css instead
38
- * - `position` - determines the position of sheet
39
- * - `transition` - flies the sheet, set to `false` to remove
40
- *
41
- * @slots
42
- *
43
- * | name | purpose | default value |
44
- * | ---------- | ------------------------------- | ------------- |
45
- * | `default` | content | `Content` |
46
- *
47
- * @events
48
- *
49
- * | name | event |
50
- * | --------- | ------------------ |
51
- * | `mount` | sheet is mounted |
52
- * | `destroy` | sheet is destroyed |
53
- *
54
- * @example
55
- *
56
- * ```svelte
57
- * <script lang="ts">
58
- * import { Sheet } from "drab";
59
- *
60
- * let display = false;
61
- * </script>
62
- *
63
- * <button
64
- * type="button"
65
- * class="button button-primary"
66
- * on:click={() => (display = true)}
67
- * >
68
- * Open
69
- * </button>
70
- *
71
- * <Sheet
72
- * bind:display
73
- * class="z-40 backdrop-blur"
74
- * classSheet="card rounded-none border-none"
75
- * position="r"
76
- * >
77
- * <div class="mb-4 flex items-center justify-between">
78
- * <h2 class="my-0">Sheet</h2>
79
- * <button
80
- * type="button"
81
- * class="button button-ghost"
82
- * on:click={() => (display = false)}
83
- * >
84
- * Close
85
- * </button>
86
- * </div>
87
- * <div>
88
- * Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
89
- * tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
90
- * quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
91
- * consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
92
- * cillum dolore eu fugiat nulla pariatur.
93
- * </div>
94
- * </Sheet>
95
- * ```
96
- */
97
- export default class Sheet extends SvelteComponent<SheetProps, SheetEvents, SheetSlots> {
98
- }
99
- export {};
@@ -1,173 +0,0 @@
1
- <!--
2
- @component
3
-
4
- ### Tablature
5
-
6
- A complementary component to the `FrettedChord` for displaying a measure of tablature for a fretted instrument like guitar or ukulele. Created with HTML elements so it is customizable and responsive to the size of the container.
7
-
8
- @props
9
-
10
- - `beats` - number of beats in the measure, defaults to `4`
11
- - `class`
12
- - `id`
13
- - `notes` - an array of notes
14
- - `repeatEnd` - puts a repeat at the end of the measure
15
- - `repeatStart` - puts a repeat at the start of the measure
16
- - `strings` - number of strings on the instrument, defaults to `6`
17
-
18
- @example
19
-
20
- ```svelte
21
- <script lang="ts">
22
- import { Tablature } from "drab";
23
- import type { ComponentProps } from "svelte";
24
-
25
- const notes: ComponentProps<Tablature>["notes"] = [
26
- {
27
- fret: 0,
28
- beat: 1,
29
- string: 1,
30
- },
31
- {
32
- fret: 1,
33
- beat: 2,
34
- string: 2,
35
- },
36
- {
37
- fret: "X",
38
- beat: 2,
39
- string: 3,
40
- },
41
- {
42
- fret: 2,
43
- beat: 3,
44
- string: 4,
45
- mod: "/3p2",
46
- },
47
- {
48
- fret: 7,
49
- beat: 4,
50
- string: 3,
51
- },
52
- ];
53
- </script>
54
-
55
- <div class="font-mono font-semibold">
56
- <div class="mb-8 h-24">
57
- <Tablature {notes} repeatStart />
58
- </div>
59
- <div class="h-16 text-sm">
60
- <Tablature {notes} strings={4} repeatEnd />
61
- </div>
62
- </div>
63
- ```
64
- -->
65
-
66
- <script>let className = "";
67
- export { className as class };
68
- export let id = "";
69
- export let strings = 6;
70
- export let beats = 4;
71
- export let repeatStart = false;
72
- export let repeatEnd = false;
73
- export let notes = [];
74
- const dotSize = 5;
75
- const dotXOffset = 9;
76
- const yOffset = (stringNumber) => {
77
- return 100 / strings * stringNumber + 100 / strings / 2;
78
- };
79
- const xOffset = (beat) => {
80
- return 100 / beats * beat - 100 / beats / 2;
81
- };
82
- const dotYOffset = () => {
83
- const stringPosition = strings < 5 ? 0.5 : 1.5;
84
- return yOffset(stringPosition) - dotSize / 2;
85
- };
86
- </script>
87
-
88
- <div
89
- class="measure {className}"
90
- {id}
91
- style:--top-offset="{yOffset(0)}%"
92
- style:--dot-size="{dotSize}%"
93
- >
94
- {#each Array.from({ length: strings }, (v, k) => k) as string}
95
- <div class="string" style:top="{yOffset(string)}%"></div>
96
- {/each}
97
- {#each notes as note}
98
- <div
99
- class="note"
100
- style:top="{yOffset(note.string - 1)}%"
101
- style:left="{xOffset(note.beat)}%"
102
- >
103
- <div style:display="flex">
104
- <span>{note.fret}</span>
105
- {#if note.mod}
106
- <span>{note.mod}</span>
107
- {/if}
108
- </div>
109
- </div>
110
- {/each}
111
- <div class="bar" style:left="0" style:width={repeatStart ? "3px" : ""}></div>
112
- <div class="bar" style:right="0" style:width={repeatEnd ? "3px" : ""}></div>
113
- {#if repeatStart}
114
- <div class="bar" style:left="5px"></div>
115
- <div
116
- class="dot"
117
- style:top="{dotYOffset()}%"
118
- style:left="{dotXOffset}px"
119
- ></div>
120
- <div
121
- class="dot"
122
- style:bottom="{dotYOffset()}%"
123
- style:left="{dotXOffset}px"
124
- ></div>
125
- {/if}
126
- {#if repeatEnd}
127
- <div class="bar" style:right="5px"></div>
128
- <div
129
- class="dot"
130
- style:top="{dotYOffset()}%"
131
- style:right="{dotXOffset}px"
132
- ></div>
133
- <div
134
- class="dot"
135
- style:bottom="{dotYOffset()}%"
136
- style:right="{dotXOffset}px"
137
- ></div>
138
- {/if}
139
- </div>
140
-
141
- <style>
142
- .measure {
143
- position: relative;
144
- width: 100%;
145
- height: 100%;
146
- }
147
- .note {
148
- position: absolute;
149
- line-height: 0;
150
- margin-left: -0.5ch;
151
- letter-spacing: 0.1em;
152
- }
153
- .string {
154
- position: absolute;
155
- opacity: 35%;
156
- width: 100%;
157
- border-top: 1px solid currentColor;
158
- }
159
- .bar {
160
- position: absolute;
161
- background-color: currentColor;
162
- width: 1.2px;
163
- top: var(--top-offset);
164
- bottom: calc(var(--top-offset) - 0.8px);
165
- }
166
- .dot {
167
- position: absolute;
168
- height: var(--dot-size);
169
- aspect-ratio: 1;
170
- background-color: currentColor;
171
- border-radius: 999px;
172
- }
173
- </style>