noph-ui 0.18.3 → 0.18.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.
@@ -1,20 +1,35 @@
1
1
  <script lang="ts">
2
- import type { ChipSetProps } from './types.ts'
2
+ import { setContext } from 'svelte'
3
+ import type { ChipSetContext, ChipSetProps } from './types.ts'
3
4
 
4
5
  let { children, ...attributes }: ChipSetProps = $props()
6
+ let chipSet: ChipSetContext = $state({
7
+ chips: [],
8
+ })
9
+ setContext('chipSet', chipSet)
5
10
  </script>
6
11
 
7
12
  {#if children}
8
- <div class={['np-chip-set', attributes.class]} style={attributes.style} role="toolbar">
13
+ <div
14
+ class={['np-chip-set', chipSet.chips.length > 0 && 'np-chip-set-has-chips', attributes.class]}
15
+ style={attributes.style}
16
+ role="toolbar"
17
+ >
9
18
  {@render children()}
10
19
  </div>
11
20
  {/if}
12
21
 
13
22
  <style>
23
+ .np-chip-set-has-chips {
24
+ margin-right: 0.5rem;
25
+ padding-block: 2px;
26
+ padding-right: 2px;
27
+ }
14
28
  .np-chip-set {
15
29
  display: flex;
16
30
  flex-wrap: wrap;
17
31
  gap: 0.5rem;
32
+ overflow: auto;
18
33
  align-items: center;
19
34
  min-width: 0;
20
35
  }
@@ -3,7 +3,8 @@
3
3
  import CheckIcon from '../icons/CheckIcon.svelte'
4
4
  import CloseIcon from '../icons/CloseIcon.svelte'
5
5
  import Ripple from '../ripple/Ripple.svelte'
6
- import type { FilterChipProps } from './types.ts'
6
+ import { getContext, onMount } from 'svelte'
7
+ import type { ChipSetContext, FilterChipProps } from './types.ts'
7
8
 
8
9
  let {
9
10
  selected = $bindable(),
@@ -23,6 +24,17 @@
23
24
  }: FilterChipProps = $props()
24
25
 
25
26
  let chipLabel: HTMLLabelElement | undefined = $state()
27
+ let chipSet: ChipSetContext = getContext('chipSet')
28
+
29
+ onMount(() => {
30
+ chipSet.chips.push({ label: label, name: name, value: value })
31
+ return () => {
32
+ const index = chipSet.chips.findIndex((chip) => chip.value === value)
33
+ if (index !== -1) {
34
+ chipSet.chips.splice(index, 1)
35
+ }
36
+ }
37
+ })
26
38
 
27
39
  $effect(() => {
28
40
  if (group && value) {
@@ -2,8 +2,8 @@
2
2
  import IconButton from '../button/IconButton.svelte'
3
3
  import CloseIcon from '../icons/CloseIcon.svelte'
4
4
  import Ripple from '../ripple/Ripple.svelte'
5
- import { onMount } from 'svelte'
6
- import type { InputChipProps } from './types.ts'
5
+ import { getContext, onMount } from 'svelte'
6
+ import type { ChipSetContext, InputChipProps } from './types.ts'
7
7
 
8
8
  let {
9
9
  selected = $bindable(),
@@ -20,6 +20,7 @@
20
20
 
21
21
  let chipLabel: HTMLDivElement | undefined = $state()
22
22
  let visible = $state(false)
23
+ let chipSet: ChipSetContext = getContext('chipSet')
23
24
 
24
25
  onMount(() => {
25
26
  const observer = new IntersectionObserver((entries) => {
@@ -34,8 +35,15 @@
34
35
  if (element) {
35
36
  observer.observe(element)
36
37
  }
38
+ chipSet.chips.push({ label: label, name: name, value: value })
37
39
 
38
- return () => observer.disconnect()
40
+ return () => {
41
+ observer.disconnect()
42
+ const index = chipSet.chips.findIndex((chip) => chip.value === value)
43
+ if (index !== -1) {
44
+ chipSet.chips.splice(index, 1)
45
+ }
46
+ }
39
47
  })
40
48
  </script>
41
49
 
@@ -46,4 +46,11 @@ export interface InputChipProps extends HTMLAttributes<HTMLDivElement> {
46
46
  currentTarget: EventTarget & HTMLButtonElement;
47
47
  }) => void;
48
48
  }
49
+ export interface ChipSetContext {
50
+ chips: {
51
+ label: string;
52
+ name: string | undefined;
53
+ value: string | number | undefined;
54
+ }[];
55
+ }
49
56
  export {};
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { isFirstInvalidControlInForm } from './report-validity.js'
3
- import type { FocusEventHandler } from 'svelte/elements'
3
+ import type { FocusEventHandler, EventHandler } from 'svelte/elements'
4
4
  import type { TextFieldProps } from './types.ts'
5
5
 
6
6
  let {
@@ -22,6 +22,8 @@
22
22
  reportValidity = $bindable(),
23
23
  checkValidity = $bindable(),
24
24
  children,
25
+ oninput,
26
+ oninvalid,
25
27
  onfocus,
26
28
  onblur,
27
29
  focused = $bindable(false),
@@ -65,15 +67,22 @@
65
67
  value = ''
66
68
  }
67
69
 
68
- const onInput = () => {
70
+ const onInputEvent = (
71
+ event: Event & {
72
+ currentTarget: (EventTarget & HTMLInputElement) | HTMLTextAreaElement
73
+ },
74
+ ) => {
69
75
  doValidity = true
76
+ ;(oninput as EventHandler)?.(event)
70
77
  }
71
78
 
72
- const onInvalid = (event: Event) => {
73
- event.preventDefault()
74
- const { currentTarget } = event as Event & {
79
+ const onInvalidEvent = (
80
+ event: Event & {
75
81
  currentTarget: HTMLInputElement | HTMLTextAreaElement
76
- }
82
+ },
83
+ ) => {
84
+ event.preventDefault()
85
+ const { currentTarget } = event
77
86
  errorRaw = true
78
87
  if (errorText === '') {
79
88
  errorTextRaw = currentTarget.validationMessage
@@ -81,34 +90,43 @@
81
90
  if (focusOnInvalid && isFirstInvalidControlInForm(currentTarget.form, currentTarget)) {
82
91
  currentTarget.focus()
83
92
  }
84
- }
85
-
86
- const onBlur = () => {
87
- queueMicrotask(() => {
88
- if (doValidity && inputElement) {
89
- focusOnInvalid = false
90
- if (checkValidity()) {
91
- errorRaw = error
92
- errorTextRaw = errorText
93
- }
94
- focusOnInvalid = true
93
+ ;(oninvalid as EventHandler)?.(event)
94
+ }
95
+
96
+ const onFocusEvent = (
97
+ event: FocusEvent & {
98
+ currentTarget: EventTarget & (HTMLInputElement | HTMLTextAreaElement)
99
+ },
100
+ ) => {
101
+ focused = true
102
+ ;(onfocus as FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>)?.(event)
103
+ }
104
+
105
+ const onBlurEvent = (
106
+ event: FocusEvent & {
107
+ currentTarget: EventTarget & (HTMLInputElement | HTMLTextAreaElement)
108
+ },
109
+ ) => {
110
+ focused = false
111
+ if (doValidity) {
112
+ focusOnInvalid = false
113
+ if (checkValidity()) {
114
+ errorRaw = error
115
+ errorTextRaw = errorText
95
116
  }
96
- })
117
+ } else {
118
+ focusOnInvalid = true
119
+ }
120
+ ;(onblur as FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>)?.(event)
97
121
  }
98
122
 
99
123
  $effect(() => {
100
124
  if (inputElement) {
101
125
  inputElement.form?.addEventListener('reset', onReset)
102
- inputElement.addEventListener('input', onInput)
103
- inputElement.addEventListener('invalid', onInvalid)
104
- inputElement.addEventListener('blur', onBlur)
105
126
  }
106
127
  return () => {
107
128
  if (inputElement) {
108
- inputElement.removeEventListener('reset', onReset)
109
- inputElement.removeEventListener('input', onInput)
110
- inputElement.removeEventListener('invalid', onInvalid)
111
- inputElement.removeEventListener('blur', onBlur)
129
+ inputElement.form?.removeEventListener('reset', onReset)
112
130
  }
113
131
  }
114
132
  })
@@ -192,14 +210,10 @@
192
210
  <textarea
193
211
  aria-label={label}
194
212
  {...attributes}
195
- onfocus={(event) => {
196
- focused = true
197
- ;(onfocus as FocusEventHandler<HTMLTextAreaElement>)?.(event)
198
- }}
199
- onblur={(event) => {
200
- focused = false
201
- ;(onblur as FocusEventHandler<HTMLTextAreaElement>)?.(event)
202
- }}
213
+ oninput={onInputEvent}
214
+ oninvalid={onInvalidEvent}
215
+ onfocus={onFocusEvent}
216
+ onblur={onBlurEvent}
203
217
  bind:value
204
218
  bind:this={inputElement}
205
219
  class="input"
@@ -218,14 +232,10 @@
218
232
  {...attributes}
219
233
  bind:value
220
234
  bind:this={inputElement}
221
- onfocus={(event) => {
222
- focused = true
223
- ;(onfocus as FocusEventHandler<HTMLInputElement>)?.(event)
224
- }}
225
- onblur={(event) => {
226
- focused = false
227
- ;(onblur as FocusEventHandler<HTMLInputElement>)?.(event)
228
- }}
235
+ oninput={onInputEvent}
236
+ oninvalid={onInvalidEvent}
237
+ onfocus={onFocusEvent}
238
+ onblur={onBlurEvent}
229
239
  class="input"
230
240
  aria-invalid={errorRaw}
231
241
  />
@@ -514,7 +524,6 @@
514
524
  }
515
525
  :global(.content .input-wrapper .np-chip-set) {
516
526
  margin-top: calc(var(--top-space, 1.5rem) - 4px);
517
- margin-right: 0.5rem;
518
527
  }
519
528
 
520
529
  .prefix {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noph-ui",
3
- "version": "0.18.3",
3
+ "version": "0.18.4",
4
4
  "license": "MIT",
5
5
  "homepage": "https://noph.dev",
6
6
  "repository": {