noph-ui 0.12.6 → 0.12.8

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.
@@ -23,40 +23,76 @@
23
23
  }
24
24
 
25
25
  const refreshValues = () => {
26
- if (element && anchor && !('anchorName' in document.documentElement.style)) {
27
- const docClientWidth = document.documentElement.clientWidth
26
+ if (element && anchor) {
28
27
  const anchorRect = anchor.getBoundingClientRect()
29
- if (anchorRect.bottom + clientHeight > innerHeight && anchorRect.top - clientHeight > 0) {
30
- element.style.top = `${anchorRect.top - clientHeight - 2}px`
28
+ let maxHeight: number
29
+ if (innerHeight - anchorRect.bottom > anchorRect.top) {
30
+ maxHeight = innerHeight - anchorRect.bottom
31
31
  } else {
32
- element.style.top = `${anchorRect.bottom + 2}px`
32
+ maxHeight = anchorRect.top
33
33
  }
34
- const left = anchorRect.left + anchorRect.width / 2 - clientWidth / 2
35
- if (left < 2) {
36
- element.style.left = '2px'
37
- } else if (left > docClientWidth - clientWidth) {
38
- element.style.left = `${docClientWidth - clientWidth - 4}px`
39
- } else {
40
- element.style.left = `${anchorRect.left + anchorRect.width / 2 - clientWidth / 2}px`
34
+ element.style.maxHeight =
35
+ maxHeight > innerHeight - anchorRect.height
36
+ ? `${innerHeight - anchorRect.height - 20}px`
37
+ : `${maxHeight - 20}px`
38
+ if (!('anchorName' in document.documentElement.style)) {
39
+ const docClientWidth = document.documentElement.clientWidth
40
+ if (anchorRect.bottom + clientHeight > innerHeight && anchorRect.top - clientHeight > 0) {
41
+ element.style.top = `${anchorRect.top - clientHeight - 2}px`
42
+ } else {
43
+ element.style.top = `${anchorRect.bottom + 2}px`
44
+ }
45
+ const left = anchorRect.left + anchorRect.width / 2 - clientWidth / 2
46
+ if (left < 2) {
47
+ element.style.left = '2px'
48
+ } else if (left > docClientWidth - clientWidth) {
49
+ element.style.left = `${docClientWidth - clientWidth - 4}px`
50
+ } else {
51
+ element.style.left = `${anchorRect.left + anchorRect.width / 2 - clientWidth / 2}px`
52
+ }
41
53
  }
42
54
  }
43
55
  }
44
56
  $effect(refreshValues)
45
57
 
58
+ const getScrollableParent = (start: HTMLElement) => {
59
+ let element: HTMLElement | null = start
60
+ while (element) {
61
+ const style = getComputedStyle(element)
62
+ const overflowY = style.overflowY
63
+ const overflowX = style.overflowX
64
+ const isScrollableY =
65
+ (overflowY === 'auto' || overflowY === 'scroll') &&
66
+ element.scrollHeight > element.clientHeight
67
+ const isScrollableX =
68
+ (overflowX === 'auto' || overflowX === 'scroll') &&
69
+ element.scrollWidth > element.clientWidth
70
+
71
+ if (isScrollableY || isScrollableX) {
72
+ return element
73
+ }
74
+
75
+ element = element.parentElement
76
+ }
77
+ return window
78
+ }
79
+
46
80
  $effect(() => {
47
81
  if (anchor && element) {
48
- if (!('anchorName' in document.documentElement.style)) {
49
- anchor.addEventListener('click', () => {
82
+ getScrollableParent(element).addEventListener(
83
+ 'scroll',
84
+ () => {
50
85
  refreshValues()
51
- })
52
- window.addEventListener(
53
- 'scroll',
54
- () => {
55
- refreshValues()
56
- },
57
- { passive: true },
58
- )
59
- } else if (!anchor.style.getPropertyValue('anchor-name')) {
86
+ },
87
+ { passive: true },
88
+ )
89
+ anchor.addEventListener('click', () => {
90
+ refreshValues()
91
+ })
92
+ if (
93
+ 'anchorName' in document.documentElement.style &&
94
+ !anchor.style.getPropertyValue('anchor-name')
95
+ ) {
60
96
  const generatedId = `--${crypto.randomUUID()}`
61
97
  element.style.setProperty('position-anchor', generatedId)
62
98
  anchor.style.setProperty('anchor-name', generatedId)
@@ -71,22 +107,6 @@
71
107
  bind:this={element}
72
108
  bind:clientWidth
73
109
  bind:clientHeight
74
- ontoggle={(event) => {
75
- const { newState, currentTarget } = event
76
- if (newState === 'open') {
77
- const rect = currentTarget.getBoundingClientRect()
78
- const viewportHeight = innerHeight
79
-
80
- if (rect.bottom > viewportHeight && rect.top < viewportHeight / 2) {
81
- const maxHeight = viewportHeight - rect.top - 18
82
- currentTarget.style.maxHeight = `${maxHeight}px`
83
- }
84
- }
85
- if (newState === 'closed') {
86
- currentTarget.style.maxHeight = '80dvh'
87
- }
88
- attributes.ontoggle?.(event)
89
- }}
90
110
  popover="auto"
91
111
  class={['np-menu', attributes.class]}
92
112
  role="menu"
@@ -105,7 +125,6 @@
105
125
  box-shadow: var(--np-elevation-2);
106
126
  margin: var(--np-menu-margin, 2px);
107
127
  inset: auto;
108
- max-height: 80dvh;
109
128
  scrollbar-color: var(--np-color-on-surface-variant) transparent;
110
129
  scrollbar-width: thin;
111
130
  transition:
@@ -114,7 +133,7 @@
114
133
  opacity: 0;
115
134
  justify-self: var(--np-menu-justify-self, anchor-center);
116
135
  position-area: var(--np-menu-position-area, bottom center);
117
- position-try: normal flip-block;
136
+ position-try: most-height flip-block;
118
137
  }
119
138
 
120
139
  .np-menu:popover-open {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noph-ui",
3
- "version": "0.12.6",
3
+ "version": "0.12.8",
4
4
  "license": "MIT",
5
5
  "homepage": "https://noph.dev",
6
6
  "repository": {