drab 3.0.2 → 3.0.4

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,11 +47,11 @@ export type FullscreenButtonSlots = typeof __propDef.slots;
47
47
  * let target: HTMLDivElement;
48
48
  * </script>
49
49
  *
50
- * <FullscreenButton class="btn" />
50
+ * <FullscreenButton class="button button-primary" />
51
51
  *
52
- * <div bind:this={target} class="mt-8 rounded bg-neutral-800 p-4 text-neutral-50">
52
+ * <div bind:this={target} class="mt-8 rounded border bg-muted p-4">
53
53
  * <div class="mb-2">Target element</div>
54
- * <FullscreenButton {target} class="btn btn-s bg-neutral-50">
54
+ * <FullscreenButton {target} class="button button-primary">
55
55
  * Enable Element Fullscreen
56
56
  * </FullscreenButton>
57
57
  * </div>
@@ -1,57 +1,62 @@
1
- <!--
2
- @component
3
-
4
- ### Popover
5
-
6
- Displays a popover in relation to the `target`.
7
-
8
- - Does not require the target to be `position: relative;`
9
- - Adjusts position in case the popover renders outside of the viewport
10
-
11
- @props
12
-
13
- - `class`
14
- - `display` - shows / hides the popover
15
- - `id`
16
- - `position` - where the popover is displayed in relation to the `target`
17
- - `target` - target element to position the popover in relation to
18
- - `transition` - scales the popover, set to `false` to disable
19
-
20
- @slots
21
-
22
- | name | purpose | default value |
23
- | ---------- | ------------------------------- | ------------- |
24
- | `default` | default | Popover |
25
-
26
- @example
27
-
28
- ```svelte
29
- <script lang="ts">
30
- import { Popover } from "drab";
31
-
32
- let target: HTMLButtonElement;
33
-
34
- let display = false;
35
-
36
- const open = () => (display = true);
37
- const close = () => (display = false);
38
- </script>
39
-
40
- <button class="btn" type="button" bind:this={target} on:click={open}>
41
- Open
42
- </button>
43
-
44
- <Popover {target} bind:display class="p-2">
45
- <div class="flex w-48 flex-col gap-2 rounded border bg-white p-2 shadow">
46
- <div class="font-bold">Bottom</div>
47
- <button class="btn" on:click={close}>Close</button>
48
- <button class="btn" on:click={close}>Close</button>
49
- <button class="btn" on:click={close}>Close</button>
50
- </div>
51
- </Popover>
52
- ```
53
- -->
54
-
1
+ <!--
2
+ @component
3
+
4
+ ### Popover
5
+
6
+ Displays a popover in relation to the `target`.
7
+
8
+ - Does not require the target to be `position: relative;`
9
+ - Adjusts position in case the popover renders outside of the viewport
10
+
11
+ @props
12
+
13
+ - `class`
14
+ - `display` - shows / hides the popover
15
+ - `id`
16
+ - `position` - where the popover is displayed in relation to the `target`, ex: `br` is bottom, right aligned
17
+ - `target` - target element to position the popover in relation to
18
+ - `transition` - scales the popover, set to `false` to disable
19
+
20
+ @slots
21
+
22
+ | name | purpose | default value |
23
+ | ---------- | ------------------------------- | ------------- |
24
+ | `default` | default | Popover |
25
+
26
+ @example
27
+
28
+ ```svelte
29
+ <script lang="ts">
30
+ import { Popover } from "drab";
31
+
32
+ let target: HTMLButtonElement;
33
+
34
+ let display = false;
35
+
36
+ const open = () => (display = true);
37
+ const close = () => (display = false);
38
+ </script>
39
+
40
+ <button
41
+ class="button button-primary"
42
+ type="button"
43
+ bind:this={target}
44
+ on:click={open}
45
+ >
46
+ Open
47
+ </button>
48
+
49
+ <Popover {target} bind:display class="p-2">
50
+ <div class="flex w-48 flex-col gap-2 rounded border bg-background p-2 shadow">
51
+ <div class="font-bold">Bottom</div>
52
+ <button class="button button-secondary" on:click={close}>Close</button>
53
+ <button class="button button-secondary" on:click={close}>Close</button>
54
+ <button class="button button-secondary" on:click={close}>Close</button>
55
+ </div>
56
+ </Popover>
57
+ ```
58
+ -->
59
+
55
60
  <script>import { prefersReducedMotion } from "../util/accessibility";
56
61
  import { duration, start } from "../util/transition";
57
62
  import { onMount, tick } from "svelte";
@@ -66,33 +71,46 @@ export let transition = { duration, start };
66
71
  let popover;
67
72
  let coordinates = { x: 0, y: 0 };
68
73
  const setPosition = async () => {
69
- if (position === "t" || position === "b") {
70
- coordinates.x = target.offsetWidth / 2 - popover.offsetWidth / 2;
71
- if (position === "t") {
74
+ if (position.startsWith("t") || position.startsWith("b")) {
75
+ if (position.startsWith("t")) {
72
76
  coordinates.y = -popover.offsetHeight;
73
77
  } else {
74
78
  coordinates.y = target.offsetHeight;
75
79
  }
80
+ if (position.endsWith("l")) {
81
+ coordinates.x = 0;
82
+ } else if (position.endsWith("r")) {
83
+ coordinates.x = target.offsetWidth - popover.offsetWidth;
84
+ } else {
85
+ coordinates.x = target.offsetWidth / 2 - popover.offsetWidth / 2;
86
+ }
76
87
  } else {
77
- coordinates.y = target.offsetHeight / 2 - popover.offsetHeight / 2;
78
- if (position === "l") {
88
+ if (position.startsWith("l")) {
79
89
  coordinates.x = -popover.offsetWidth;
80
90
  } else {
81
91
  coordinates.x = target.offsetWidth;
82
92
  }
93
+ if (position.endsWith("t")) {
94
+ coordinates.y = 0;
95
+ } else if (position.endsWith("b")) {
96
+ coordinates.y = target.offsetHeight - popover.offsetHeight;
97
+ } else {
98
+ coordinates.y = target.offsetHeight / 2 - popover.offsetHeight / 2;
99
+ }
83
100
  }
84
101
  const targetRect = target.getBoundingClientRect();
85
102
  coordinates.x += targetRect.x + window.scrollX;
86
103
  coordinates.y += targetRect.y + window.scrollY;
87
104
  await tick();
88
105
  const popoverRect = popover.getBoundingClientRect();
89
- if (popoverRect.x < 0) {
90
- coordinates.x += Math.abs(popoverRect.x);
106
+ const extraMargin = 10;
107
+ if (popoverRect.x < extraMargin) {
108
+ coordinates.x += Math.abs(popoverRect.x) + extraMargin;
91
109
  } else if (popoverRect.x + popover.offsetWidth > window.innerWidth) {
92
- coordinates.x -= popoverRect.x + popover.offsetWidth - window.innerWidth + 16;
110
+ coordinates.x -= popoverRect.x + popover.offsetWidth - window.innerWidth + extraMargin;
93
111
  }
94
112
  if (popoverRect.y < 0) {
95
- coordinates.y += Math.abs(popoverRect.y);
113
+ coordinates.y += Math.abs(popoverRect.y) + extraMargin;
96
114
  } else if (popoverRect.y + popover.offsetHeight > window.innerHeight) {
97
115
  coordinates.y -= popoverRect.y + popover.offsetHeight - window.innerHeight;
98
116
  }
@@ -109,26 +127,27 @@ onMount(() => {
109
127
  if (prefersReducedMotion())
110
128
  transition = false;
111
129
  });
112
- </script>
113
-
114
- <svelte:body on:keydown={onKeyDown} />
115
-
116
- {#if display}
117
- <div
118
- role="dialog"
119
- bind:this={popover}
120
- class={className}
121
- {id}
122
- style:top="{coordinates.y}px"
123
- style:left="{coordinates.x}px"
124
- transition:scale={transition ? transition : { duration: 0 }}
125
- >
126
- <slot>Popover</slot>
127
- </div>
128
- {/if}
129
-
130
- <style>
131
- div {
132
- position: absolute;
133
- }
134
- </style>
130
+ </script>
131
+
132
+ <svelte:body on:keydown={onKeyDown} />
133
+
134
+ {#if display}
135
+ <div
136
+ role="dialog"
137
+ bind:this={popover}
138
+ class={className}
139
+ {id}
140
+ style:top="{coordinates.y}px"
141
+ style:left="{coordinates.x}px"
142
+ transition:scale={transition ? transition : { duration: 0 }}
143
+ >
144
+ <slot>Popover</slot>
145
+ </div>
146
+ {/if}
147
+
148
+ <style>
149
+ div {
150
+ position: absolute;
151
+ margin: 0;
152
+ }
153
+ </style>
@@ -5,7 +5,7 @@ declare const __propDef: {
5
5
  class?: string | undefined;
6
6
  id?: string | undefined;
7
7
  /** shows / hides the popover */ display?: boolean | undefined;
8
- /** where the popover is displayed in relation to the `target` */ position?: "t" | "b" | "l" | "r" | undefined;
8
+ /** where the popover is displayed in relation to the `target`, ex: `br` is bottom, right aligned */ position?: ("tr" | "tl" | "t" | "rt" | "r" | "rb" | "br" | "b" | "bl" | "lb" | "l" | "lt") | undefined;
9
9
  /** target element to position the popover in relation to */ target: HTMLElement;
10
10
  /** scales the popover, set to `false` to disable */ transition?: false | ScaleParams | undefined;
11
11
  };
@@ -32,7 +32,7 @@ export type PopoverSlots = typeof __propDef.slots;
32
32
  * - `class`
33
33
  * - `display` - shows / hides the popover
34
34
  * - `id`
35
- * - `position` - where the popover is displayed in relation to the `target`
35
+ * - `position` - where the popover is displayed in relation to the `target`, ex: `br` is bottom, right aligned
36
36
  * - `target` - target element to position the popover in relation to
37
37
  * - `transition` - scales the popover, set to `false` to disable
38
38
  *
@@ -56,16 +56,21 @@ export type PopoverSlots = typeof __propDef.slots;
56
56
  * const close = () => (display = false);
57
57
  * </script>
58
58
  *
59
- * <button class="btn" type="button" bind:this={target} on:click={open}>
59
+ * <button
60
+ * class="button button-primary"
61
+ * type="button"
62
+ * bind:this={target}
63
+ * on:click={open}
64
+ * >
60
65
  * Open
61
66
  * </button>
62
67
  *
63
68
  * <Popover {target} bind:display class="p-2">
64
- * <div class="flex w-48 flex-col gap-2 rounded border bg-white p-2 shadow">
69
+ * <div class="flex w-48 flex-col gap-2 rounded border bg-background p-2 shadow">
65
70
  * <div class="font-bold">Bottom</div>
66
- * <button class="btn" on:click={close}>Close</button>
67
- * <button class="btn" on:click={close}>Close</button>
68
- * <button class="btn" on:click={close}>Close</button>
71
+ * <button class="button button-secondary" on:click={close}>Close</button>
72
+ * <button class="button button-secondary" on:click={close}>Close</button>
73
+ * <button class="button button-secondary" on:click={close}>Close</button>
69
74
  * </div>
70
75
  * </Popover>
71
76
  * ```
@@ -1,18 +1,18 @@
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
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
16
 
17
17
  - `classNoscript` - `noscript` class
18
18
  - `class`
@@ -20,57 +20,57 @@ Uses the [Navigator API](https://developer.mozilla.org/en-US/docs/Web/API/Naviga
20
20
  - `shareData` - [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/share)
21
21
  - `title`
22
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
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
31
 
32
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="btn 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="btn" bind:shareData={fileShareData}>
68
- Share File
69
- </ShareButton>
70
- </div>
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
71
  ```
72
- -->
73
-
72
+ -->
73
+
74
74
  <script>import { onMount } from "svelte";
75
75
  import { delay } from "../util/delay";
76
76
  let className = "";
@@ -107,25 +107,25 @@ const onClick = async () => {
107
107
  }
108
108
  };
109
109
  onMount(() => clientJs = true);
110
- </script>
111
-
112
- <button
113
- type="button"
114
- disabled={!clientJs || (!shareData.url && !shareData.files)}
115
- on:click={onClick}
116
- class={className}
117
- {id}
118
- {title}
119
- >
120
- {#if complete}
121
- <slot name="complete">Copied</slot>
122
- {:else}
123
- <slot>Share</slot>
124
- {/if}
125
- </button>
126
-
127
- <a href="/" bind:this={downloadAnchor} style:display="none">Download</a>
128
-
129
- {#if shareData.url}
130
- <noscript><span class={classNoscript}>{shareData.url}</span></noscript>
131
- {/if}
110
+ </script>
111
+
112
+ <button
113
+ type="button"
114
+ disabled={!clientJs || (!shareData.url && !shareData.files)}
115
+ on:click={onClick}
116
+ class={className}
117
+ {id}
118
+ {title}
119
+ >
120
+ {#if complete}
121
+ <slot name="complete">Copied</slot>
122
+ {:else}
123
+ <slot>Share</slot>
124
+ {/if}
125
+ </button>
126
+
127
+ <a href="/" bind:this={downloadAnchor} style:display="none">Download</a>
128
+
129
+ {#if shareData.url}
130
+ <noscript><span class={classNoscript}>{shareData.url}</span></noscript>
131
+ {/if}
@@ -63,7 +63,7 @@ export type ShareButtonSlots = typeof __propDef.slots;
63
63
  * </script>
64
64
  *
65
65
  * <ShareButton
66
- * class="btn mb-8"
66
+ * class="button button-primary mb-8"
67
67
  * shareData={{
68
68
  * text: "Check out this page: ",
69
69
  * title: "drab",
@@ -82,7 +82,7 @@ export type ShareButtonSlots = typeof __propDef.slots;
82
82
  * bind:this={fileInput}
83
83
  * on:input={onInput}
84
84
  * />
85
- * <ShareButton class="btn" bind:shareData={fileShareData}>
85
+ * <ShareButton class="button button-primary" bind:shareData={fileShareData}>
86
86
  * Share File
87
87
  * </ShareButton>
88
88
  * </div>