drab 3.0.2 → 3.0.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.
@@ -1,57 +1,57 @@
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 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
+
55
55
  <script>import { prefersReducedMotion } from "../util/accessibility";
56
56
  import { duration, start } from "../util/transition";
57
57
  import { onMount, tick } from "svelte";
@@ -66,33 +66,46 @@ export let transition = { duration, start };
66
66
  let popover;
67
67
  let coordinates = { x: 0, y: 0 };
68
68
  const setPosition = async () => {
69
- if (position === "t" || position === "b") {
70
- coordinates.x = target.offsetWidth / 2 - popover.offsetWidth / 2;
71
- if (position === "t") {
69
+ if (position.startsWith("t") || position.startsWith("b")) {
70
+ if (position.startsWith("t")) {
72
71
  coordinates.y = -popover.offsetHeight;
73
72
  } else {
74
73
  coordinates.y = target.offsetHeight;
75
74
  }
75
+ if (position.endsWith("l")) {
76
+ coordinates.x = 0;
77
+ } else if (position.endsWith("r")) {
78
+ coordinates.x = target.offsetWidth - popover.offsetWidth;
79
+ } else {
80
+ coordinates.x = target.offsetWidth / 2 - popover.offsetWidth / 2;
81
+ }
76
82
  } else {
77
- coordinates.y = target.offsetHeight / 2 - popover.offsetHeight / 2;
78
- if (position === "l") {
83
+ if (position.startsWith("l")) {
79
84
  coordinates.x = -popover.offsetWidth;
80
85
  } else {
81
86
  coordinates.x = target.offsetWidth;
82
87
  }
88
+ if (position.endsWith("t")) {
89
+ coordinates.y = 0;
90
+ } else if (position.endsWith("b")) {
91
+ coordinates.y = target.offsetHeight - popover.offsetHeight;
92
+ } else {
93
+ coordinates.y = target.offsetHeight / 2 - popover.offsetHeight / 2;
94
+ }
83
95
  }
84
96
  const targetRect = target.getBoundingClientRect();
85
97
  coordinates.x += targetRect.x + window.scrollX;
86
98
  coordinates.y += targetRect.y + window.scrollY;
87
99
  await tick();
88
100
  const popoverRect = popover.getBoundingClientRect();
89
- if (popoverRect.x < 0) {
90
- coordinates.x += Math.abs(popoverRect.x);
101
+ const extraMargin = 10;
102
+ if (popoverRect.x < extraMargin) {
103
+ coordinates.x += Math.abs(popoverRect.x) + extraMargin;
91
104
  } else if (popoverRect.x + popover.offsetWidth > window.innerWidth) {
92
- coordinates.x -= popoverRect.x + popover.offsetWidth - window.innerWidth + 16;
105
+ coordinates.x -= popoverRect.x + popover.offsetWidth - window.innerWidth + extraMargin;
93
106
  }
94
107
  if (popoverRect.y < 0) {
95
- coordinates.y += Math.abs(popoverRect.y);
108
+ coordinates.y += Math.abs(popoverRect.y) + extraMargin;
96
109
  } else if (popoverRect.y + popover.offsetHeight > window.innerHeight) {
97
110
  coordinates.y -= popoverRect.y + popover.offsetHeight - window.innerHeight;
98
111
  }
@@ -109,26 +122,27 @@ onMount(() => {
109
122
  if (prefersReducedMotion())
110
123
  transition = false;
111
124
  });
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>
125
+ </script>
126
+
127
+ <svelte:body on:keydown={onKeyDown} />
128
+
129
+ {#if display}
130
+ <div
131
+ role="dialog"
132
+ bind:this={popover}
133
+ class={className}
134
+ {id}
135
+ style:top="{coordinates.y}px"
136
+ style:left="{coordinates.x}px"
137
+ transition:scale={transition ? transition : { duration: 0 }}
138
+ >
139
+ <slot>Popover</slot>
140
+ </div>
141
+ {/if}
142
+
143
+ <style>
144
+ div {
145
+ position: absolute;
146
+ margin: 0;
147
+ }
148
+ </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
  *
@@ -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="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>
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}
@@ -1,70 +1,70 @@
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
- - `transitionSheet` - flies the sheet, set to `false` to remove
17
- - `transition` - blurs the entire component, set to `false` to remove
18
-
19
- @slots
20
-
21
- | name | purpose | default value |
22
- | ---------- | ------------------------------- | ------------- |
23
- | `default` | content | `Content` |
24
-
25
- @events
26
-
27
- | name | event |
28
- | --------- | ------------------ |
29
- | `mount` | sheet is mounted |
30
- | `destroy` | sheet is destroyed |
31
-
32
- @example
33
-
34
- ```svelte
35
- <script lang="ts">
36
- import { Sheet } from "drab";
37
-
38
- let display = false;
39
- </script>
40
-
41
- <button type="button" class="btn" on:click={() => (display = true)}>
42
- Open
43
- </button>
44
-
45
- <Sheet
46
- bind:display
47
- class="backdrop-blur"
48
- classSheet="p-4 shadow bg-white"
49
- position="r"
50
- >
51
- <div class="mb-4 flex items-center justify-between">
52
- <h2 class="my-0">Sheet</h2>
53
- <button type="button" class="btn btn-s" on:click={() => (display = false)}>
54
- Close
55
- </button>
56
- </div>
57
- <div>
58
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
59
- tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
60
- quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
61
- consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
62
- cillum dolore eu fugiat nulla pariatur.
63
- </div>
64
- </Sheet>
65
- ```
66
- -->
67
-
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
+ - `transitionSheet` - flies the sheet, set to `false` to remove
17
+ - `transition` - blurs the entire component, set to `false` to remove
18
+
19
+ @slots
20
+
21
+ | name | purpose | default value |
22
+ | ---------- | ------------------------------- | ------------- |
23
+ | `default` | content | `Content` |
24
+
25
+ @events
26
+
27
+ | name | event |
28
+ | --------- | ------------------ |
29
+ | `mount` | sheet is mounted |
30
+ | `destroy` | sheet is destroyed |
31
+
32
+ @example
33
+
34
+ ```svelte
35
+ <script lang="ts">
36
+ import { Sheet } from "drab";
37
+
38
+ let display = false;
39
+ </script>
40
+
41
+ <button type="button" class="btn" on:click={() => (display = true)}>
42
+ Open
43
+ </button>
44
+
45
+ <Sheet
46
+ bind:display
47
+ class="backdrop-blur"
48
+ classSheet="p-4 shadow bg-white"
49
+ position="r"
50
+ >
51
+ <div class="mb-4 flex items-center justify-between">
52
+ <h2 class="my-0">Sheet</h2>
53
+ <button type="button" class="btn btn-s" on:click={() => (display = false)}>
54
+ Close
55
+ </button>
56
+ </div>
57
+ <div>
58
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
59
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
60
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
61
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
62
+ cillum dolore eu fugiat nulla pariatur.
63
+ </div>
64
+ </Sheet>
65
+ ```
66
+ -->
67
+
68
68
  <script>import { createEventDispatcher, onMount } from "svelte";
69
69
  import {
70
70
  blur,
@@ -111,56 +111,56 @@ onMount(() => {
111
111
  transitionSheet = false;
112
112
  }
113
113
  });
114
- </script>
115
-
116
- <svelte:body on:keydown={onKeyDown} />
117
-
118
- {#if display}
119
- <div
120
- transition:blur={transition ? transition : { duration: 0 }}
121
- class="d-backdrop {className}"
122
- class:d-backdrop-bottom={position === "b"}
123
- class:d-backdrop-top={position === "t"}
124
- class:d-backdrop-right={position === "r"}
125
- {id}
126
- >
127
- <div
128
- bind:this={sheet}
129
- transition:fly={transitionSheet ? transitionSheet : { duration: 0 }}
130
- use:lifecycle
131
- role="dialog"
132
- tabindex="-1"
133
- style={position === "t" || position === "b"
134
- ? `max-height: ${maxSize}px;`
135
- : `max-width: ${maxSize}px`}
136
- class={classSheet}
137
- >
138
- <slot>Content</slot>
139
- </div>
140
- <button title="Close" on:click={close}></button>
141
- </div>
142
- {/if}
143
-
144
- <style>
145
- button {
146
- flex-grow: 1;
147
- }
148
- .d-backdrop {
149
- position: fixed;
150
- display: flex;
151
- top: 0;
152
- bottom: 0;
153
- left: 0;
154
- right: 0;
155
- overflow: hidden;
156
- }
157
- .d-backdrop-bottom {
158
- flex-direction: column-reverse;
159
- }
160
- .d-backdrop-top {
161
- flex-direction: column;
162
- }
163
- .d-backdrop-right {
164
- flex-direction: row-reverse;
165
- }
166
- </style>
114
+ </script>
115
+
116
+ <svelte:body on:keydown={onKeyDown} />
117
+
118
+ {#if display}
119
+ <div
120
+ transition:blur={transition ? transition : { duration: 0 }}
121
+ class="d-backdrop {className}"
122
+ class:d-backdrop-bottom={position === "b"}
123
+ class:d-backdrop-top={position === "t"}
124
+ class:d-backdrop-right={position === "r"}
125
+ {id}
126
+ >
127
+ <div
128
+ bind:this={sheet}
129
+ transition:fly={transitionSheet ? transitionSheet : { duration: 0 }}
130
+ use:lifecycle
131
+ role="dialog"
132
+ tabindex="-1"
133
+ style={position === "t" || position === "b"
134
+ ? `max-height: ${maxSize}px;`
135
+ : `max-width: ${maxSize}px`}
136
+ class={classSheet}
137
+ >
138
+ <slot>Content</slot>
139
+ </div>
140
+ <button title="Close" on:click={close}></button>
141
+ </div>
142
+ {/if}
143
+
144
+ <style>
145
+ button {
146
+ flex-grow: 1;
147
+ }
148
+ .d-backdrop {
149
+ position: fixed;
150
+ display: flex;
151
+ top: 0;
152
+ bottom: 0;
153
+ left: 0;
154
+ right: 0;
155
+ overflow: hidden;
156
+ }
157
+ .d-backdrop-bottom {
158
+ flex-direction: column-reverse;
159
+ }
160
+ .d-backdrop-top {
161
+ flex-direction: column;
162
+ }
163
+ .d-backdrop-right {
164
+ flex-direction: row-reverse;
165
+ }
166
+ </style>
@@ -7,7 +7,7 @@ declare const __propDef: {
7
7
  /** sheet class - not the backdrop */ classSheet?: string | undefined;
8
8
  /** controls whether the sheet is displayed*/ display?: boolean | undefined;
9
9
  /** blurs the entire component, set to `false` to remove */ transition?: false | BlurParams | undefined;
10
- /** determines the position of sheet */ position?: "t" | "b" | "l" | "r" | undefined;
10
+ /** determines the position of sheet */ position?: "t" | "r" | "b" | "l" | undefined;
11
11
  /** max width/height of sheet based on the `side` - can also use css instead */ maxSize?: number | undefined;
12
12
  /** flies the sheet, set to `false` to remove */ transitionSheet?: false | FlyParams | undefined;
13
13
  };