noph-ui 0.9.3 → 0.9.5
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.
- package/dist/menu/Menu.svelte +14 -39
- package/dist/menu/types.d.ts +0 -1
- package/dist/select/Select.svelte +5 -2
- package/dist/tooltip/Tooltip.svelte +44 -36
- package/package.json +1 -1
package/dist/menu/Menu.svelte
CHANGED
|
@@ -8,7 +8,6 @@
|
|
|
8
8
|
element = $bindable(),
|
|
9
9
|
showPopover = $bindable(),
|
|
10
10
|
hidePopover = $bindable(),
|
|
11
|
-
position = 'bottom',
|
|
12
11
|
...attributes
|
|
13
12
|
}: MenuProps = $props()
|
|
14
13
|
|
|
@@ -16,9 +15,6 @@
|
|
|
16
15
|
let clientHeight = $state(0)
|
|
17
16
|
let innerHeight = $state(0)
|
|
18
17
|
let innerWidth = $state(0)
|
|
19
|
-
let scrollY = $state(0)
|
|
20
|
-
let scrollX = $state(0)
|
|
21
|
-
let anchorId = anchor?.style.getPropertyValue('anchor-name')
|
|
22
18
|
|
|
23
19
|
showPopover = () => {
|
|
24
20
|
element?.showPopover()
|
|
@@ -30,6 +26,7 @@
|
|
|
30
26
|
|
|
31
27
|
const refreshValues = () => {
|
|
32
28
|
if (element && anchor && !('anchorName' in document.documentElement.style)) {
|
|
29
|
+
const docClientWidth = document.documentElement.clientWidth
|
|
33
30
|
const anchorRect = anchor.getBoundingClientRect()
|
|
34
31
|
if (anchorRect.bottom + clientHeight > innerHeight && anchorRect.top - clientHeight > 0) {
|
|
35
32
|
element.style.top = `${anchorRect.top - clientHeight - 2}px`
|
|
@@ -37,10 +34,10 @@
|
|
|
37
34
|
element.style.top = `${anchorRect.bottom + 2}px`
|
|
38
35
|
}
|
|
39
36
|
const left = anchorRect.left + anchorRect.width / 2 - clientWidth / 2
|
|
40
|
-
if (left
|
|
41
|
-
element.style.left =
|
|
42
|
-
} else if (left
|
|
43
|
-
element.style.left =
|
|
37
|
+
if (left < 2) {
|
|
38
|
+
element.style.left = '2px'
|
|
39
|
+
} else if (left > docClientWidth - clientWidth) {
|
|
40
|
+
element.style.left = `${docClientWidth - clientWidth - 4}px`
|
|
44
41
|
} else {
|
|
45
42
|
element.style.left = `${anchorRect.left + anchorRect.width / 2 - clientWidth / 2}px`
|
|
46
43
|
}
|
|
@@ -78,7 +75,7 @@
|
|
|
78
75
|
},
|
|
79
76
|
{ passive: true },
|
|
80
77
|
)
|
|
81
|
-
} else if (!
|
|
78
|
+
} else if (!anchor.style.getPropertyValue('anchor-name')) {
|
|
82
79
|
const generatedId = `--${generateUUIDv4()}`
|
|
83
80
|
element.style.setProperty('position-anchor', generatedId)
|
|
84
81
|
anchor.style.setProperty('anchor-name', generatedId)
|
|
@@ -87,13 +84,7 @@
|
|
|
87
84
|
})
|
|
88
85
|
</script>
|
|
89
86
|
|
|
90
|
-
<svelte:window
|
|
91
|
-
bind:scrollX
|
|
92
|
-
bind:scrollY
|
|
93
|
-
bind:innerHeight
|
|
94
|
-
bind:innerWidth
|
|
95
|
-
onresize={refreshValues}
|
|
96
|
-
/>
|
|
87
|
+
<svelte:window bind:innerHeight onresize={refreshValues} />
|
|
97
88
|
|
|
98
89
|
<div
|
|
99
90
|
{...attributes}
|
|
@@ -101,7 +92,7 @@
|
|
|
101
92
|
bind:clientWidth
|
|
102
93
|
bind:clientHeight
|
|
103
94
|
popover="auto"
|
|
104
|
-
class={[
|
|
95
|
+
class={['np-menu', attributes.class]}
|
|
105
96
|
role="menu"
|
|
106
97
|
>
|
|
107
98
|
{@render children()}
|
|
@@ -116,7 +107,7 @@
|
|
|
116
107
|
border-radius: var(--np-menu-container-shape, var(--np-shape-corner-extra-small));
|
|
117
108
|
padding: 0.5rem 0;
|
|
118
109
|
box-shadow: var(--np-elevation-2);
|
|
119
|
-
margin: 2px;
|
|
110
|
+
margin: var(--np-menu-margin, 2px);
|
|
120
111
|
max-height: 80dvh;
|
|
121
112
|
scrollbar-color: var(--np-color-on-surface-variant) transparent;
|
|
122
113
|
scrollbar-width: thin;
|
|
@@ -124,19 +115,9 @@
|
|
|
124
115
|
display 0.2s allow-discrete,
|
|
125
116
|
opacity 0.2s linear;
|
|
126
117
|
opacity: 0;
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
top: anchor(bottom);
|
|
131
|
-
left: anchor(left);
|
|
132
|
-
justify-self: anchor-center;
|
|
133
|
-
position-try-fallbacks: --menu-top-left;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
.bottom.np-menu[popover] {
|
|
137
|
-
top: anchor(bottom);
|
|
138
|
-
position-try-fallbacks: --menu-top;
|
|
139
|
-
justify-self: anchor-center;
|
|
118
|
+
justify-self: var(--np-menu-justify-self, anchor-center);
|
|
119
|
+
position-area: var(--np-menu-position-area, bottom center);
|
|
120
|
+
position-try-fallbacks: --np-menu-position-fallback;
|
|
140
121
|
}
|
|
141
122
|
|
|
142
123
|
.np-menu:popover-open {
|
|
@@ -145,13 +126,7 @@
|
|
|
145
126
|
opacity: 0;
|
|
146
127
|
}
|
|
147
128
|
}
|
|
148
|
-
@position-try --menu-
|
|
149
|
-
|
|
150
|
-
bottom: anchor(top);
|
|
151
|
-
}
|
|
152
|
-
@position-try --menu-top-left {
|
|
153
|
-
inset: auto;
|
|
154
|
-
bottom: anchor(top);
|
|
155
|
-
left: anchor(left);
|
|
129
|
+
@position-try --np-menu-position-fallback {
|
|
130
|
+
position-area: var(--np-menu-position-area-fallback, top center);
|
|
156
131
|
}
|
|
157
132
|
</style>
|
package/dist/menu/types.d.ts
CHANGED
|
@@ -5,7 +5,6 @@ export interface MenuProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
5
5
|
anchor?: HTMLElement | undefined;
|
|
6
6
|
showPopover?: () => void;
|
|
7
7
|
hidePopover?: () => void;
|
|
8
|
-
position?: 'bottom-left' | 'bottom';
|
|
9
8
|
element?: HTMLDivElement;
|
|
10
9
|
}
|
|
11
10
|
interface ButtonProps extends HTMLButtonAttributes {
|
|
@@ -197,9 +197,12 @@
|
|
|
197
197
|
</div>
|
|
198
198
|
|
|
199
199
|
<Menu
|
|
200
|
-
style="position-anchor:{menuId};min-width:
|
|
200
|
+
style="position-anchor:{menuId};min-width: 300px;"
|
|
201
201
|
popover="manual"
|
|
202
|
-
|
|
202
|
+
--np-menu-justify-self="none"
|
|
203
|
+
--np-menu-position-area-fallback="top span-right"
|
|
204
|
+
--np-menu-position-area="bottom span-right"
|
|
205
|
+
--np-menu-margin="2px 0"
|
|
203
206
|
anchor={element}
|
|
204
207
|
ontoggle={({ newState }) => {
|
|
205
208
|
if (newState === 'open') {
|
|
@@ -1,51 +1,54 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { generateUUIDv4 } from '../utils.js'
|
|
2
3
|
import type { TooltipProps } from './types.ts'
|
|
3
4
|
|
|
4
5
|
let { children, element = $bindable(), id, ...attributes }: TooltipProps = $props()
|
|
5
6
|
let clientWidth = $state(0)
|
|
6
7
|
let clientHeight = $state(0)
|
|
7
8
|
let innerHeight = $state(0)
|
|
8
|
-
let innerWidth = $state(0)
|
|
9
9
|
let anchor: HTMLElement | undefined = $state()
|
|
10
|
-
let anchorRect: DOMRect | undefined = $state()
|
|
11
10
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (!anchorRect) {
|
|
30
|
-
return 0
|
|
11
|
+
const refreshValues = () => {
|
|
12
|
+
if (element && anchor && !('anchorName' in document.documentElement.style)) {
|
|
13
|
+
const docClientWidth = document.documentElement.clientWidth
|
|
14
|
+
const anchorRect = anchor.getBoundingClientRect()
|
|
15
|
+
if (anchorRect.bottom + clientHeight > innerHeight && anchorRect.top - clientHeight > 0) {
|
|
16
|
+
element.style.top = `${anchorRect.top - clientHeight - 8}px`
|
|
17
|
+
} else {
|
|
18
|
+
element.style.top = `${anchorRect.bottom}px`
|
|
19
|
+
}
|
|
20
|
+
const left = anchorRect.left + anchorRect.width / 2 - clientWidth / 2
|
|
21
|
+
if (left < 2) {
|
|
22
|
+
element.style.left = '2px'
|
|
23
|
+
} else if (left > docClientWidth - clientWidth) {
|
|
24
|
+
element.style.left = `${docClientWidth - clientWidth - 2}px`
|
|
25
|
+
} else {
|
|
26
|
+
element.style.left = `${anchorRect.left + anchorRect.width / 2 - clientWidth / 2}px`
|
|
27
|
+
}
|
|
31
28
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
return anchorRect.top - clientHeight - 4
|
|
35
|
-
}
|
|
36
|
-
return top
|
|
37
|
-
})
|
|
29
|
+
}
|
|
30
|
+
$effect(refreshValues)
|
|
38
31
|
let setAnchor = (document: Document) => {
|
|
39
32
|
anchor = (document.querySelector(`[aria-describedby="${id}"]`) as HTMLElement) ?? undefined
|
|
40
33
|
}
|
|
41
34
|
|
|
42
35
|
$effect(() => {
|
|
43
|
-
if (anchor) {
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
if (anchor && element) {
|
|
37
|
+
if ('anchorName' in document.documentElement.style) {
|
|
38
|
+
const anchorName = anchor.style.getPropertyValue('anchor-name')
|
|
39
|
+
const generatedId = anchorName || `--${generateUUIDv4()}`
|
|
40
|
+
element.style.setProperty('position-anchor', generatedId)
|
|
41
|
+
if (!anchorName) {
|
|
42
|
+
anchor.style.setProperty('anchor-name', generatedId)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
anchor.addEventListener('mouseenter', () => {
|
|
46
46
|
element?.showPopover()
|
|
47
47
|
})
|
|
48
|
-
anchor.addEventListener('
|
|
48
|
+
anchor.addEventListener('mouseleave', () => {
|
|
49
|
+
element?.hidePopover()
|
|
50
|
+
})
|
|
51
|
+
anchor.addEventListener('click', () => {
|
|
49
52
|
element?.hidePopover()
|
|
50
53
|
})
|
|
51
54
|
}
|
|
@@ -53,13 +56,12 @@
|
|
|
53
56
|
</script>
|
|
54
57
|
|
|
55
58
|
<svelte:document use:setAnchor />
|
|
56
|
-
<svelte:window bind:innerHeight
|
|
59
|
+
<svelte:window bind:innerHeight />
|
|
57
60
|
|
|
58
61
|
<div
|
|
59
62
|
{...attributes}
|
|
60
63
|
{id}
|
|
61
64
|
class={['np-tooltip', attributes.class]}
|
|
62
|
-
style="top:{calculateTopPos}px;left:{calculateLeftPos}px;{attributes.style}"
|
|
63
65
|
role="tooltip"
|
|
64
66
|
popover="manual"
|
|
65
67
|
bind:this={element}
|
|
@@ -70,25 +72,31 @@
|
|
|
70
72
|
</div>
|
|
71
73
|
|
|
72
74
|
<style>
|
|
73
|
-
.np-tooltip {
|
|
75
|
+
.np-tooltip[popover] {
|
|
74
76
|
width: max-content;
|
|
75
|
-
margin: 0;
|
|
77
|
+
margin: 4px 0;
|
|
76
78
|
background: var(--np-color-inverse-surface);
|
|
77
79
|
color: var(--np-color-inverse-on-surface);
|
|
78
80
|
padding: 0.25rem 0.5rem;
|
|
81
|
+
border: none;
|
|
79
82
|
border-radius: 0.25rem;
|
|
80
83
|
line-height: 1rem;
|
|
81
84
|
font-size: 0.75rem;
|
|
82
85
|
opacity: 0;
|
|
83
86
|
transition:
|
|
84
|
-
overlay 0.3s allow-discrete,
|
|
85
87
|
display 0.3s allow-discrete,
|
|
86
88
|
opacity 0.3s ease;
|
|
89
|
+
justify-self: var(--np-tooltip-justify-self, anchor-center);
|
|
90
|
+
position-area: var(--np-tooltip-position-area, top);
|
|
91
|
+
position-try-fallbacks: --np-tooltip-position-fallback;
|
|
87
92
|
}
|
|
88
93
|
.np-tooltip:popover-open {
|
|
89
94
|
opacity: 1;
|
|
90
95
|
animation: scaleIn 0.3s ease;
|
|
91
96
|
}
|
|
97
|
+
@position-try --np-tooltip-position-fallback {
|
|
98
|
+
position-area: var(--np-tooltip-position-area-fallback, bottom);
|
|
99
|
+
}
|
|
92
100
|
|
|
93
101
|
@keyframes scaleIn {
|
|
94
102
|
from {
|