noph-ui 0.12.7 → 0.12.9

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.
@@ -13,6 +13,7 @@
13
13
  let clientWidth = $state(0)
14
14
  let clientHeight = $state(0)
15
15
  let innerHeight = $state(0)
16
+ let menuOpen = $state(false)
16
17
 
17
18
  showPopover = () => {
18
19
  element?.showPopover()
@@ -23,7 +24,7 @@
23
24
  }
24
25
 
25
26
  const refreshValues = () => {
26
- if (element && anchor) {
27
+ if (element && anchor && menuOpen) {
27
28
  const anchorRect = anchor.getBoundingClientRect()
28
29
  let maxHeight: number
29
30
  if (innerHeight - anchorRect.bottom > anchorRect.top) {
@@ -33,8 +34,8 @@
33
34
  }
34
35
  element.style.maxHeight =
35
36
  maxHeight > innerHeight - anchorRect.height
36
- ? `${innerHeight - anchorRect.height - 20}px`
37
- : `${maxHeight - 20}px`
37
+ ? `${innerHeight - anchorRect.height - 4}px`
38
+ : `${maxHeight - 4}px`
38
39
  if (!('anchorName' in document.documentElement.style)) {
39
40
  const docClientWidth = document.documentElement.clientWidth
40
41
  if (anchorRect.bottom + clientHeight > innerHeight && anchorRect.top - clientHeight > 0) {
@@ -55,20 +56,41 @@
55
56
  }
56
57
  $effect(refreshValues)
57
58
 
59
+ const getScrollableParent = (start: HTMLElement) => {
60
+ let element: HTMLElement | null = start
61
+ while (element) {
62
+ const style = getComputedStyle(element)
63
+ const overflowY = style.overflowY
64
+ const overflowX = style.overflowX
65
+ const isScrollableY =
66
+ (overflowY === 'auto' || overflowY === 'scroll') &&
67
+ element.scrollHeight > element.clientHeight
68
+ const isScrollableX =
69
+ (overflowX === 'auto' || overflowX === 'scroll') &&
70
+ element.scrollWidth > element.clientWidth
71
+
72
+ if (isScrollableY || isScrollableX) {
73
+ return element
74
+ }
75
+
76
+ element = element.parentElement
77
+ }
78
+ return window
79
+ }
80
+
58
81
  $effect(() => {
59
82
  if (anchor && element) {
60
- window.addEventListener(
83
+ getScrollableParent(element).addEventListener(
61
84
  'scroll',
62
85
  () => {
63
86
  refreshValues()
64
87
  },
65
88
  { passive: true },
66
89
  )
67
- if (!('anchorName' in document.documentElement.style)) {
68
- anchor.addEventListener('click', () => {
69
- refreshValues()
70
- })
71
- } else if (!anchor.style.getPropertyValue('anchor-name')) {
90
+ if (
91
+ 'anchorName' in document.documentElement.style &&
92
+ !anchor.style.getPropertyValue('anchor-name')
93
+ ) {
72
94
  const generatedId = `--${crypto.randomUUID()}`
73
95
  element.style.setProperty('position-anchor', generatedId)
74
96
  anchor.style.setProperty('anchor-name', generatedId)
@@ -83,26 +105,37 @@
83
105
  bind:this={element}
84
106
  bind:clientWidth
85
107
  bind:clientHeight
108
+ ontoggle={(event) => {
109
+ let { newState } = event
110
+ menuOpen = newState === 'open'
111
+ }}
86
112
  popover="auto"
87
- class={['np-menu', attributes.class]}
113
+ class={['np-menu-container', attributes.class]}
88
114
  role="menu"
89
115
  >
90
- {@render children()}
116
+ <div class="np-menu">
117
+ {@render children()}
118
+ </div>
91
119
  </div>
92
120
 
93
121
  <style>
94
- .np-menu[popover] {
122
+ .np-menu {
123
+ overflow-y: auto;
124
+ overflow-x: hidden;
125
+ flex: 1;
126
+ padding: 0.5rem 0;
127
+ scrollbar-color: var(--np-color-on-surface-variant) transparent;
128
+ scrollbar-width: thin;
129
+ }
130
+ .np-menu-container[popover] {
95
131
  color: var(--np-menu-text-color, var(--np-color-on-surface));
96
132
  background-color: var(--np-menu-container-color, var(--np-color-surface-container));
97
- overflow-y: auto;
98
133
  border: none;
99
134
  border-radius: var(--np-menu-container-shape, var(--np-shape-corner-extra-small));
100
- padding: 0.5rem 0;
135
+ padding: 0;
101
136
  box-shadow: var(--np-elevation-2);
102
137
  margin: var(--np-menu-margin, 2px);
103
138
  inset: auto;
104
- scrollbar-color: var(--np-color-on-surface-variant) transparent;
105
- scrollbar-width: thin;
106
139
  transition:
107
140
  display 0.2s allow-discrete,
108
141
  opacity 0.2s linear;
@@ -112,8 +145,9 @@
112
145
  position-try: most-height flip-block;
113
146
  }
114
147
 
115
- .np-menu:popover-open {
148
+ .np-menu-container:popover-open {
116
149
  opacity: 1;
150
+ display: flex;
117
151
  @starting-style {
118
152
  opacity: 0;
119
153
  }
@@ -202,7 +202,6 @@
202
202
  style="position-anchor:{menuId};min-width:{clientWidth}px;"
203
203
  popover="manual"
204
204
  --np-menu-justify-self="none"
205
- --np-menu-position-area-fallback="top span-right"
206
205
  --np-menu-position-area="bottom span-right"
207
206
  --np-menu-margin="2px 0"
208
207
  --np-menu-container-shape={variant === 'outlined'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noph-ui",
3
- "version": "0.12.7",
3
+ "version": "0.12.9",
4
4
  "license": "MIT",
5
5
  "homepage": "https://noph.dev",
6
6
  "repository": {