drab 2.0.0 → 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.
@@ -47,6 +47,8 @@ Generates a guitar chord `svg`.
47
47
  ```
48
48
  -->
49
49
 
50
+ <script context="module"></script>
51
+
50
52
  <script>let className = "";
51
53
  export { className as class };
52
54
  export let id = "";
@@ -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 position = { x: 0, y: 0 };
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 parent = contextMenu.parentElement;
51
- if (parent) {
52
- parent.addEventListener("contextmenu", async (e) => {
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
- position.x = e.clientX;
57
- position.y = e.clientY + scrollY;
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 (position.x + offsetWidth > innerWidth) {
65
- position.x = innerWidth - offsetWidth;
72
+ if (coordinates.x + offsetWidth > scrollX + innerWidth) {
73
+ coordinates.x = scrollX + innerWidth - offsetWidth;
66
74
  }
67
- if (position.y + offsetHeight > scrollY + innerHeight) {
68
- position.y = scrollY + innerHeight - offsetHeight;
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="display: {display
83
- ? 'block'
84
- : 'none'}; top: {position.y}px; left: {position.x}px;"
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>let className = "";
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
@@ -10,6 +10,7 @@ Data table to display an array of JS objects. Click a column header to sort.
10
10
  - `ascending` - default sort order
11
11
  - `classButton` - button class
12
12
  - `classFooter` - footer class
13
+ - `classNoscript` - noscript class
13
14
  - `classPageControls` - class of `div` that wraps the "Previous" and "Next" buttons
14
15
  - `classPageNumber` - class of `div` wrapping page numbers
15
16
  - `classTable` - table class
@@ -57,7 +58,9 @@ 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>export let data;
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]);
@@ -80,6 +83,8 @@ export let classPageNumber = "";
80
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,6 +122,7 @@ 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
128
  <table class={classTable} id={idTable}>
@@ -155,18 +161,24 @@ sort(sortBy, false);
155
161
  <div class={classPageControls}>
156
162
  <button
157
163
  class={classButton}
158
- disabled={currentPage < 2}
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
170
  class={classButton}
165
- disabled={currentPage >= numberOfPages}
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}
@@ -24,6 +24,7 @@ declare const __propDef: {
24
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>;
@@ -46,6 +47,7 @@ export type DataTableSlots = typeof __propDef.slots;
46
47
  * - `ascending` - default sort order
47
48
  * - `classButton` - button class
48
49
  * - `classFooter` - footer class
50
+ * - `classNoscript` - noscript class
49
51
  * - `classPageControls` - class of `div` that wraps the "Previous" and "Next" buttons
50
52
  * - `classPageNumber` - class of `div` wrapping page numbers
51
53
  * - `classTable` - table class
@@ -9,6 +9,7 @@ Text editor with controls to add elements and keyboard shortcuts.
9
9
 
10
10
  - `classButton` - `class` of all the `button` elements
11
11
  - `classControls` - `class` of the `div` that wraps the controls
12
+ - `classNoscript` - noscript class
12
13
  - `classTextarea` - `class` of the `textarea` element
13
14
  - `contentElements` - an array of content elements for the controls
14
15
  - `idControls` - `id` of the `div` that wraps the controls
@@ -55,7 +56,9 @@ Text editor with controls to add elements and keyboard shortcuts.
55
56
 
56
57
  <script context="module"></script>
57
58
 
58
- <script>export let contentElements = [];
59
+ <script>import { onMount } from "svelte";
60
+ import { messageNoScript } from "../util/messages";
61
+ export let contentElements = [];
59
62
  export let valueTextarea = "";
60
63
  export let placeholderTextarea = "";
61
64
  export let classTextarea = "";
@@ -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")
@@ -330,6 +335,7 @@ const correctFollowing = (currentLineNumber, decrement = false) => {
330
335
  }
331
336
  valueTextarea = lines.join("\n");
332
337
  };
338
+ onMount(() => clientJs = true);
333
339
  </script>
334
340
 
335
341
  <textarea
@@ -348,13 +354,14 @@ const correctFollowing = (currentLineNumber, decrement = false) => {
348
354
  }}
349
355
  on:input
350
356
  />
357
+
351
358
  <div id={idControls} class={classControls}>
352
359
  {#each contentElements as el}
353
360
  <button
354
361
  class={el.class ? `${classButton} ${el.class}` : classButton}
355
362
  on:click={() => addContent(el)}
356
363
  title={el.name}
357
- aria-label={el.name}
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,7 +18,7 @@ export interface EditorContentElement {
18
18
  /** class to apply to the specific button */
19
19
  class?: string;
20
20
  }
21
- import type { ComponentType } from "svelte";
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;
@@ -34,6 +34,7 @@ declare const __propDef: {
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;
@@ -54,6 +55,7 @@ export type EditorSlots = typeof __propDef.slots;
54
55
  *
55
56
  * - `classButton` - `class` of all the `button` elements
56
57
  * - `classControls` - `class` of the `div` that wraps the controls
58
+ * - `classNoscript` - noscript class
57
59
  * - `classTextarea` - `class` of the `textarea` element
58
60
  * - `contentElements` - an array of content elements for the controls
59
61
  * - `idControls` - `id` of the `div` that wraps the controls
@@ -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 name="disabled">Enable Fullscreen</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
- disabled: {};
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>let className = "";
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": "2.0.0",
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.4",
52
- "@sveltejs/package": "^2.2.0",
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.4.1",
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",