@furystack/shades-common-components 10.0.1 → 10.0.3

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.
Files changed (72) hide show
  1. package/esm/components/button.d.ts.map +1 -1
  2. package/esm/components/button.js +9 -8
  3. package/esm/components/button.js.map +1 -1
  4. package/esm/components/command-palette/command-palette-input.d.ts.map +1 -1
  5. package/esm/components/command-palette/command-palette-input.js +1 -1
  6. package/esm/components/command-palette/command-palette-input.js.map +1 -1
  7. package/esm/components/command-palette/command-palette-suggestion-list.d.ts.map +1 -1
  8. package/esm/components/command-palette/command-palette-suggestion-list.js +7 -5
  9. package/esm/components/command-palette/command-palette-suggestion-list.js.map +1 -1
  10. package/esm/components/command-palette/index.d.ts.map +1 -1
  11. package/esm/components/command-palette/index.js +10 -10
  12. package/esm/components/command-palette/index.js.map +1 -1
  13. package/esm/components/data-grid/footer.d.ts +1 -1
  14. package/esm/components/data-grid/footer.d.ts.map +1 -1
  15. package/esm/components/data-grid/footer.js.map +1 -1
  16. package/esm/components/data-grid/header.d.ts.map +1 -1
  17. package/esm/components/data-grid/header.js +6 -6
  18. package/esm/components/data-grid/header.js.map +1 -1
  19. package/esm/components/form.d.ts.map +1 -1
  20. package/esm/components/form.js +3 -1
  21. package/esm/components/form.js.map +1 -1
  22. package/esm/components/inputs/autocomplete.d.ts.map +1 -1
  23. package/esm/components/inputs/autocomplete.js.map +1 -1
  24. package/esm/components/inputs/input.d.ts +5 -0
  25. package/esm/components/inputs/input.d.ts.map +1 -1
  26. package/esm/components/inputs/input.js +8 -6
  27. package/esm/components/inputs/input.js.map +1 -1
  28. package/esm/components/inputs/text-area.d.ts.map +1 -1
  29. package/esm/components/inputs/text-area.js +4 -4
  30. package/esm/components/inputs/text-area.js.map +1 -1
  31. package/esm/components/loader.d.ts.map +1 -1
  32. package/esm/components/loader.js +2 -2
  33. package/esm/components/loader.js.map +1 -1
  34. package/esm/components/modal.d.ts.map +1 -1
  35. package/esm/components/modal.js +1 -1
  36. package/esm/components/modal.js.map +1 -1
  37. package/esm/components/noty-list.d.ts.map +1 -1
  38. package/esm/components/noty-list.js +2 -9
  39. package/esm/components/noty-list.js.map +1 -1
  40. package/esm/components/skeleton.d.ts.map +1 -1
  41. package/esm/components/skeleton.js +2 -2
  42. package/esm/components/skeleton.js.map +1 -1
  43. package/esm/components/suggest/index.d.ts.map +1 -1
  44. package/esm/components/suggest/index.js +10 -10
  45. package/esm/components/suggest/index.js.map +1 -1
  46. package/esm/components/suggest/suggestion-list.d.ts.map +1 -1
  47. package/esm/components/suggest/suggestion-list.js +7 -5
  48. package/esm/components/suggest/suggestion-list.js.map +1 -1
  49. package/esm/services/collection-service.d.ts.map +1 -1
  50. package/esm/services/collection-service.js +17 -7
  51. package/esm/services/collection-service.js.map +1 -1
  52. package/esm/utils/promisify-animation.spec.js +7 -3
  53. package/esm/utils/promisify-animation.spec.js.map +1 -1
  54. package/package.json +7 -7
  55. package/src/components/button.tsx +9 -8
  56. package/src/components/command-palette/command-palette-input.tsx +1 -1
  57. package/src/components/command-palette/command-palette-suggestion-list.tsx +7 -5
  58. package/src/components/command-palette/index.tsx +10 -10
  59. package/src/components/data-grid/footer.tsx +5 -5
  60. package/src/components/data-grid/header.tsx +11 -9
  61. package/src/components/form.tsx +3 -1
  62. package/src/components/inputs/autocomplete.tsx +1 -1
  63. package/src/components/inputs/input.tsx +14 -7
  64. package/src/components/inputs/text-area.tsx +4 -4
  65. package/src/components/loader.tsx +2 -2
  66. package/src/components/modal.tsx +1 -1
  67. package/src/components/noty-list.tsx +3 -11
  68. package/src/components/skeleton.tsx +2 -2
  69. package/src/components/suggest/index.tsx +26 -18
  70. package/src/components/suggest/suggestion-list.tsx +7 -5
  71. package/src/services/collection-service.ts +16 -8
  72. package/src/utils/promisify-animation.spec.ts +7 -3
@@ -30,15 +30,15 @@ export const CommandPalette = Shade<CommandPaletteProps>({
30
30
  useDisposable('clickAwayService', () => new ClickAwayService(element, () => manager.isOpened.setValue(false)))
31
31
 
32
32
  const [isLoadingAtRender] = useObservable('isLoading', manager.isLoading, {
33
- onChange: async (isLoading) => {
33
+ onChange: (isLoading) => {
34
34
  const loader = element.querySelector('.loader-container')
35
35
  if (isLoading) {
36
- promisifyAnimation(loader, [{ opacity: 0 }, { opacity: 1 }], {
36
+ void promisifyAnimation(loader, [{ opacity: 0 }, { opacity: 1 }], {
37
37
  duration: 100,
38
38
  fill: 'forwards',
39
39
  })
40
40
  } else {
41
- promisifyAnimation(loader, [{ opacity: 1 }, { opacity: 0 }], {
41
+ void promisifyAnimation(loader, [{ opacity: 1 }, { opacity: 0 }], {
42
42
  duration: 100,
43
43
  fill: 'forwards',
44
44
  })
@@ -53,17 +53,17 @@ export const CommandPalette = Shade<CommandPaletteProps>({
53
53
  const postControls = element.querySelector('.post-controls')
54
54
  const inputContainer = element.querySelector('.input-container') as HTMLDivElement
55
55
  if (isOpened) {
56
- promisifyAnimation(suggestions, [{ opacity: 0 }, { opacity: 1 }], {
56
+ void promisifyAnimation(suggestions, [{ opacity: 0 }, { opacity: 1 }], {
57
57
  duration: 500,
58
58
  fill: 'forwards',
59
59
  })
60
60
 
61
- promisifyAnimation(postControls, [{ width: '0px' }, { width: '50px' }], {
61
+ void promisifyAnimation(postControls, [{ width: '0px' }, { width: '50px' }], {
62
62
  duration: 100,
63
63
  fill: 'forwards',
64
64
  })
65
65
 
66
- promisifyAnimation(
66
+ void promisifyAnimation(
67
67
  inputContainer,
68
68
  [{ background: 'transparent' }, { background: theme.background.default }],
69
69
  {
@@ -73,18 +73,18 @@ export const CommandPalette = Shade<CommandPaletteProps>({
73
73
  },
74
74
  )
75
75
  } else {
76
- promisifyAnimation(suggestions, [{ opacity: 1 }, { opacity: 0 }], {
76
+ void promisifyAnimation(suggestions, [{ opacity: 1 }, { opacity: 0 }], {
77
77
  duration: 500,
78
78
  fill: 'forwards',
79
79
  })
80
80
 
81
- promisifyAnimation(postControls, [{ width: '50px' }, { width: '0px' }], {
81
+ void promisifyAnimation(postControls, [{ width: '50px' }, { width: '0px' }], {
82
82
  duration: 500,
83
83
  fill: 'forwards',
84
84
  delay: 300,
85
85
  })
86
86
 
87
- promisifyAnimation(
87
+ void promisifyAnimation(
88
88
  inputContainer,
89
89
  [{ background: theme.background.default }, { background: 'transparent' }],
90
90
  {
@@ -118,7 +118,7 @@ export const CommandPalette = Shade<CommandPaletteProps>({
118
118
  )
119
119
  }
120
120
 
121
- manager.getSuggestion({ injector, term: (ev.target as any).value })
121
+ void manager.getSuggestion({ injector, term: (ev.target as HTMLInputElement).value })
122
122
  }}
123
123
  >
124
124
  <div
@@ -1,8 +1,8 @@
1
- import { Shade, createComponent } from '@furystack/shades'
2
- import { ThemeProviderService } from '../../services/theme-provider-service.js'
3
- import type { CollectionService } from '../../services/collection-service.js'
4
1
  import type { FindOptions } from '@furystack/core'
2
+ import { Shade, createComponent } from '@furystack/shades'
5
3
  import type { ObservableValue } from '@furystack/utils'
4
+ import type { CollectionService } from '../../services/collection-service.js'
5
+ import { ThemeProviderService } from '../../services/theme-provider-service.js'
6
6
 
7
7
  export const dataGridItemsPerPage = [10, 20, 25, 50, 100, Infinity]
8
8
 
@@ -47,7 +47,7 @@ export const DataGridFooter = Shade<{
47
47
  <select
48
48
  style={{ margin: '0 1em' }}
49
49
  onchange={(ev) => {
50
- const value = parseInt((ev.target as any).value, 10)
50
+ const value = parseInt((ev.target as HTMLInputElement).value, 10)
51
51
  setCurrentOptions({ ...currentOptions, skip: (currentOptions.top || 0) * value })
52
52
  }}
53
53
  >
@@ -64,7 +64,7 @@ export const DataGridFooter = Shade<{
64
64
  <select
65
65
  style={{ margin: '0 1em' }}
66
66
  onchange={(ev) => {
67
- const value = parseInt((ev.currentTarget as any).value as string, 10)
67
+ const value = parseInt((ev.currentTarget as HTMLInputElement).value, 10)
68
68
  setCurrentOptions({
69
69
  ...currentOptions,
70
70
  top: value,
@@ -109,7 +109,7 @@ const SearchForm = Shade<{
109
109
  },
110
110
  })
111
111
 
112
- const currentValue = (findOptions.filter?.[props.fieldName] as any)?.$regex || ''
112
+ const currentValue = (findOptions.filter?.[props.fieldName] as FilterType<Record<string, string>>)?.$regex || ''
113
113
 
114
114
  return (
115
115
  <Form<SearchSubmitType>
@@ -122,7 +122,9 @@ const SearchForm = Shade<{
122
122
  justifyContent: 'space-around',
123
123
  opacity: '0',
124
124
  }}
125
- validate={(data): data is SearchSubmitType => data.searchValue?.length}
125
+ validate={(data): data is SearchSubmitType =>
126
+ typeof (data as SearchSubmitType).searchValue?.length === 'number'
127
+ }
126
128
  onSubmit={({ searchValue }) => {
127
129
  props.onSubmit(searchValue)
128
130
  }}
@@ -133,7 +135,7 @@ const SearchForm = Shade<{
133
135
  autofocus
134
136
  labelTitle={`${props.fieldName}`}
135
137
  name="searchValue"
136
- value={currentValue}
138
+ value={typeof currentValue === 'string' ? currentValue : ''}
137
139
  labelProps={{
138
140
  style: { padding: '0px 2em' },
139
141
  }}
@@ -171,15 +173,15 @@ export const DataGridHeader: <T, Column extends string>(
171
173
  const searchForm = element.querySelector('.search-form') as HTMLElement
172
174
  const headerContent = element.querySelector('.header-content') as HTMLElement
173
175
  if (!newValue) {
174
- collapse(searchForm)
175
- expand(headerContent)
176
+ void collapse(searchForm)
177
+ void expand(headerContent)
176
178
  } else {
177
179
  searchForm.style.display = 'flex'
178
- expand(searchForm).then(async () => {
180
+ void expand(searchForm).then(async () => {
179
181
  await sleepAsync(100)
180
182
  searchForm.querySelector('input')?.focus()
181
183
  })
182
- collapse(headerContent)
184
+ void collapse(headerContent)
183
185
  }
184
186
  },
185
187
  })
@@ -188,13 +190,13 @@ export const DataGridHeader: <T, Column extends string>(
188
190
 
189
191
  const updateSearchValue = (value?: string) => {
190
192
  if (value) {
191
- const newSettings: FindOptions<unknown, any> = {
193
+ const newSettings = {
192
194
  ...findOptions,
193
195
  filter: {
194
196
  ...findOptions.filter,
195
197
  [props.field]: { $regex: value },
196
198
  },
197
- }
199
+ } as typeof findOptions
198
200
  setFindOptions(newSettings)
199
201
  } else {
200
202
  const { [props.field]: _, ...newFilter } = findOptions.filter || {}
@@ -74,7 +74,9 @@ export const Form: <T>(props: FormProps<T>, children: ChildrenList) => JSX.Eleme
74
74
  } else if (props.validate(formData)) {
75
75
  formService.validationResult.setValue({ isValid: true })
76
76
  formService.validatedFormData.setValue(formData)
77
- shouldSubmit && props.onSubmit(formData)
77
+ if (shouldSubmit) {
78
+ props.onSubmit(formData)
79
+ }
78
80
  } else {
79
81
  formService.validationResult.setValue({ isValid: false, reason: 'validation-failed' })
80
82
  }
@@ -21,7 +21,7 @@ export const Autocomplete = Shade<{
21
21
  <Input
22
22
  {...props.inputProps}
23
23
  onchange={(ev) => {
24
- const { value } = ev.target as any
24
+ const { value } = ev.target as HTMLInputElement
25
25
  if (props.strict) {
26
26
  if (!props.suggestions.includes(value)) {
27
27
  ;(ev.target as HTMLInputElement).setCustomValidity('Please select a valid entry!')
@@ -61,6 +61,12 @@ export interface TextInputProps extends PartialElement<HTMLInputElement> {
61
61
  getEndIcon?: (options: { state: TextInputState; validationResult?: InputValidationResult }) => JSX.Element | string
62
62
  }
63
63
 
64
+ declare global {
65
+ interface ValidityState {
66
+ toJSON: () => Partial<ValidityState>
67
+ }
68
+ }
69
+
64
70
  export type TextInputState = {
65
71
  value: string
66
72
  focused: boolean
@@ -175,7 +181,7 @@ export const Input = Shade<TextInputProps>({
175
181
 
176
182
  newState.value = input?.value || newState.value
177
183
  newState.validity = input?.validity || newState.validity
178
- ;(newState.validity as any).toJSON = () => {
184
+ newState.validity.toJSON = () => {
179
185
  return {
180
186
  valid: newState.validity.valid,
181
187
  valueMissing: newState.validity.valueMissing,
@@ -192,9 +198,11 @@ export const Input = Shade<TextInputProps>({
192
198
 
193
199
  const validationResult = props.getValidationResult?.({ state: newState })
194
200
 
195
- validationResult?.isValid === false || newState.validity?.valid === false
196
- ? element.setAttribute('data-validation-failed', 'true')
197
- : element.removeAttribute('data-validation-failed')
201
+ if (validationResult?.isValid === false || newState.validity?.valid === false) {
202
+ element.setAttribute('data-validation-failed', 'true')
203
+ } else {
204
+ element.removeAttribute('data-validation-failed')
205
+ }
198
206
 
199
207
  attachStyles(label, { style: getLabelStyle({ themeProvider, props, state: newState, validationResult }) })
200
208
 
@@ -215,7 +223,6 @@ export const Input = Shade<TextInputProps>({
215
223
  const formService = injector.getInstance(FormService)
216
224
  formService.setFieldState(props.name as keyof unknown, validationResult || { isValid: true }, newState.validity)
217
225
  }
218
- return newState
219
226
  }
220
227
 
221
228
  const [state, setState] = useObservable<TextInputState>(
@@ -247,12 +254,12 @@ export const Input = Shade<TextInputProps>({
247
254
  const el = ev.target as HTMLInputElement
248
255
  setState({ ...state, validity: el.validity })
249
256
  }}
250
- onchange={(ev) => {
257
+ onchange={function (ev) {
251
258
  const el = ev.target as HTMLInputElement
252
259
  const newValue = el.value
253
260
  setState({ ...state, value: newValue, validity: el?.validity })
254
261
  props.onTextChange?.(newValue)
255
- props.onchange && (props.onchange as any)(ev)
262
+ props?.onchange?.call(this, ev)
256
263
  }}
257
264
  onfocus={(ev) => {
258
265
  const el = ev.target as HTMLInputElement
@@ -50,7 +50,7 @@ export const TextArea = Shade<TextAreaProps>({
50
50
  }}
51
51
  onfocus={() => {
52
52
  if (!props.disabled) {
53
- promisifyAnimation(
53
+ void promisifyAnimation(
54
54
  element.querySelector('label'),
55
55
  [{ color: themeProvider.getTextColor(theme.background.default) }, { color: palette.primary.main }],
56
56
  {
@@ -59,7 +59,7 @@ export const TextArea = Shade<TextAreaProps>({
59
59
  fill: 'forwards',
60
60
  },
61
61
  )
62
- promisifyAnimation(
62
+ void promisifyAnimation(
63
63
  element.querySelector('div[contenteditable="true"]'),
64
64
  [
65
65
  { boxShadow: '0px 0px 0px rgba(128,128,128,0.1)' },
@@ -74,7 +74,7 @@ export const TextArea = Shade<TextAreaProps>({
74
74
  }}
75
75
  onblur={() => {
76
76
  if (!props.disabled) {
77
- promisifyAnimation(
77
+ void promisifyAnimation(
78
78
  element.querySelector('label'),
79
79
  [{ color: palette.primary.main }, { color: themeProvider.getTextColor(theme.background.default) }],
80
80
  {
@@ -83,7 +83,7 @@ export const TextArea = Shade<TextAreaProps>({
83
83
  fill: 'forwards',
84
84
  },
85
85
  )
86
- promisifyAnimation(
86
+ void promisifyAnimation(
87
87
  element.querySelector('div[contenteditable="true"]'),
88
88
  [
89
89
  { boxShadow: '0px 3px 0px rgba(128,128,128,0.4)' },
@@ -38,12 +38,12 @@ export const Loader = Shade<LoaderProps>({
38
38
  const { borderColor = theme.palette.primary.main } = props
39
39
 
40
40
  setTimeout(() => {
41
- promisifyAnimation(element, [{ opacity: '0' }, { opacity: '1' }], {
41
+ void promisifyAnimation(element, [{ opacity: '0' }, { opacity: '1' }], {
42
42
  duration: 500,
43
43
  delay,
44
44
  fill: 'forwards',
45
45
  })
46
- promisifyAnimation(
46
+ void promisifyAnimation(
47
47
  element.firstElementChild,
48
48
  [{ transform: 'rotate(0deg)' }, { transform: 'rotate(180deg)' }, { transform: 'rotate(360deg)' }],
49
49
  {
@@ -15,7 +15,7 @@ export const Modal = Shade<ModalProps>({
15
15
  const [isVisible] = useObservable('isVisible', props.isVisible)
16
16
 
17
17
  if (isVisible) {
18
- props.showAnimation?.(element)
18
+ void props.showAnimation?.(element)
19
19
  }
20
20
 
21
21
  return isVisible ? (
@@ -25,7 +25,7 @@ export const NotyComponent = Shade<{ model: NotyModel; onDismiss: () => void }>(
25
25
  constructed: ({ element }) => {
26
26
  setTimeout(() => {
27
27
  const height = element.scrollHeight || 80
28
- promisifyAnimation(
28
+ void promisifyAnimation(
29
29
  element,
30
30
  [
31
31
  { opacity: '0', height: '0px' },
@@ -73,21 +73,13 @@ export const NotyComponent = Shade<{ model: NotyModel; onDismiss: () => void }>(
73
73
 
74
74
  const timeout = props.model.timeout || getDefaultNotyTimeouts(props.model.type)
75
75
  if (timeout) {
76
- setTimeout(removeSelf, timeout)
76
+ setTimeout(() => void removeSelf(), timeout)
77
77
  }
78
78
 
79
79
  element.className = `noty ${props.model.type}`
80
80
  element.style.backgroundColor = colors.main
81
81
  element.style.color = textColor
82
82
 
83
- // attachProps(element, {
84
- // className: `noty ${props.model.type}`,
85
- // style: {
86
- // backgroundColor: colors.main,
87
- // color: textColor,
88
- // },
89
- // })
90
-
91
83
  return (
92
84
  <>
93
85
  <div
@@ -153,7 +145,7 @@ export const NotyList = Shade({
153
145
  useDisposable('removeNoty', () =>
154
146
  notyService.subscribe('onNotyRemoved', (n) => {
155
147
  element.querySelectorAll('shade-noty').forEach((e) => {
156
- if ((e as JSX.Element).props.model === n) {
148
+ if ((e as JSX.Element<{ model?: NotyModel }>).props.model === n) {
157
149
  e.remove()
158
150
  }
159
151
  })
@@ -22,13 +22,13 @@ export const Skeleton = Shade<SkeletonProps>({
22
22
  render: ({ element, props }) => {
23
23
  const { delay = 1500 } = props
24
24
  setTimeout(() => {
25
- promisifyAnimation(element, [{ opacity: 0 }, { opacity: 1 }], {
25
+ void promisifyAnimation(element, [{ opacity: 0 }, { opacity: 1 }], {
26
26
  fill: 'forwards',
27
27
  duration: 300,
28
28
  easing: 'ease-out',
29
29
  delay,
30
30
  }).then(() => {
31
- promisifyAnimation(
31
+ void promisifyAnimation(
32
32
  element,
33
33
  [{ backgroundPosition: '0% 50%' }, { backgroundPosition: '100% 50%' }, { backgroundPosition: '0% 50%' }],
34
34
  {
@@ -38,49 +38,57 @@ export const Suggest: <T>(props: SuggestProps<T>, children: ChildrenList) => JSX
38
38
  const suggestions = element.querySelector('.close-suggestions')
39
39
  const postControls = element.querySelector('.post-controls')
40
40
  if (isOpened) {
41
- promisifyAnimation(suggestions, [{ opacity: 0 }, { opacity: 1 }], {
41
+ void promisifyAnimation(suggestions, [{ opacity: 0 }, { opacity: 1 }], {
42
42
  duration: 500,
43
43
  fill: 'forwards',
44
44
  })
45
45
 
46
- promisifyAnimation(postControls, [{ width: '0px' }, { width: '50px' }], {
46
+ void promisifyAnimation(postControls, [{ width: '0px' }, { width: '50px' }], {
47
47
  duration: 100,
48
48
  fill: 'forwards',
49
49
  })
50
50
 
51
- promisifyAnimation(inputContainer, [{ background: 'transparent' }, { background: theme.background.default }], {
52
- duration: 500,
53
- fill: 'forwards',
54
- easing: 'cubic-bezier(0.050, 0.570, 0.840, 1.005)',
55
- })
51
+ void promisifyAnimation(
52
+ inputContainer,
53
+ [{ background: 'transparent' }, { background: theme.background.default }],
54
+ {
55
+ duration: 500,
56
+ fill: 'forwards',
57
+ easing: 'cubic-bezier(0.050, 0.570, 0.840, 1.005)',
58
+ },
59
+ )
56
60
  } else {
57
- promisifyAnimation(suggestions, [{ opacity: 1 }, { opacity: 0 }], {
61
+ void promisifyAnimation(suggestions, [{ opacity: 1 }, { opacity: 0 }], {
58
62
  duration: 500,
59
63
  fill: 'forwards',
60
64
  })
61
65
 
62
- promisifyAnimation(postControls, [{ width: '50px' }, { width: '0px' }], {
66
+ void promisifyAnimation(postControls, [{ width: '50px' }, { width: '0px' }], {
63
67
  duration: 500,
64
68
  fill: 'forwards',
65
69
  delay: 300,
66
70
  })
67
71
 
68
- promisifyAnimation(inputContainer, [{ background: theme.background.default }, { background: 'transparent' }], {
69
- duration: 300,
70
- fill: 'forwards',
71
- easing: 'cubic-bezier(0.000, 0.245, 0.190, 0.790)',
72
- })
72
+ void promisifyAnimation(
73
+ inputContainer,
74
+ [{ background: theme.background.default }, { background: 'transparent' }],
75
+ {
76
+ duration: 300,
77
+ fill: 'forwards',
78
+ easing: 'cubic-bezier(0.000, 0.245, 0.190, 0.790)',
79
+ },
80
+ )
73
81
  }
74
82
  })
75
- manager.isLoading.subscribe(async (isLoading) => {
83
+ manager.isLoading.subscribe((isLoading) => {
76
84
  const loader = element.querySelector('shade-loader')
77
85
  if (isLoading) {
78
- promisifyAnimation(loader, [{ opacity: 0 }, { opacity: 1 }], {
86
+ void promisifyAnimation(loader, [{ opacity: 0 }, { opacity: 1 }], {
79
87
  duration: 100,
80
88
  fill: 'forwards',
81
89
  })
82
90
  } else {
83
- promisifyAnimation(loader, [{ opacity: 1 }, { opacity: 0 }], {
91
+ void promisifyAnimation(loader, [{ opacity: 1 }, { opacity: 0 }], {
84
92
  duration: 100,
85
93
  fill: 'forwards',
86
94
  })
@@ -107,7 +115,7 @@ export const Suggest: <T>(props: SuggestProps<T>, children: ChildrenList) => JSX
107
115
  )
108
116
  }
109
117
 
110
- manager.getSuggestion({ injector, term: (ev.target as any).value })
118
+ void manager.getSuggestion({ injector, term: (ev.target as HTMLInputElement).value })
111
119
  }}
112
120
  >
113
121
  <div
@@ -1,8 +1,8 @@
1
1
  import type { ChildrenList } from '@furystack/shades'
2
2
  import { Shade, createComponent } from '@furystack/shades'
3
+ import { ThemeProviderService } from '../../services/theme-provider-service.js'
3
4
  import { promisifyAnimation } from '../../utils/promisify-animation.js'
4
5
  import type { SuggestManager } from './suggest-manager.js'
5
- import { ThemeProviderService } from '../../services/theme-provider-service.js'
6
6
 
7
7
  export const SuggestionList: <T>(props: { manager: SuggestManager<T> }, children: ChildrenList) => JSX.Element<any> =
8
8
  Shade<{ manager: SuggestManager<any> }>({
@@ -29,14 +29,14 @@ export const SuggestionList: <T>(props: { manager: SuggestManager<T> }, children
29
29
  })
30
30
 
31
31
  const [isListOpened] = useObservable('isOpened', manager.isOpened, {
32
- onChange: async (isOpened) => {
32
+ onChange: (isOpened) => {
33
33
  const container = element.firstElementChild as HTMLDivElement
34
34
  if (isOpened) {
35
35
  container.style.zIndex = '1'
36
36
  container.style.width = `calc(${Math.round(
37
37
  element.parentElement?.getBoundingClientRect().width || 200,
38
38
  )}px - 3em)`
39
- await promisifyAnimation(
39
+ void promisifyAnimation(
40
40
  container,
41
41
  [
42
42
  { opacity: 0, transform: 'translate(0, -50px)' },
@@ -45,7 +45,7 @@ export const SuggestionList: <T>(props: { manager: SuggestManager<T> }, children
45
45
  { fill: 'forwards', duration: 500 },
46
46
  )
47
47
  } else {
48
- await promisifyAnimation(
48
+ void promisifyAnimation(
49
49
  container,
50
50
  [
51
51
  { opacity: 1, transform: 'translate(0, 0)' },
@@ -80,7 +80,9 @@ export const SuggestionList: <T>(props: { manager: SuggestManager<T> }, children
80
80
  <div
81
81
  className="suggestion-item"
82
82
  onclick={() => {
83
- isListOpened && manager.selectSuggestion(i)
83
+ if (isListOpened) {
84
+ manager.selectSuggestion(i)
85
+ }
84
86
  }}
85
87
  style={{
86
88
  padding: '1em',
@@ -44,7 +44,11 @@ export class CollectionService<T> implements Disposable {
44
44
  }
45
45
 
46
46
  public toggleSelection = (entry: T) => {
47
- this.isSelected(entry) ? this.removeFromSelection(entry) : this.addToSelection(entry)
47
+ if (this.isSelected(entry)) {
48
+ this.removeFromSelection(entry)
49
+ } else {
50
+ this.addToSelection(entry)
51
+ }
48
52
  }
49
53
 
50
54
  public data = new ObservableValue<CollectionData<T>>({ count: 0, entries: [] })
@@ -68,12 +72,13 @@ export class CollectionService<T> implements Disposable {
68
72
  switch (ev.key) {
69
73
  case ' ':
70
74
  ev.preventDefault()
71
- focusedEntry &&
75
+ if (focusedEntry) {
72
76
  this.selection.setValue(
73
77
  selectedEntries.includes(focusedEntry)
74
78
  ? selectedEntries.filter((e) => e !== focusedEntry)
75
79
  : [...selectedEntries, focusedEntry],
76
80
  )
81
+ }
77
82
  break
78
83
  case '*':
79
84
  this.selection.setValue(entries.filter((e) => !selectedEntries.includes(e)))
@@ -85,11 +90,14 @@ export class CollectionService<T> implements Disposable {
85
90
  this.selection.setValue([])
86
91
  break
87
92
  case 'Insert':
88
- focusedEntry &&
89
- (this.selection.getValue().includes(focusedEntry)
90
- ? this.selection.setValue([...this.selection.getValue().filter((e) => e !== focusedEntry)])
91
- : this.selection.setValue([...this.selection.getValue(), focusedEntry]))
92
- this.focusedEntry.setValue(entries[entries.findIndex((e) => e === this.focusedEntry.getValue()) + 1])
93
+ if (focusedEntry) {
94
+ if (this.selection.getValue().includes(focusedEntry)) {
95
+ this.selection.setValue([...this.selection.getValue().filter((e) => e !== focusedEntry)])
96
+ } else {
97
+ this.selection.setValue([...this.selection.getValue(), focusedEntry])
98
+ }
99
+ this.focusedEntry.setValue(entries[entries.findIndex((e) => e === this.focusedEntry.getValue()) + 1])
100
+ }
93
101
 
94
102
  break
95
103
  case 'ArrowUp':
@@ -125,7 +133,7 @@ export class CollectionService<T> implements Disposable {
125
133
  const newFocusedEntry = entries.find(
126
134
  (e) =>
127
135
  this.options.searchField &&
128
- (e[this.options.searchField] as any)?.toString().startsWith(newSearchExpression),
136
+ (e[this.options.searchField] as string)?.toString().startsWith(newSearchExpression),
129
137
  )
130
138
  this.focusedEntry.setValue(newFocusedEntry)
131
139
  this.searchTerm.setValue(newSearchExpression)
@@ -1,18 +1,22 @@
1
1
  import { sleepAsync } from '@furystack/utils'
2
+ import { describe, expect, it, vi } from 'vitest'
2
3
  import { promisifyAnimation } from './promisify-animation.js'
3
- import { describe, it, expect, vi } from 'vitest'
4
4
 
5
5
  describe('promisifyAnimation', () => {
6
6
  it('should trigger the element animation', async () => {
7
7
  const el = document.createElement('div')
8
- const onfinish = vi.fn()
8
+ const onfinish = vi.fn(() => {})
9
9
  const oncancel = vi.fn()
10
10
  const animate = vi.fn(() => {
11
11
  const animation = {
12
12
  onfinish,
13
13
  oncancel,
14
14
  }
15
- sleepAsync(100).then(() => animation.onfinish())
15
+ sleepAsync(100)
16
+ .then(() => animation.onfinish())
17
+ .catch(() => {
18
+ /** */
19
+ })
16
20
  return animation
17
21
  })
18
22
  Object.assign(el, { animate })