@x33025/sveltely 0.0.12 → 0.0.13

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.
@@ -7,6 +7,7 @@
7
7
  children: Snippet;
8
8
  class?: string;
9
9
  align?: 'left' | 'right';
10
+ anchor?: 'top' | 'bottom' | 'leading' | 'trailing';
10
11
  closeOnSelect?: boolean;
11
12
  }
12
13
 
@@ -15,21 +16,51 @@
15
16
  children,
16
17
  class: className = '',
17
18
  align = 'left',
19
+ anchor = 'bottom',
18
20
  closeOnSelect = true
19
21
  }: Props = $props();
20
22
 
21
23
  let isOpen = $state(false);
22
24
  let triggerEl = $state<HTMLElement | null>(null);
23
- let menuCoords = $state({ top: 0, left: 0, width: 0 });
25
+ let menuCoords = $state({ top: 0, left: 0 });
26
+ let menuTransform = $state('none');
24
27
 
25
28
  function open() {
26
29
  if (triggerEl) {
27
30
  const rect = triggerEl.getBoundingClientRect();
28
- menuCoords = {
29
- top: rect.bottom + window.scrollY,
30
- left: align === 'left' ? rect.left + window.scrollX : rect.right + window.scrollX,
31
- width: rect.width
32
- };
31
+ const spaceAbove = rect.top;
32
+ const spaceBelow = window.innerHeight - rect.bottom;
33
+ const spaceLeft = rect.left;
34
+ const spaceRight = window.innerWidth - rect.right;
35
+ let resolvedAnchor = anchor;
36
+
37
+ if (anchor === 'bottom' && spaceBelow < spaceAbove) {
38
+ resolvedAnchor = 'top';
39
+ } else if (anchor === 'top' && spaceAbove < spaceBelow) {
40
+ resolvedAnchor = 'bottom';
41
+ } else if (anchor === 'leading' && spaceLeft < spaceRight) {
42
+ resolvedAnchor = 'trailing';
43
+ } else if (anchor === 'trailing' && spaceRight < spaceLeft) {
44
+ resolvedAnchor = 'leading';
45
+ }
46
+
47
+ if (resolvedAnchor === 'top' || resolvedAnchor === 'bottom') {
48
+ const left = align === 'left' ? rect.left + window.scrollX : rect.right + window.scrollX;
49
+ const top =
50
+ resolvedAnchor === 'bottom' ? rect.bottom + window.scrollY : rect.top + window.scrollY;
51
+ menuCoords = { top, left };
52
+ if (resolvedAnchor === 'top' && align === 'right')
53
+ menuTransform = 'translate(-100%, -100%)';
54
+ else if (resolvedAnchor === 'top') menuTransform = 'translateY(-100%)';
55
+ else if (align === 'right') menuTransform = 'translateX(-100%)';
56
+ else menuTransform = 'none';
57
+ } else if (resolvedAnchor === 'leading') {
58
+ menuCoords = { top: rect.top + window.scrollY, left: rect.left + window.scrollX };
59
+ menuTransform = 'translateX(-100%)';
60
+ } else {
61
+ menuCoords = { top: rect.top + window.scrollY, left: rect.right + window.scrollX };
62
+ menuTransform = 'none';
63
+ }
33
64
  }
34
65
  isOpen = true;
35
66
  }
@@ -71,9 +102,7 @@
71
102
  <div
72
103
  use:portal
73
104
  class="dropdown-menu fixed z-50 border border-gray-200 focus:outline-none"
74
- style="top: {menuCoords.top}px; {align === 'left'
75
- ? `left: ${menuCoords.left}px;`
76
- : `right: ${window.innerWidth - menuCoords.left}px;`}; border-radius: var(--dropdown-border-radius); background: var(--dropdown-background); box-shadow: var(--dropdown-shadow);"
105
+ style="top: {menuCoords.top}px; left: {menuCoords.left}px; transform: {menuTransform}; border-radius: var(--dropdown-border-radius); background: var(--dropdown-background); box-shadow: var(--dropdown-shadow);"
77
106
  role="menu"
78
107
  aria-orientation="vertical"
79
108
  tabindex="-1"
@@ -4,6 +4,7 @@ interface Props {
4
4
  children: Snippet;
5
5
  class?: string;
6
6
  align?: 'left' | 'right';
7
+ anchor?: 'top' | 'bottom' | 'leading' | 'trailing';
7
8
  closeOnSelect?: boolean;
8
9
  }
9
10
  declare const Dropdown: import("svelte").Component<Props, {}, "">;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x33025/sveltely",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && npm run prepack",