noph-ui 0.21.9 → 0.21.11

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.
@@ -4,6 +4,7 @@
4
4
  import VirtualList from '../select/VirtualList.svelte'
5
5
  import type { AutoCompleteOption, AutoCompleteProps } from './types.ts'
6
6
  import TextField from '../text-field/TextField.svelte'
7
+ import { on } from 'svelte/events'
7
8
 
8
9
  let {
9
10
  options = [],
@@ -26,6 +27,8 @@
26
27
  onkeydown,
27
28
  onclick,
28
29
  oninput,
30
+ onblur,
31
+ onfocusout,
29
32
  focused = $bindable(false),
30
33
  ...attributes
31
34
  }: AutoCompleteProps = $props()
@@ -46,22 +49,25 @@
46
49
  let clientWidth = $state(0)
47
50
  let menuElement: HTMLDivElement | undefined = $state()
48
51
  let finalPopulated = $state(populated)
52
+ let blockEvent = $state(false)
49
53
  </script>
50
54
 
51
55
  {#snippet item(option: AutoCompleteOption)}
52
56
  <Item
53
57
  onclick={(event) => {
54
58
  event.preventDefault()
55
- onoptionselect(option)
56
59
  element?.focus()
60
+ onoptionselect(option)
57
61
  }}
58
62
  disabled={option.disabled}
59
63
  onkeydown={(event) => {
60
64
  if (event.key === 'ArrowDown') {
65
+ blockEvent = true
61
66
  ;(event.currentTarget?.nextElementSibling as HTMLElement)?.focus()
62
67
  event.preventDefault()
63
68
  }
64
69
  if (event.key === 'ArrowUp') {
70
+ blockEvent = true
65
71
  ;(event.currentTarget?.previousElementSibling as HTMLElement)?.focus()
66
72
  event.preventDefault()
67
73
  }
@@ -70,7 +76,8 @@
70
76
  }
71
77
  if (event.key === 'Tab') {
72
78
  finalPopulated = populated
73
- menuElement?.hidePopover()
79
+ blockEvent = false
80
+ hidePopover?.()
74
81
  }
75
82
  }}
76
83
  variant="button"
@@ -90,26 +97,38 @@
90
97
  style="anchor-name:--{uid};"
91
98
  onclick={(event) => {
92
99
  finalPopulated = true
93
- menuElement?.showPopover()
100
+ showPopover()
94
101
  onclick?.(event)
95
102
  }}
96
103
  oninput={(event) => {
97
- menuElement?.showPopover()
104
+ showPopover()
98
105
  oninput?.(event)
99
106
  }}
100
107
  onkeydown={(event) => {
101
108
  if (event.key === 'Tab' || event.key === 'Escape') {
102
- menuElement?.hidePopover()
109
+ blockEvent = false
110
+ hidePopover()
103
111
  } else {
104
112
  if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
105
113
  event.preventDefault()
106
114
  finalPopulated = true
107
- menuElement?.showPopover()
115
+ blockEvent = true
116
+ showPopover()
108
117
  ;(menuElement?.firstElementChild?.firstElementChild as HTMLElement)?.focus()
109
118
  }
110
119
  }
111
120
  onkeydown?.(event)
112
121
  }}
122
+ onblur={(event) => {
123
+ if (!blockEvent) {
124
+ onblur?.(event)
125
+ }
126
+ }}
127
+ onfocusout={(event) => {
128
+ if (!blockEvent) {
129
+ onfocusout?.(event)
130
+ }
131
+ }}
113
132
  bind:reportValidity
114
133
  bind:checkValidity
115
134
  bind:element
@@ -128,9 +147,25 @@
128
147
  ? 'var(--np-outlined-select-text-field-container-shape)'
129
148
  : 'var(--np-filled-select-text-field-container-shape)'}
130
149
  anchor={element}
150
+ onbeforetoggle={(e) => {
151
+ if (e.newState !== 'closed') {
152
+ blockEvent = true
153
+ }
154
+ }}
131
155
  ontoggle={(e) => {
132
- if (e.newState === 'closed' && !populated && finalPopulated && !value) {
133
- finalPopulated = false
156
+ if (e.newState === 'closed') {
157
+ blockEvent = false
158
+ if (!populated && finalPopulated && !value) {
159
+ finalPopulated = false
160
+ }
161
+ }
162
+ if (!focused) {
163
+ const event = {
164
+ ...new FocusEvent('blur', { relatedTarget: element }),
165
+ currentTarget: element as EventTarget & HTMLInputElement,
166
+ } as FocusEvent & { currentTarget: EventTarget & HTMLInputElement }
167
+ onblur?.(event)
168
+ onfocusout?.(event)
134
169
  }
135
170
  }}
136
171
  bind:element={menuElement}
@@ -123,6 +123,9 @@
123
123
  scrollbar-color: var(--np-color-on-surface-variant) transparent;
124
124
  scrollbar-width: thin;
125
125
  }
126
+ :global(.np-menu .np-divider) {
127
+ margin-block: 0.5rem;
128
+ }
126
129
  .np-menu-container[popover] {
127
130
  color: var(--np-menu-text-color, var(--np-color-on-surface));
128
131
  background-color: var(--np-menu-container-color, var(--np-color-surface-container));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noph-ui",
3
- "version": "0.21.9",
3
+ "version": "0.21.11",
4
4
  "license": "MIT",
5
5
  "homepage": "https://noph.dev",
6
6
  "repository": {