noph-ui 0.9.2 → 0.9.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.
- package/dist/menu/Menu.svelte +14 -41
- 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,9 +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:
|
|
120
|
-
margin-bottom: 2px;
|
|
121
|
-
margin-top: 2px;
|
|
110
|
+
margin: var(--np-menu-margin, 2px);
|
|
122
111
|
max-height: 80dvh;
|
|
123
112
|
scrollbar-color: var(--np-color-on-surface-variant) transparent;
|
|
124
113
|
scrollbar-width: thin;
|
|
@@ -126,19 +115,9 @@
|
|
|
126
115
|
display 0.2s allow-discrete,
|
|
127
116
|
opacity 0.2s linear;
|
|
128
117
|
opacity: 0;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
top: anchor(bottom);
|
|
133
|
-
left: anchor(left);
|
|
134
|
-
justify-self: anchor-center;
|
|
135
|
-
position-try-fallbacks: --menu-top-left;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
.bottom.np-menu[popover] {
|
|
139
|
-
top: anchor(bottom);
|
|
140
|
-
position-try-fallbacks: --menu-top;
|
|
141
|
-
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;
|
|
142
121
|
}
|
|
143
122
|
|
|
144
123
|
.np-menu:popover-open {
|
|
@@ -147,13 +126,7 @@
|
|
|
147
126
|
opacity: 0;
|
|
148
127
|
}
|
|
149
128
|
}
|
|
150
|
-
@position-try --menu-
|
|
151
|
-
|
|
152
|
-
bottom: anchor(top);
|
|
153
|
-
}
|
|
154
|
-
@position-try --menu-top-left {
|
|
155
|
-
inset: auto;
|
|
156
|
-
bottom: anchor(top);
|
|
157
|
-
left: anchor(left);
|
|
129
|
+
@position-try --np-menu-position-fallback {
|
|
130
|
+
position-area: var(--np-menu-position-area-fallback, top center);
|
|
158
131
|
}
|
|
159
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.ts'
|
|
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 {
|