webcoreui 0.3.0 → 0.4.0

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 (127) hide show
  1. package/README.md +5 -2
  2. package/astro.d.ts +7 -1
  3. package/astro.js +6 -0
  4. package/components/Accordion/Accordion.astro +2 -0
  5. package/components/Accordion/Accordion.svelte +2 -0
  6. package/components/Accordion/Accordion.tsx +2 -0
  7. package/components/Alert/Alert.astro +3 -2
  8. package/components/Alert/Alert.svelte +4 -3
  9. package/components/Alert/Alert.tsx +3 -2
  10. package/components/Avatar/Avatar.astro +2 -1
  11. package/components/Avatar/Avatar.svelte +2 -1
  12. package/components/Avatar/Avatar.tsx +3 -3
  13. package/components/Badge/Badge.astro +1 -0
  14. package/components/Badge/Badge.svelte +3 -2
  15. package/components/Badge/Badge.tsx +2 -1
  16. package/components/Button/Button.astro +4 -5
  17. package/components/Button/Button.svelte +2 -1
  18. package/components/Button/Button.tsx +2 -1
  19. package/components/Button/button.ts +1 -1
  20. package/components/Card/Card.astro +11 -3
  21. package/components/Card/Card.svelte +5 -2
  22. package/components/Card/Card.tsx +5 -2
  23. package/components/Card/card.ts +1 -0
  24. package/components/Checkbox/Checkbox.astro +1 -0
  25. package/components/Checkbox/Checkbox.svelte +7 -5
  26. package/components/Checkbox/Checkbox.tsx +4 -2
  27. package/components/Collapsible/Collapsible.astro +2 -1
  28. package/components/Collapsible/Collapsible.svelte +2 -1
  29. package/components/Collapsible/Collapsible.tsx +55 -54
  30. package/components/ConditionalWrapper/ConditionalWrapper.astro +2 -1
  31. package/components/ConditionalWrapper/ConditionalWrapper.tsx +1 -2
  32. package/components/Group/Group.astro +22 -0
  33. package/components/Group/Group.svelte +20 -0
  34. package/components/Group/Group.tsx +22 -0
  35. package/components/Group/group.module.scss +43 -0
  36. package/components/Group/group.ts +8 -0
  37. package/components/Icon/map.ts +2 -0
  38. package/components/Input/Input.astro +8 -1
  39. package/components/Input/Input.svelte +15 -3
  40. package/components/Input/Input.tsx +10 -3
  41. package/components/Input/input.module.scss +4 -1
  42. package/components/Input/input.ts +9 -4
  43. package/components/List/List.astro +169 -0
  44. package/components/List/List.svelte +147 -0
  45. package/components/List/List.tsx +168 -0
  46. package/components/List/list.module.scss +91 -0
  47. package/components/List/list.ts +37 -0
  48. package/components/Menu/Menu.astro +2 -1
  49. package/components/Menu/Menu.svelte +7 -5
  50. package/components/Menu/Menu.tsx +116 -113
  51. package/components/Modal/Modal.astro +6 -4
  52. package/components/Modal/Modal.svelte +8 -6
  53. package/components/Modal/Modal.tsx +79 -76
  54. package/components/Modal/modal.ts +1 -0
  55. package/components/Popover/Popover.astro +4 -1
  56. package/components/Popover/Popover.svelte +4 -2
  57. package/components/Popover/Popover.tsx +55 -27
  58. package/components/Popover/popover.module.scss +1 -0
  59. package/components/Popover/popover.ts +2 -0
  60. package/components/Progress/Progress.astro +2 -1
  61. package/components/Progress/Progress.svelte +2 -1
  62. package/components/Progress/Progress.tsx +3 -2
  63. package/components/Radio/Radio.astro +1 -0
  64. package/components/Radio/Radio.svelte +4 -2
  65. package/components/Radio/Radio.tsx +3 -2
  66. package/components/Rating/Rating.astro +3 -1
  67. package/components/Rating/Rating.svelte +9 -7
  68. package/components/Rating/Rating.tsx +4 -2
  69. package/components/Select/Select.astro +135 -0
  70. package/components/Select/Select.svelte +122 -0
  71. package/components/Select/Select.tsx +142 -0
  72. package/components/Select/select.module.scss +25 -0
  73. package/components/Select/select.ts +21 -0
  74. package/components/Sheet/Sheet.astro +2 -1
  75. package/components/Sheet/Sheet.svelte +2 -1
  76. package/components/Sheet/Sheet.tsx +33 -32
  77. package/components/Slider/Slider.astro +2 -1
  78. package/components/Slider/Slider.svelte +2 -1
  79. package/components/Slider/Slider.tsx +49 -48
  80. package/components/Spinner/Spinner.astro +4 -3
  81. package/components/Spinner/Spinner.svelte +3 -2
  82. package/components/Spinner/Spinner.tsx +4 -3
  83. package/components/Switch/Switch.astro +2 -1
  84. package/components/Switch/Switch.svelte +5 -4
  85. package/components/Switch/Switch.tsx +2 -2
  86. package/components/Switch/switch.module.scss +1 -1
  87. package/components/Table/Table.astro +1 -0
  88. package/components/Table/Table.svelte +2 -1
  89. package/components/Table/Table.tsx +2 -1
  90. package/components/Tabs/Tabs.astro +2 -1
  91. package/components/Tabs/Tabs.svelte +2 -1
  92. package/components/Tabs/Tabs.tsx +4 -3
  93. package/components/Textarea/Textarea.astro +1 -0
  94. package/components/Textarea/Textarea.svelte +3 -1
  95. package/components/Textarea/Textarea.tsx +52 -50
  96. package/components/ThemeSwitcher/ThemeSwitcher.astro +108 -107
  97. package/components/ThemeSwitcher/ThemeSwitcher.svelte +5 -4
  98. package/components/ThemeSwitcher/ThemeSwitcher.tsx +91 -90
  99. package/components/Timeline/Timeline.astro +3 -2
  100. package/components/Timeline/Timeline.svelte +3 -2
  101. package/components/Timeline/Timeline.tsx +3 -2
  102. package/components/TimelineItem/TimelineItem.svelte +2 -1
  103. package/components/TimelineItem/TimelineItem.tsx +2 -1
  104. package/components/Toast/Toast.astro +3 -1
  105. package/components/Toast/Toast.svelte +3 -1
  106. package/components/Toast/Toast.tsx +3 -1
  107. package/icons/moon.svg +1 -1
  108. package/icons/search.svg +3 -0
  109. package/icons.d.ts +1 -0
  110. package/icons.js +1 -0
  111. package/index.d.ts +55 -25
  112. package/package.json +22 -4
  113. package/react.d.ts +6 -0
  114. package/react.js +6 -0
  115. package/scss/config/mixins.scss +12 -10
  116. package/scss/config/variables.scss +1 -0
  117. package/scss/config.scss +1 -0
  118. package/scss/global/utility.scss +2 -0
  119. package/svelte.d.ts +7 -1
  120. package/svelte.js +6 -0
  121. package/utils/cookies.ts +4 -4
  122. package/utils/debounce.ts +1 -1
  123. package/utils/event.ts +2 -2
  124. package/utils/interpolate.ts +5 -5
  125. package/utils/modal.ts +90 -27
  126. package/utils/popover.ts +30 -8
  127. package/utils/toast.ts +6 -2
@@ -1,54 +1,55 @@
1
- import React, { useState } from 'react'
2
- import type { ReactCollapsibleProps } from './collapsible'
3
-
4
- import styles from './collapsible.module.scss'
5
- import { classNames } from '../../utils/classNames'
6
-
7
- const Collapsible = ({
8
- initialHeight,
9
- maxHeight,
10
- toggled,
11
- on,
12
- off,
13
- children,
14
- className,
15
- togglesClassName
16
- }: ReactCollapsibleProps) => {
17
- const [toggle, setToggled] = useState(toggled)
18
-
19
- const classes = classNames([
20
- styles.collapsible,
21
- maxHeight && styles.animated,
22
- className
23
- ])
24
-
25
- const styleVariables = {
26
- ...(initialHeight && { '--w-collapsible-initial-height': initialHeight }),
27
- ...(maxHeight && { '--w-collapsible-max-height': maxHeight })
28
- } as React.CSSProperties
29
-
30
- return (
31
- <div
32
- className={classes}
33
- data-toggled={toggle ? 'true' : undefined}
34
- >
35
- <div
36
- className={styles.wrapper}
37
- style={styleVariables}
38
- >
39
- {children}
40
- </div>
41
- <div
42
- onClick={() => setToggled(!toggle)}
43
- onKeyUp={() => setToggled(!toggle)}
44
- role="button"
45
- tabIndex={0}
46
- className={togglesClassName}
47
- >
48
- {toggle ? off : on}
49
- </div>
50
- </div>
51
- )
52
- }
53
-
54
- export default Collapsible
1
+ import React, { useState } from 'react'
2
+ import type { ReactCollapsibleProps } from './collapsible'
3
+
4
+ import { classNames } from '../../utils/classNames'
5
+
6
+ import styles from './collapsible.module.scss'
7
+
8
+ const Collapsible = ({
9
+ initialHeight,
10
+ maxHeight,
11
+ toggled,
12
+ on,
13
+ off,
14
+ children,
15
+ className,
16
+ togglesClassName
17
+ }: ReactCollapsibleProps) => {
18
+ const [toggle, setToggled] = useState(toggled)
19
+
20
+ const classes = classNames([
21
+ styles.collapsible,
22
+ maxHeight && styles.animated,
23
+ className
24
+ ])
25
+
26
+ const styleVariables = {
27
+ ...(initialHeight && { '--w-collapsible-initial-height': initialHeight }),
28
+ ...(maxHeight && { '--w-collapsible-max-height': maxHeight })
29
+ } as React.CSSProperties
30
+
31
+ return (
32
+ <div
33
+ className={classes}
34
+ data-toggled={toggle ? 'true' : undefined}
35
+ >
36
+ <div
37
+ className={styles.wrapper}
38
+ style={styleVariables}
39
+ >
40
+ {children}
41
+ </div>
42
+ <div
43
+ onClick={() => setToggled(!toggle)}
44
+ onKeyUp={() => setToggled(!toggle)}
45
+ role="button"
46
+ tabIndex={0}
47
+ className={togglesClassName}
48
+ >
49
+ {toggle ? off : on}
50
+ </div>
51
+ </div>
52
+ )
53
+ }
54
+
55
+ export default Collapsible
@@ -10,7 +10,8 @@ const children = await Astro.slots.render('default')
10
10
  const wrapped = wrapper?.replace('children', children)
11
11
 
12
12
  if (!Astro.slots.has('wrapper')) {
13
- console.error('Missing wrapper. Add slot="wrapper" to one of the elements.')
13
+ // eslint-disable-next-line no-console
14
+ console.error('Missing wrapper. Add slot="wrapper" to one of the elements.')
14
15
  }
15
16
  ---
16
17
 
@@ -1,7 +1,6 @@
1
- import React from 'react'
2
1
  import type { ReactConditionalWrapperProps } from './conditionalwrapper'
3
2
 
4
3
  const ConditionalWrapper = ({ condition, wrapper, children }: ReactConditionalWrapperProps) =>
5
- condition ? wrapper(children) : children
4
+ condition ? wrapper(children) : children
6
5
 
7
6
  export default ConditionalWrapper
@@ -0,0 +1,22 @@
1
+ ---
2
+ import type { GroupProps } from './group'
3
+
4
+ import styles from './group.module.scss'
5
+
6
+ interface Props extends GroupProps {}
7
+
8
+ const {
9
+ withSeparator,
10
+ className
11
+ } = Astro.props
12
+
13
+ const classes = [
14
+ styles.group,
15
+ withSeparator && styles.separator,
16
+ className
17
+ ]
18
+ ---
19
+
20
+ <div class:list={classes}>
21
+ <slot />
22
+ </div>
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import type { GroupProps } from './group'
3
+
4
+ import { classNames } from '../../utils/classNames'
5
+
6
+ import styles from './group.module.scss'
7
+
8
+ export let withSeparator: GroupProps['withSeparator'] = false
9
+ export let className: GroupProps['className'] = ''
10
+
11
+ const classes = classNames([
12
+ styles.group,
13
+ withSeparator && styles.separator,
14
+ className
15
+ ])
16
+ </script>
17
+
18
+ <div class={classes}>
19
+ <slot />
20
+ </div>
@@ -0,0 +1,22 @@
1
+ import React from 'react'
2
+ import type { ReactGroupProps } from './group'
3
+
4
+ import { classNames } from '../../utils/classNames'
5
+
6
+ import styles from './group.module.scss'
7
+
8
+ const Group = ({
9
+ withSeparator,
10
+ className,
11
+ children
12
+ }: ReactGroupProps) => {
13
+ const classes = classNames([
14
+ styles.group,
15
+ withSeparator && styles.separator,
16
+ className
17
+ ])
18
+
19
+ return <div className={classes}>{children}</div>
20
+ }
21
+
22
+ export default Group
@@ -0,0 +1,43 @@
1
+ @import '../../scss/config.scss';
2
+
3
+ .group {
4
+ @include layout(flex, none);
5
+ @include visibility(auto);
6
+
7
+ button,
8
+ span {
9
+ @include border-radius(none);
10
+
11
+ &:first-child {
12
+ @include border-radius(left, md);
13
+ }
14
+
15
+ &:last-child {
16
+ @include border-radius(right, md);
17
+ }
18
+ }
19
+
20
+ &.separator button:not(:last-child),
21
+ &.separator span:not(:last-child) {
22
+ @include border(1px, right, primary-70);
23
+ }
24
+
25
+ &.outline button
26
+ &.outline span {
27
+ @include border(1px, primary-20);
28
+ box-shadow: none;
29
+
30
+ &:hover {
31
+ @include border(1px, primary);
32
+ box-shadow: none;
33
+ }
34
+
35
+ &:first-child {
36
+ @include border(right, 0);
37
+ }
38
+
39
+ &:last-child {
40
+ @include border(left, 0);
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,8 @@
1
+ export type GroupProps = {
2
+ withSeparator?: boolean
3
+ className?: string
4
+ }
5
+
6
+ export type ReactGroupProps = {
7
+ children: React.ReactNode
8
+ } & GroupProps
@@ -6,6 +6,7 @@ import Close from '../../icons/close.svg?raw'
6
6
  import Github from '../../icons/github.svg?raw'
7
7
  import Info from '../../icons/info.svg?raw'
8
8
  import Moon from '../../icons/moon.svg?raw'
9
+ import Search from '../../icons/search.svg?raw'
9
10
  import Sun from '../../icons/sun.svg?raw'
10
11
  import Warning from '../../icons/warning.svg?raw'
11
12
 
@@ -18,6 +19,7 @@ const iconMap = {
18
19
  'github': Github,
19
20
  'info': Info,
20
21
  'moon': Moon,
22
+ 'search': Search,
21
23
  'sun': Sun,
22
24
  'warning': Warning
23
25
  }
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  import type { InputProps } from './input'
3
+
3
4
  import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.astro'
4
5
 
5
6
  import styles from './input.module.scss'
@@ -12,6 +13,7 @@ const {
12
13
  label,
13
14
  subText,
14
15
  className,
16
+ labelClassName,
15
17
  ...rest
16
18
  } = Astro.props
17
19
 
@@ -21,11 +23,16 @@ const classes = [
21
23
  className
22
24
  ]
23
25
 
26
+ const labelClasses = [
27
+ styles['input-label'],
28
+ labelClassName
29
+ ]
30
+
24
31
  const useLabel = !!(label || subText || Astro.slots.has('default'))
25
32
  ---
26
33
 
27
34
  <ConditionalWrapper condition={useLabel}>
28
- <label slot="wrapper" class={styles['input-label']}>
35
+ <label slot="wrapper" class:list={labelClasses}>
29
36
  {label && (
30
37
  <div class={styles.label}>{label}</div>
31
38
  )}
@@ -1,17 +1,22 @@
1
1
  <script lang="ts">
2
2
  import type { SvelteInputProps } from './input'
3
+
3
4
  import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.svelte'
4
5
 
5
- import styles from './input.module.scss'
6
6
  import { classNames } from '../../utils/classNames'
7
7
 
8
+ import styles from './input.module.scss'
9
+
8
10
  export let type: SvelteInputProps['type'] = 'text'
9
11
  export let theme: SvelteInputProps['theme'] = null
10
12
  export let label: SvelteInputProps['label'] = ''
11
13
  export let subText: SvelteInputProps['subText'] = ''
12
14
  export let className: SvelteInputProps['className'] = ''
15
+ export let labelClassName: SvelteInputProps['labelClassName'] = ''
13
16
  export let onChange: SvelteInputProps['onChange'] = () => {}
14
17
  export let onKeyUp: SvelteInputProps['onKeyUp'] = () => {}
18
+ export let onInput: SvelteInputProps['onInput'] = () => {}
19
+ export let onClick: SvelteInputProps['onClick'] = () => {}
15
20
 
16
21
  const classes = classNames([
17
22
  styles.input,
@@ -19,13 +24,18 @@
19
24
  className
20
25
  ])
21
26
 
27
+ const labelClasses = classNames([
28
+ styles['input-label'],
29
+ labelClassName
30
+ ])
31
+
22
32
  const useLabel = !!(label || subText || $$slots.default)
23
33
  </script>
24
34
 
25
35
  <ConditionalWrapper
26
36
  condition={useLabel}
27
37
  element="label"
28
- class={styles['input-label']}
38
+ class={labelClasses}
29
39
  >
30
40
  {#if label}
31
41
  <div class={styles.label}>{label}</div>
@@ -41,10 +51,12 @@
41
51
  class={classes}
42
52
  on:change={onChange}
43
53
  on:keyup={onKeyUp}
54
+ on:input={onInput}
55
+ on:click={onClick}
44
56
  {...$$restProps}
45
57
  />
46
58
  </ConditionalWrapper>
47
- {#if label}
59
+ {#if subText}
48
60
  <div class={styles.subtext}>
49
61
  {@html subText}
50
62
  </div>
@@ -1,18 +1,20 @@
1
1
  import React from 'react'
2
2
  import type { ReactInputProps } from './input'
3
+
3
4
  import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.tsx'
4
5
 
5
- import styles from './input.module.scss'
6
6
  import { classNames } from '../../utils/classNames'
7
7
 
8
+ import styles from './input.module.scss'
9
+
8
10
  const Input = ({
9
11
  type = 'text',
10
12
  theme,
11
13
  label,
12
14
  subText,
13
- icon,
14
15
  value,
15
16
  className,
17
+ labelClassName,
16
18
  children,
17
19
  ...rest
18
20
  }: ReactInputProps) => {
@@ -22,11 +24,16 @@ const Input = ({
22
24
  className
23
25
  ])
24
26
 
27
+ const labelClasses = classNames([
28
+ styles['input-label'],
29
+ labelClassName
30
+ ])
31
+
25
32
  const useLabel = !!(label || subText || children)
26
33
 
27
34
  return (
28
35
  <ConditionalWrapper condition={useLabel} wrapper={children => (
29
- <label className={styles['input-label']}>
36
+ <label className={labelClasses}>
30
37
  {children}
31
38
  </label>
32
39
  )}>
@@ -68,7 +68,10 @@
68
68
 
69
69
  svg {
70
70
  @include position(absolute, l10px);
71
- @include size(20px);
71
+ @include size(18px);
72
+ @include typography(primary-30);
73
+
74
+ pointer-events: none;
72
75
  }
73
76
  }
74
77
 
@@ -35,16 +35,21 @@ export type InputProps = {
35
35
  autofocus?: boolean
36
36
  autocomplete?: 'on' | 'off'
37
37
  className?: string
38
+ labelClassName?: string
38
39
  [key: string]: any
39
40
  }
40
41
 
41
42
  export type SvelteInputProps = {
42
- onChange?: (e: any) => any
43
- onKeyUp?: (e: any) => any
43
+ onChange?: (event: Event & { currentTarget: HTMLInputElement }) => void
44
+ onKeyUp?: (event: KeyboardEvent & { currentTarget: HTMLInputElement }) => void
45
+ onInput?: (event: any) => void
46
+ onClick?: (event: MouseEvent & { currentTarget: HTMLInputElement }) => void
44
47
  } & InputProps
45
48
 
46
49
  export type ReactInputProps = {
47
- onChange?: (e: any) => any
48
- onKeyUp?: (e: any) => any
50
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
51
+ onKeyUp?: (event: React.KeyboardEvent<HTMLInputElement>) => void
52
+ onInput?: (event: React.FormEvent<HTMLInputElement>) => void
53
+ onClick?: (event: React.MouseEvent<HTMLInputElement>) => void
49
54
  children?: React.ReactNode
50
55
  } & InputProps
@@ -0,0 +1,169 @@
1
+ ---
2
+ import type { ListProps } from './list'
3
+
4
+ import ConditionalWrapper from '../ConditionalWrapper/ConditionalWrapper.astro'
5
+ import Input from '../Input/Input.astro'
6
+
7
+ import searchIcon from '../../icons/search.svg?raw'
8
+
9
+ import styles from './list.module.scss'
10
+
11
+ interface Props extends ListProps {}
12
+
13
+ const {
14
+ showSearchBar,
15
+ showSearchBarIcon,
16
+ searchBarPlaceholder,
17
+ noResultsLabel = 'No results.',
18
+ maxHeight,
19
+ id,
20
+ className,
21
+ wrapperClassName,
22
+ itemGroups
23
+ } = Astro.props
24
+
25
+ const classes = [
26
+ styles.list,
27
+ !showSearchBar && styles.container,
28
+ className
29
+ ]
30
+
31
+ const wrapperClasses = [
32
+ styles.container,
33
+ wrapperClassName
34
+ ]
35
+ ---
36
+
37
+ <ConditionalWrapper condition={!!showSearchBar}>
38
+ <div slot="wrapper" class:list={wrapperClasses} data-id="w-list-wrapper">
39
+ <Input
40
+ type="search"
41
+ placeholder={searchBarPlaceholder}
42
+ data-id="w-list-search"
43
+ >
44
+ <Fragment
45
+ set:html={searchIcon}
46
+ slot={showSearchBarIcon ? 'default' : null}
47
+ />
48
+ </Input>
49
+ children
50
+ </div>
51
+ <ul class:list={classes} id={id} data-id="w-list" style={maxHeight && `max-height: ${maxHeight}`}>
52
+ {itemGroups.map((group: ListProps['itemGroups'][0]) => (
53
+ <Fragment>
54
+ {group.title && (
55
+ <li class={styles.title} data-id="w-list-title">
56
+ {group.title}
57
+ </li>
58
+ )}
59
+ {group.items.map(item => (
60
+ <li
61
+ tabindex={item.href || item.disabled ? undefined : 0}
62
+ data-value={item.value}
63
+ data-name={item.name}
64
+ data-disabled={item.disabled ? 'true' : undefined}
65
+ data-selected={item.selected}
66
+ >
67
+ <ConditionalWrapper condition={!!item.href}>
68
+ <a
69
+ slot="wrapper"
70
+ href={item.href}
71
+ target={item.target}
72
+ >
73
+ children
74
+ </a>
75
+
76
+ <ConditionalWrapper condition={!!(item.icon && item.subText)}>
77
+ <div slot="wrapper">children</div>
78
+ {item.icon && <Fragment set:html={item.icon} />}
79
+ {item.name}
80
+ </ConditionalWrapper>
81
+ {item.subText && <span>{item.subText}</span>}
82
+ </ConditionalWrapper>
83
+ </li>
84
+ ))}
85
+ </Fragment>
86
+ ))}
87
+ {showSearchBar && (
88
+ <li data-id="w-no-results" data-hidden>{noResultsLabel}</li>
89
+ )}
90
+ </ul>
91
+ </ConditionalWrapper>
92
+
93
+ <script>
94
+ import { dispatch } from '../../utils/event'
95
+
96
+ const lists = document.querySelectorAll('[data-id="w-list"]')
97
+ const searchInputs = document.querySelectorAll('[data-id="w-list-search"]')
98
+
99
+ const handleClick = (list: Element, items: Element[], event: Event) => {
100
+ const target = event.target as HTMLElement
101
+
102
+ if (target.dataset.value && !target.dataset.disabled) {
103
+ dispatch('listOnSelect', {
104
+ value: target.dataset.value,
105
+ name: target.dataset.name,
106
+ list
107
+ })
108
+
109
+ items.forEach(item => item.removeAttribute('data-selected'))
110
+ target.dataset.selected = 'true'
111
+ }
112
+ }
113
+
114
+ Array.from(lists).forEach(list => {
115
+ const items = Array.from(list.children)
116
+
117
+ list.addEventListener('click', event => handleClick(list, items, event))
118
+ list.addEventListener('keyup', event => {
119
+ if ((event as KeyboardEvent).key === 'Enter') {
120
+ handleClick(list, items, event)
121
+ }
122
+ })
123
+ })
124
+
125
+ Array.from(searchInputs).forEach(element => {
126
+ element.addEventListener('input', event => {
127
+ const target = event.target as HTMLInputElement
128
+ const ul = target.closest('[data-id="w-list-wrapper"]')
129
+ ?.querySelector('ul') as HTMLUListElement
130
+
131
+ const noResults = ul.querySelector('[data-id="w-no-results"]')
132
+ const items = Array.from(ul.children)
133
+ const value = target.value.toLowerCase()
134
+
135
+ items.forEach(item => {
136
+ const li = item as HTMLLIElement
137
+ const hideItem = (!li.dataset.value?.toLowerCase().includes(value)
138
+ && !li.innerText.toLowerCase().includes(value))
139
+ || li.dataset.id === 'w-list-title'
140
+ || li.dataset.id === 'w-no-results'
141
+
142
+ if (hideItem) {
143
+ li.dataset.hidden = 'true'
144
+ } else if (li.dataset.id !== 'w-no-results') {
145
+ li.removeAttribute('data-hidden')
146
+ }
147
+ })
148
+
149
+ const numberOfResults = items.filter(item => {
150
+ const li = item as HTMLLIElement
151
+ return li.dataset.name && !li.dataset.hidden
152
+ }).length
153
+
154
+ if (!numberOfResults) {
155
+ noResults?.removeAttribute('data-hidden')
156
+ }
157
+
158
+ if (!value) {
159
+ items.forEach(item => {
160
+ const li = item as HTMLLIElement
161
+
162
+ li.dataset.id === 'w-no-results'
163
+ ? li.dataset.hidden = 'true'
164
+ : li.removeAttribute('data-hidden')
165
+ })
166
+ }
167
+ })
168
+ })
169
+ </script>